@stacksjs/ts-cloud 0.16.38 → 0.16.40

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 (204) hide show
  1. package/dist/aws/bedrock.d.ts +110 -9
  2. package/dist/aws/index.js +1 -1
  3. package/dist/bin/chunk-0716rh6x.js +1 -0
  4. package/dist/bin/{chunk-dnmb3sr0.js → chunk-0scywedn.js} +1 -1
  5. package/dist/bin/{chunk-48nz63ab.js → chunk-1dqn0y04.js} +3 -3
  6. package/dist/bin/{chunk-q8hp4dfy.js → chunk-1jwmkbzx.js} +94 -94
  7. package/dist/bin/{chunk-4bp4k1x2.js → chunk-22x7vxxw.js} +2 -2
  8. package/dist/bin/{chunk-r0yapyqc.js → chunk-35x7z78g.js} +1 -1
  9. package/dist/bin/chunk-459waehf.js +1 -0
  10. package/dist/bin/chunk-45a8yv3j.js +6 -0
  11. package/dist/bin/{chunk-cqhtnsby.js → chunk-4g1z81pt.js} +5 -5
  12. package/dist/bin/chunk-4y8zhe38.js +1 -0
  13. package/dist/bin/{chunk-55cckkb2.js → chunk-4yym8xm4.js} +5 -5
  14. package/dist/bin/{chunk-ygsdntxq.js → chunk-5k3npcm6.js} +5 -5
  15. package/dist/bin/chunk-5khcwxhn.js +1 -0
  16. package/dist/bin/{chunk-zmp0mksb.js → chunk-5nmt4s5w.js} +2 -2
  17. package/dist/bin/{chunk-8zn63v9h.js → chunk-5wx26yjy.js} +3 -3
  18. package/dist/bin/chunk-68tgx5j2.js +1 -0
  19. package/dist/bin/chunk-7453cepa.js +1 -0
  20. package/dist/bin/{chunk-0ynfqf9t.js → chunk-7593hjcq.js} +1 -1
  21. package/dist/bin/{chunk-wga7gj0h.js → chunk-7p2va3nj.js} +1 -1
  22. package/dist/bin/{chunk-hjq05rxh.js → chunk-8fxksvw4.js} +5 -5
  23. package/dist/bin/{chunk-sqmays54.js → chunk-9eqpnanr.js} +1 -1
  24. package/dist/bin/{chunk-0c1fv0xt.js → chunk-9vszh4dj.js} +5 -5
  25. package/dist/bin/chunk-az504aqf.js +1 -0
  26. package/dist/bin/{chunk-5wqjqh6c.js → chunk-b2kdxqd5.js} +23 -23
  27. package/dist/bin/chunk-bb08ms5q.js +1 -0
  28. package/dist/bin/{chunk-pyr0dc6j.js → chunk-bmj1d9xc.js} +63 -63
  29. package/dist/bin/chunk-cxcgqqdb.js +1 -0
  30. package/dist/bin/{chunk-dmwfnbg0.js → chunk-dkf2kcsc.js} +6 -6
  31. package/dist/bin/chunk-ecd4swb7.js +2 -0
  32. package/dist/bin/{chunk-d8x60kvn.js → chunk-f2q239cy.js} +2 -2
  33. package/dist/bin/{chunk-gc8p1tdr.js → chunk-f64jvh96.js} +2 -2
  34. package/dist/bin/{chunk-c7z8et78.js → chunk-fkzp9sg5.js} +1 -1
  35. package/dist/bin/chunk-h0s69e9p.js +1 -0
  36. package/dist/bin/{chunk-85k5gvnc.js → chunk-jmkfx9th.js} +3 -3
  37. package/dist/bin/chunk-jrztbsnb.js +1 -0
  38. package/dist/bin/chunk-js888a3w.js +1 -0
  39. package/dist/bin/chunk-jv9qp13h.js +1 -0
  40. package/dist/bin/chunk-jxfgkhkc.js +1 -0
  41. package/dist/bin/chunk-k2mdcb66.js +1 -0
  42. package/dist/bin/{chunk-mbr9j2fw.js → chunk-k343q24p.js} +6 -6
  43. package/dist/bin/chunk-k9ate69x.js +1 -0
  44. package/dist/bin/chunk-kbwm0sqv.js +2 -0
  45. package/dist/bin/chunk-kva8aybv.js +1 -0
  46. package/dist/bin/{chunk-x0ywfbk5.js → chunk-kzpzkdpd.js} +1 -1
  47. package/dist/bin/chunk-m8p7mw67.js +1 -0
  48. package/dist/bin/{chunk-6r5mehaj.js → chunk-mex7tac5.js} +4 -4
  49. package/dist/bin/chunk-mh3rgn0e.js +1 -0
  50. package/dist/bin/{chunk-07qwk0sj.js → chunk-n7yefy09.js} +5 -5
  51. package/dist/bin/{chunk-7rpj0qhb.js → chunk-nj9x0tb8.js} +2 -2
  52. package/dist/bin/{chunk-tt3m3fda.js → chunk-nmqjmx30.js} +22 -22
  53. package/dist/bin/{chunk-8496fsmq.js → chunk-nqn983fx.js} +104 -104
  54. package/dist/bin/chunk-p9baztvr.js +1 -0
  55. package/dist/bin/{chunk-aykdp1wv.js → chunk-pj5svs6q.js} +2 -2
  56. package/dist/bin/{chunk-qxg95ndf.js → chunk-q40k9jvk.js} +2 -2
  57. package/dist/bin/chunk-qgqgdkg0.js +1 -0
  58. package/dist/bin/chunk-s77kny9g.js +1 -0
  59. package/dist/bin/{chunk-4h60xsat.js → chunk-sfzdr2b3.js} +3 -3
  60. package/dist/bin/chunk-t5kqyr8m.js +1 -0
  61. package/dist/bin/{chunk-e0kapeev.js → chunk-v9wf266f.js} +14 -14
  62. package/dist/bin/chunk-w232tc20.js +1 -0
  63. package/dist/bin/chunk-w9rx90s2.js +1 -0
  64. package/dist/bin/{chunk-w6yx9bhb.js → chunk-zvbc92pc.js} +1 -1
  65. package/dist/bin/cli.js +173 -173
  66. package/dist/bin/dashboard-server.js +1 -1
  67. package/dist/{chunk-yrcv3hrj.js → chunk-0evxayn1.js} +7 -7
  68. package/dist/chunk-1yhrkahz.js +1 -0
  69. package/dist/chunk-27y037yh.js +1 -0
  70. package/dist/chunk-2ns1w1fe.js +1 -0
  71. package/dist/chunk-2vrv31sk.js +37 -0
  72. package/dist/{chunk-n1r9313b.js → chunk-3s8dtcz8.js} +2 -2
  73. package/dist/chunk-3w7q4sjs.js +2 -0
  74. package/dist/{chunk-tbn385ak.js → chunk-5n1y5ehd.js} +94 -94
  75. package/dist/chunk-74yycwrd.js +1 -0
  76. package/dist/{chunk-t52wetq8.js → chunk-7eaech9q.js} +1 -1
  77. package/dist/{chunk-2n4ktft4.js → chunk-97gre81w.js} +1 -1
  78. package/dist/{chunk-zvyrpmvd.js → chunk-9e4afej1.js} +1 -1
  79. package/dist/{chunk-3cyszqzh.js → chunk-9mv07nz0.js} +2 -2
  80. package/dist/{chunk-t80x808z.js → chunk-bez9ytaz.js} +108 -108
  81. package/dist/{chunk-kpjhfgbh.js → chunk-bfbahave.js} +4 -4
  82. package/dist/{chunk-xr7ew64s.js → chunk-bwtxb2hf.js} +3 -3
  83. package/dist/{chunk-dg834141.js → chunk-cgcthvq9.js} +5 -5
  84. package/dist/chunk-e9z4gzmg.js +1 -0
  85. package/dist/{chunk-ffba3270.js → chunk-jbtnyhrh.js} +2 -2
  86. package/dist/{chunk-gcqq9m4b.js → chunk-kexwq2h0.js} +4 -4
  87. package/dist/{chunk-p4rknh9f.js → chunk-mxprxjd4.js} +1 -1
  88. package/dist/{chunk-c45ay9fx.js → chunk-my61jkg1.js} +5 -5
  89. package/dist/{chunk-kkeb1dk1.js → chunk-qbbap3bt.js} +1 -1
  90. package/dist/{chunk-jsnhb1p4.js → chunk-qg03hfb6.js} +19 -19
  91. package/dist/{chunk-bx3jmgd0.js → chunk-r3m1fjd4.js} +2 -2
  92. package/dist/{chunk-nzmangkw.js → chunk-v6hysd5c.js} +5 -5
  93. package/dist/{chunk-kyn6a4zf.js → chunk-varjr6np.js} +1 -1
  94. package/dist/chunk-vd2jqt9w.js +1 -0
  95. package/dist/{chunk-n8g8t8hf.js → chunk-w78e5n94.js} +3 -3
  96. package/dist/{chunk-q08s698e.js → chunk-yjh3y68t.js} +71 -71
  97. package/dist/{chunk-ej9dqt2r.js → chunk-ype3pqh5.js} +5 -5
  98. package/dist/{chunk-j1aq97br.js → chunk-ysx5m6cs.js} +2 -2
  99. package/dist/{chunk-qhtgfjhd.js → chunk-yt6m703r.js} +23 -23
  100. package/dist/deploy/index.js +1 -1
  101. package/dist/dns/index.js +1 -1
  102. package/dist/drivers/index.js +1 -1
  103. package/dist/index.d.ts +1 -0
  104. package/dist/index.js +42 -42
  105. package/dist/operations/index.js +1 -1
  106. package/dist/protection/index.js +1 -1
  107. package/dist/r2/index.d.ts +8 -0
  108. package/dist/r2/provider.d.ts +303 -0
  109. package/dist/r2/provider.test.d.ts +1 -0
  110. package/dist/r2/reconcile.d.ts +98 -0
  111. package/dist/r2/reconcile.test.d.ts +1 -0
  112. package/dist/r2/test-fetch.d.ts +32 -0
  113. package/dist/spend/index.js +1 -1
  114. package/dist/ui/404.html +1 -1
  115. package/dist/ui/accept-invitation.html +1 -1
  116. package/dist/ui/access-denied.html +1 -1
  117. package/dist/ui/account/automation.html +6 -6
  118. package/dist/ui/account/security.html +2 -2
  119. package/dist/ui/applications/compose.html +6 -6
  120. package/dist/ui/applications/new.html +2 -2
  121. package/dist/ui/data/backups.html +6 -6
  122. package/dist/ui/data/services.html +6 -6
  123. package/dist/ui/data/volumes.html +6 -6
  124. package/dist/ui/index.html +6 -6
  125. package/dist/ui/infrastructure/topology.html +6 -6
  126. package/dist/ui/integrations.html +1 -1
  127. package/dist/ui/operations/alerts.html +6 -6
  128. package/dist/ui/operations/configuration.html +6 -6
  129. package/dist/ui/operations/jobs.html +5 -5
  130. package/dist/ui/operations/maintenance.html +6 -6
  131. package/dist/ui/operations/observability.html +5 -5
  132. package/dist/ui/operations/previews.html +6 -6
  133. package/dist/ui/operations/queue.html +6 -6
  134. package/dist/ui/operations/regions.html +6 -6
  135. package/dist/ui/operations/releases.html +6 -6
  136. package/dist/ui/operations/spend.html +5 -5
  137. package/dist/ui/operations/workloads.html +6 -6
  138. package/dist/ui/security.html +1 -1
  139. package/dist/ui/server/actions.html +6 -6
  140. package/dist/ui/server/activity.html +2 -2
  141. package/dist/ui/server/capacity.html +5 -5
  142. package/dist/ui/server/database.html +5 -5
  143. package/dist/ui/server/deployments.html +6 -6
  144. package/dist/ui/server/diagnostics.html +2 -2
  145. package/dist/ui/server/firewall.html +6 -6
  146. package/dist/ui/server/fleet.html +6 -6
  147. package/dist/ui/server/logs.html +6 -6
  148. package/dist/ui/server/metrics.html +6 -6
  149. package/dist/ui/server/security.html +2 -2
  150. package/dist/ui/server/services.html +2 -2
  151. package/dist/ui/server/sites.html +6 -6
  152. package/dist/ui/server/ssh-keys.html +6 -6
  153. package/dist/ui/server/team.html +6 -6
  154. package/dist/ui/server/terminal.html +2 -2
  155. package/dist/ui/serverless/alarms.html +6 -6
  156. package/dist/ui/serverless/assets.html +2 -2
  157. package/dist/ui/serverless/cost.html +2 -2
  158. package/dist/ui/serverless/data.html +6 -6
  159. package/dist/ui/serverless/deployments.html +2 -2
  160. package/dist/ui/serverless/firewall.html +1 -1
  161. package/dist/ui/serverless/functions.html +6 -6
  162. package/dist/ui/serverless/logs.html +6 -6
  163. package/dist/ui/serverless/metrics.html +2 -2
  164. package/dist/ui/serverless/queues.html +6 -6
  165. package/dist/ui/serverless/secrets.html +6 -6
  166. package/dist/ui/serverless/traces.html +6 -6
  167. package/dist/ui/serverless.html +5 -5
  168. package/package.json +3 -3
  169. package/dist/bin/chunk-0c5vn8rp.js +0 -1
  170. package/dist/bin/chunk-1wf1s8db.js +0 -1
  171. package/dist/bin/chunk-4dtrry0t.js +0 -1
  172. package/dist/bin/chunk-6kcxf3b2.js +0 -1
  173. package/dist/bin/chunk-6ksbfg6t.js +0 -1
  174. package/dist/bin/chunk-7rkg1yph.js +0 -1
  175. package/dist/bin/chunk-989j6ezd.js +0 -1
  176. package/dist/bin/chunk-bgdvhp6m.js +0 -1
  177. package/dist/bin/chunk-cvc9bxd4.js +0 -2
  178. package/dist/bin/chunk-czzrfhn7.js +0 -1
  179. package/dist/bin/chunk-d5arnf2f.js +0 -1
  180. package/dist/bin/chunk-e06m9m6z.js +0 -1
  181. package/dist/bin/chunk-e51ajfyr.js +0 -1
  182. package/dist/bin/chunk-e6mfcw0v.js +0 -6
  183. package/dist/bin/chunk-fh5bjm3d.js +0 -1
  184. package/dist/bin/chunk-fw6hbyeg.js +0 -1
  185. package/dist/bin/chunk-h7gfd2yq.js +0 -1
  186. package/dist/bin/chunk-jxnw879g.js +0 -1
  187. package/dist/bin/chunk-k3yq569a.js +0 -1
  188. package/dist/bin/chunk-nhrwct94.js +0 -1
  189. package/dist/bin/chunk-pa4fymr0.js +0 -1
  190. package/dist/bin/chunk-s9xven24.js +0 -1
  191. package/dist/bin/chunk-w8jfw39t.js +0 -2
  192. package/dist/bin/chunk-wgv9nv0z.js +0 -1
  193. package/dist/bin/chunk-y5980ycr.js +0 -1
  194. package/dist/bin/chunk-y5ez6ba7.js +0 -1
  195. package/dist/bin/chunk-ya71t2ed.js +0 -1
  196. package/dist/bin/chunk-zb1nh252.js +0 -1
  197. package/dist/chunk-1ty76ybd.js +0 -1
  198. package/dist/chunk-2mypcz4a.js +0 -1
  199. package/dist/chunk-5vk7nss8.js +0 -2
  200. package/dist/chunk-fe5sbczg.js +0 -1
  201. package/dist/chunk-gtc1gvfj.js +0 -1
  202. package/dist/chunk-j5t1amn0.js +0 -1
  203. package/dist/chunk-s20830hg.js +0 -1
  204. package/dist/chunk-v83qx041.js +0 -37
@@ -1,14 +1,14 @@
1
- import{Y,Ko,Pt,Tn}from"./chunk-55cckkb2.js";import{Xt,Lr}from"./chunk-qxg95ndf.js";var dm={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}},um={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 dt,join as Ke,relative as cr}from"node:path";var Zs=".ts-cloud",Wc="TS_CLOUD_STATE_DIR",mt=null;function ea(e){mt=e?.trim()||null}function ta(){return Boolean(process.env[Wc]?.trim()||mt)}function gn(){return process.env[Wc]?.trim()||mt||Zs}function Ue(...e){return Ke(gn(),...e)}function A(e,...n){let r=gn();return dt(r)?Ke(r,...n):Ke(e,r,...n)}function ra(e,n=process.cwd()){let r=(s,a)=>{let c=cr(s,a);return c===""||!c.startsWith("..")&&!dt(c)},i=dt(e)?e:Ke(n,e);return r(A(n),i)}function Kc(e){let n=e.infrastructure?.compute!=null,r=Object.values(e.environments??{}).some((i)=>i?.app!=null);return{server:n,serverless:r}}function H(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:n}=Kc(e);return n?"serverless":"server"}function xr(e){let{server:n,serverless:r}=Kc(e);if(n&&r)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(e.mode==="server"&&r&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&n&&!r)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function w(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function lr(e){return typeof e==="object"&&e!==null?e:{}}function Kd(e){return e===!0||typeof e==="object"&&e!==null}function ur(e,n){let r=n?e.environments?.[n]:void 0;if(r?.domain)return r.domain;let i=Object.values(e.sites??{}),s=e.sites?.main?.domain??i.find((a)=>a.domain)?.domain;if(s)return s;return`${e.project?.slug??"app"}.local`}function dr(e){let n=e.indexOf(".");return n>0?e.slice(n+1):void 0}function Ri(e,n={}){let r=e.infrastructure?.compute?.managedServices?.mail,i=lr(r),s=n.environmentType??(n.environment?e.environments?.[n.environment]?.type:void 0),a=i.mode??(s==="production"?"server":"catcher"),c=a==="server",u=ur(e,n.environment),d=i.hostname??(c?`mail.${u}`:"localhost"),m=i.ports??{},p=c?{smtp:m.smtp??25,submission:m.submission??587,submissions:m.submissions??465,imap:m.imap??143,imaps:m.imaps??993,webmail:m.webmail??8080,managesieve:m.managesieve}:{smtp:m.smtp??1025,submission:m.submission,submissions:m.submissions,imap:m.imap,imaps:m.imaps,webmail:m.webmail??8025,managesieve:m.managesieve},g=i.tls??{},y=g.enabled??c,h=!!(g.certPath&&g.keyPath),f=(i.accounts??[]).map((M)=>({address:M.address,password:M.password})),S=typeof i.dkim==="object"&&i.dkim!==null?i.dkim:{},C=i.dkim===!1?!1:i.dkim===!0||c,P=typeof i.webmail==="object"&&i.webmail!==null?i.webmail:{},E=i.webmail===!1?!1:P.enabled??!0,v=i.spam??{},I=i.delivery??(c?"direct":"none"),D=i.expose??c,x=dr(d),F=[...new Set([d,...x?[x]:[],...i.domains??[]])];return{enabled:Kd(r),mode:a,version:i.version,hostname:d,domains:F,ports:p,tls:{enabled:y,acme:y&&!h&&(g.acme??!0),certPath:g.certPath,keyPath:g.keyPath,requireForAuth:g.requireForAuth??(y&&c),acmeEmail:g.acmeEmail??f[0]?.address},dkim:{enabled:C,selector:S.selector??"default",rotate:S.rotate??!1,rotateIntervalDays:S.rotateIntervalDays??90},webmail:{enabled:E,port:P.port??p.webmail,domain:P.domain},delivery:I,sesRegion:i.sesRegion??"us-east-1",accounts:f,storagePath:i.storagePath??"/var/lib/mail",maxMessageSize:i.maxMessageSize??26214400,spam:{enabled:v.enabled??c,enforce:v.enforce??!1,junkScore:v.junkScore??5,rejectScore:v.rejectScore??12,dnsbl:v.dnsbl??c,greylist:v.greylist??!1},webhookUrl:i.webhookUrl,expose:D,bindAddress:D?"0.0.0.0":"127.0.0.1"}}function na(e){if(!e.enabled||!e.expose)return[];let n=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((r)=>typeof r==="number");if(e.webmail.enabled&&!e.webmail.domain)n.push(e.webmail.port);return[...new Set(n)].sort((r,i)=>r-i)}function ia(e){if(!e.enabled)return{};let n=e.ports.submission??e.ports.smtp,r={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(e.mode==="server"){r.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let i=e.accounts[0];if(i)r.MAIL_USERNAME=i.address,r.MAIL_PASSWORD=i.password}else r.MAIL_ENCRYPTION="null",r.MAIL_USERNAME="null",r.MAIL_PASSWORD="null";return r}function B(e){if(e.cloud?.provider)return e.cloud.provider;if(e.ssh?.hosts?.length)return"ssh";if(e.hetzner?.apiToken)return"hetzner";return"aws"}class Lo{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,n){return this.template.Resources[e]=n,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=n,this}addOutput(e,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=n,this}addMetadata(e,n){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[e]=n,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,n=0){let r=" ".repeat(n),i="";for(let[s,a]of Object.entries(e)){if(a===null||a===void 0)continue;if(typeof a==="object"&&!Array.isArray(a))i+=`${r}${s}:
1
+ import{Y,Yo,Pt,An}from"./chunk-4yym8xm4.js";import{Xt,Br}from"./chunk-q40k9jvk.js";var gm={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}},fm={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 dt,join as Ke,relative as cr}from"node:path";var na=".ts-cloud",Qc="TS_CLOUD_STATE_DIR",mt=null;function ia(e){mt=e?.trim()||null}function oa(){return Boolean(process.env[Qc]?.trim()||mt)}function yn(){return process.env[Qc]?.trim()||mt||na}function Be(...e){return Ke(yn(),...e)}function A(e,...n){let r=yn();return dt(r)?Ke(r,...n):Ke(e,r,...n)}function sa(e,n=process.cwd()){let r=(s,a)=>{let c=cr(s,a);return c===""||!c.startsWith("..")&&!dt(c)},i=dt(e)?e:Ke(n,e);return r(A(n),i)}function Yc(e){let n=e.infrastructure?.compute!=null,r=Object.values(e.environments??{}).some((i)=>i?.app!=null);return{server:n,serverless:r}}function H(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:n}=Yc(e);return n?"serverless":"server"}function $r(e){let{server:n,serverless:r}=Yc(e);if(n&&r)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(e.mode==="server"&&r&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&n&&!r)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function w(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function lr(e){return typeof e==="object"&&e!==null?e:{}}function Yd(e){return e===!0||typeof e==="object"&&e!==null}function ur(e,n){let r=n?e.environments?.[n]:void 0;if(r?.domain)return r.domain;let i=Object.values(e.sites??{}),s=e.sites?.main?.domain??i.find((a)=>a.domain)?.domain;if(s)return s;return`${e.project?.slug??"app"}.local`}function dr(e){let n=e.indexOf(".");return n>0?e.slice(n+1):void 0}function ki(e,n={}){let r=e.infrastructure?.compute?.managedServices?.mail,i=lr(r),s=n.environmentType??(n.environment?e.environments?.[n.environment]?.type:void 0),a=i.mode??(s==="production"?"server":"catcher"),c=a==="server",u=ur(e,n.environment),d=i.hostname??(c?`mail.${u}`:"localhost"),m=i.ports??{},p=c?{smtp:m.smtp??25,submission:m.submission??587,submissions:m.submissions??465,imap:m.imap??143,imaps:m.imaps??993,webmail:m.webmail??8080,managesieve:m.managesieve}:{smtp:m.smtp??1025,submission:m.submission,submissions:m.submissions,imap:m.imap,imaps:m.imaps,webmail:m.webmail??8025,managesieve:m.managesieve},g=i.tls??{},y=g.enabled??c,h=!!(g.certPath&&g.keyPath),f=(i.accounts??[]).map((M)=>({address:M.address,password:M.password})),S=typeof i.dkim==="object"&&i.dkim!==null?i.dkim:{},C=i.dkim===!1?!1:i.dkim===!0||c,P=typeof i.webmail==="object"&&i.webmail!==null?i.webmail:{},E=i.webmail===!1?!1:P.enabled??!0,v=i.spam??{},I=i.delivery??(c?"direct":"none"),D=i.expose??c,N=dr(d),B=[...new Set([d,...N?[N]:[],...i.domains??[]])];return{enabled:Yd(r),mode:a,version:i.version,hostname:d,domains:B,ports:p,tls:{enabled:y,acme:y&&!h&&(g.acme??!0),certPath:g.certPath,keyPath:g.keyPath,requireForAuth:g.requireForAuth??(y&&c),acmeEmail:g.acmeEmail??f[0]?.address},dkim:{enabled:C,selector:S.selector??"default",rotate:S.rotate??!1,rotateIntervalDays:S.rotateIntervalDays??90},webmail:{enabled:E,port:P.port??p.webmail,domain:P.domain},delivery:I,sesRegion:i.sesRegion??"us-east-1",accounts:f,storagePath:i.storagePath??"/var/lib/mail",maxMessageSize:i.maxMessageSize??26214400,spam:{enabled:v.enabled??c,enforce:v.enforce??!1,junkScore:v.junkScore??5,rejectScore:v.rejectScore??12,dnsbl:v.dnsbl??c,greylist:v.greylist??!1},webhookUrl:i.webhookUrl,expose:D,bindAddress:D?"0.0.0.0":"127.0.0.1"}}function aa(e){if(!e.enabled||!e.expose)return[];let n=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((r)=>typeof r==="number");if(e.webmail.enabled&&!e.webmail.domain)n.push(e.webmail.port);return[...new Set(n)].sort((r,i)=>r-i)}function ca(e){if(!e.enabled)return{};let n=e.ports.submission??e.ports.smtp,r={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(e.mode==="server"){r.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let i=e.accounts[0];if(i)r.MAIL_USERNAME=i.address,r.MAIL_PASSWORD=i.password}else r.MAIL_ENCRYPTION="null",r.MAIL_USERNAME="null",r.MAIL_PASSWORD="null";return r}function F(e){if(e.cloud?.provider)return e.cloud.provider;if(e.ssh?.hosts?.length)return"ssh";if(e.hetzner?.apiToken)return"hetzner";return"aws"}class Fo{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,n){return this.template.Resources[e]=n,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=n,this}addOutput(e,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=n,this}addMetadata(e,n){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[e]=n,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,n=0){let r=" ".repeat(n),i="";for(let[s,a]of Object.entries(e)){if(a===null||a===void 0)continue;if(typeof a==="object"&&!Array.isArray(a))i+=`${r}${s}:
2
2
  ${this.convertToYAML(a,n+1)}`;else if(Array.isArray(a)){i+=`${r}${s}:
3
3
  `;for(let c of a)if(typeof c==="object")i+=`${r} -
4
4
  ${this.convertToYAML(c,n+2)}`;else i+=`${r} - ${c}
5
5
  `}else i+=`${r}${s}: ${a}
6
- `}return i}}function Jd(e){let n=[],r=[],i=[];if(mr(e,n),e.Resources)pr(e.Resources,n,r);else n.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});if(e.Parameters)gr(e.Parameters,n,r);if(e.Outputs)yr(e.Outputs,n);hr(e,n);let s=fr(e);if(s.length>0)for(let a of s)n.push({path:"Resources",message:`Circular dependency detected: ${a.join(" → ")}`,severity:"error"});return Sr(e,r,i),{valid:n.length===0,errors:n,warnings:r,info:i}}function mr(e,n){if(!e.AWSTemplateFormatVersion)n.push({path:"AWSTemplateFormatVersion",message:"Template should specify AWSTemplateFormatVersion",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")n.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion must be "2010-09-09"',severity:"error"})}function pr(e,n,r){let i=Object.keys(e);if(i.length===0){n.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});return}if(i.length>500)r.push({path:"Resources",message:`Template contains ${i.length} resources (limit is 500)`,severity:"warning"});for(let s of i){let a=e[s];if(!/^[a-zA-Z0-9]+$/.test(s))n.push({path:`Resources.${s}`,message:"Logical ID must contain only alphanumeric characters",severity:"error"});if(!a.Type)n.push({path:`Resources.${s}.Type`,message:"Resource Type is required",severity:"error"});else if(!a.Type.startsWith("AWS::")&&!a.Type.startsWith("Custom::"))n.push({path:`Resources.${s}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(a.DeletionPolicy&&!["Delete","Retain","Snapshot"].includes(a.DeletionPolicy))n.push({path:`Resources.${s}.DeletionPolicy`,message:'DeletionPolicy must be "Delete", "Retain", or "Snapshot"',severity:"error"});if(!a.DeletionPolicy&&nn(a.Type))r.push({path:`Resources.${s}.DeletionPolicy`,message:`${a.Type} should specify DeletionPolicy to prevent accidental data loss`,severity:"warning"})}}function gr(e,n,r){let i=Object.keys(e);if(i.length>200)r.push({path:"Parameters",message:`Template contains ${i.length} parameters (limit is 200)`,severity:"warning"});for(let s of i){let a=e[s];if(!a.Type)n.push({path:`Parameters.${s}.Type`,message:"Parameter Type is required",severity:"error"});let c=["String","Number","List<Number>","CommaDelimitedList","AWS::EC2::AvailabilityZone::Name","AWS::EC2::Image::Id","AWS::EC2::Instance::Id","AWS::EC2::KeyPair::KeyName","AWS::EC2::SecurityGroup::GroupName","AWS::EC2::SecurityGroup::Id","AWS::EC2::Subnet::Id","AWS::EC2::Volume::Id","AWS::EC2::VPC::Id","AWS::Route53::HostedZone::Id","List<AWS::EC2::AvailabilityZone::Name>","List<AWS::EC2::Image::Id>","List<AWS::EC2::Instance::Id>","List<AWS::EC2::SecurityGroup::GroupName>","List<AWS::EC2::SecurityGroup::Id>","List<AWS::EC2::Subnet::Id>","List<AWS::EC2::Volume::Id>","List<AWS::EC2::VPC::Id>","List<AWS::Route53::HostedZone::Id>","AWS::SSM::Parameter::Name","AWS::SSM::Parameter::Value<String>","AWS::SSM::Parameter::Value<List<String>>","AWS::SSM::Parameter::Value<CommaDelimitedList>"];if(a.Type&&!c.includes(a.Type))n.push({path:`Parameters.${s}.Type`,message:`Invalid parameter type: ${a.Type}`,severity:"error"})}}function yr(e,n){let r=Object.keys(e);for(let i of r)if(!e[i].Value)n.push({path:`Outputs.${i}.Value`,message:"Output Value is required",severity:"error"})}function hr(e,n){let r=e.Resources||{},i=e.Parameters||{},s=new Set(Object.keys(r)),a=new Set(Object.keys(i));function c(u,d){if(typeof u!=="object"||u===null)return;if(u.Ref){let m=u.Ref;if(!s.has(m)&&!a.has(m)&&m!=="AWS::Region"&&m!=="AWS::AccountId"&&m!=="AWS::StackName"&&m!=="AWS::StackId"&&m!=="AWS::URLSuffix"&&m!=="AWS::Partition"&&m!=="AWS::NoValue")n.push({path:d,message:`Reference to non-existent resource or parameter: ${m}`,severity:"error"})}if(u["Fn::GetAtt"]){let m=u["Fn::GetAtt"];if(Array.isArray(m)&&m.length>=1){let p=m[0];if(!s.has(p))n.push({path:d,message:`GetAtt references non-existent resource: ${p}`,severity:"error"})}}for(let m in u)c(u[m],`${d}.${m}`)}for(let u in r)c(r[u],`Resources.${u}`);if(e.Outputs)for(let u in e.Outputs)c(e.Outputs[u],`Outputs.${u}`)}function fr(e){let n=e.Resources||{},r=new Map;for(let u in n){let d=new Set,m=n[u];if(m.DependsOn)if(Array.isArray(m.DependsOn))m.DependsOn.forEach((g)=>d.add(g));else d.add(m.DependsOn);br(m).forEach((g)=>d.add(g)),r.set(u,d)}let i=[],s=new Set,a=new Set;function c(u,d){s.add(u),a.add(u),d.push(u);let m=r.get(u)||new Set;for(let p of m)if(!s.has(p))c(p,[...d]);else if(a.has(p)){let g=d.indexOf(p),y=[...d.slice(g),p];i.push(y)}a.delete(u)}for(let u of r.keys())if(!s.has(u))c(u,[]);return i}function br(e){let n=new Set;function r(i){if(typeof i!=="object"||i===null)return;if(i.Ref&&typeof i.Ref==="string"){if(!i.Ref.startsWith("AWS::"))n.add(i.Ref)}if(i["Fn::GetAtt"]&&Array.isArray(i["Fn::GetAtt"]))n.add(i["Fn::GetAtt"][0]);for(let s in i)r(i[s])}return r(e),n}function nn(e){return["AWS::S3::Bucket","AWS::DynamoDB::Table","AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::EFS::FileSystem","AWS::OpenSearchService::Domain"].includes(e)}function Sr(e,n,r){let i=e.Resources||{};if(!e.Description)r.push({path:"Description",message:"Consider adding a Description to the template",severity:"info"});for(let s in i){let a=i[s],c=a.Properties;if(c&&!c.Tags&&Ar(a.Type))r.push({path:`Resources.${s}`,message:`Consider adding Tags to ${a.Type}`,severity:"info"});if(nn(a.Type)){if(a.Type==="AWS::S3::Bucket"&&!c?.BucketEncryption)n.push({path:`Resources.${s}`,message:"S3 bucket should enable encryption",severity:"warning"});if(a.Type==="AWS::RDS::DBInstance"&&!c?.StorageEncrypted)n.push({path:`Resources.${s}`,message:"RDS instance should enable storage encryption",severity:"warning"})}}}function Ar(e){return!["AWS::CloudFormation::Stack","AWS::CloudFormation::WaitCondition","AWS::CloudFormation::WaitConditionHandle"].includes(e)}function Xd(e){let n=[],r=[],i=[],s=Buffer.byteLength(e,"utf8"),a=s/1024,c=51200,u=460800;if(s>460800)n.push({path:"Template",message:`Template size (${a.toFixed(2)} KB) exceeds maximum size of 450 KB`,severity:"error"});else if(s>51200)r.push({path:"Template",message:`Template size (${a.toFixed(2)} KB) exceeds 50 KB. Must use S3 for deployment.`,severity:"warning"});return{valid:n.length===0,errors:n,warnings:r,info:i}}function Qd(e){let n=[],r=[],i=[],s=e.Resources||{},a=e.Parameters||{},c=e.Outputs||{};if(Object.keys(s).length>500)n.push({path:"Resources",message:`Template has ${Object.keys(s).length} resources (limit is 500)`,severity:"error"});if(Object.keys(a).length>200)n.push({path:"Parameters",message:`Template has ${Object.keys(a).length} parameters (limit is 200)`,severity:"error"});if(Object.keys(c).length>200)n.push({path:"Outputs",message:`Template has ${Object.keys(c).length} outputs (limit is 200)`,severity:"error"});return{valid:n.length===0,errors:n,warnings:r,info:i}}var R={Ref:(e)=>({Ref:e}),GetAtt:(e,n)=>({"Fn::GetAtt":[e,n]}),Sub:(e,n)=>{if(n)return{"Fn::Sub":[e,n]};return{"Fn::Sub":e}},Join:(e,n)=>({"Fn::Join":[e,n]}),Select:(e,n)=>({"Fn::Select":[e,n]}),Split:(e,n)=>({"Fn::Split":[e,n]}),GetAZs:(e="")=>({"Fn::GetAZs":e}),ImportValue:(e)=>({"Fn::ImportValue":e}),If:(e,n,r)=>({"Fn::If":[e,n,r]}),Equals:(e,n)=>({"Fn::Equals":[e,n]}),And:(...e)=>({"Fn::And":e}),Or:(...e)=>({"Fn::Or":e}),Not:(e)=>({"Fn::Not":[e]}),Base64:(e)=>({"Fn::Base64":e})},Yd={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 l(e){let{slug:n,environment:r,resourceType:i,timestamp:s,suffix:a}=e,c=[n,r,i];if(s)c.push(s);if(a)c.push(a);return c.join("-")}function o(e){return e.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function pm(){return Date.now().toString()}function mm(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function T(e,n){return e.project.stackName??`${e.project.slug}-${n}`}function oa(e,n,r,i){return r.stackName??`${e.project.slug}-${i}-${n}-site`}function sa(e,n){return`${e.project.slug}-${n}`}function aa(e,n,r,i){if(i)return i;if(r==="main")return`${e}-${n}-site`;return`${e}-${n}-${r}`}function gm(e,n,r,i){return i??`${e}-${n}-${r}`}function fm(e,n){return`${e}-${n}-deploy`}function ke(e,n){return`${e.project.slug}-${n}-app`}function ca(e,n){return`${e}-${n}-deployments`}function Ii(e,n){return`${e}-${n}-assets`}class Zd{nodes=new Map;addResource(e,n){let r=this.extractDependencies(n);this.nodes.set(e,{logicalId:e,resource:n,dependencies:r})}extractDependencies(e){let n=new Set;if(e.DependsOn)if(Array.isArray(e.DependsOn))e.DependsOn.forEach((r)=>n.add(r));else n.add(e.DependsOn);return this.findReferences(e.Properties||{},n),n}findReferences(e,n){if(!e||typeof e!=="object")return;if("Ref"in e&&typeof e.Ref==="string"){if(!e.Ref.startsWith("AWS::"))n.add(e.Ref)}if("Fn::GetAtt"in e&&Array.isArray(e["Fn::GetAtt"]))n.add(e["Fn::GetAtt"][0]);for(let r of Object.values(e))if(typeof r==="object")this.findReferences(r,n)}topologicalSort(){let e=[],n=new Set,r=new Set,i=(s)=>{if(n.has(s))return;if(r.has(s))throw Error(`Circular dependency detected: ${s}`);r.add(s);let a=this.nodes.get(s);if(a)for(let c of a.dependencies)i(c);r.delete(s),n.add(s),e.push(s)};for(let s of this.nodes.keys())i(s);return e}validate(){for(let[e,n]of this.nodes.entries())for(let r of n.dependencies)if(!this.nodes.has(r))throw Error(`Resource "${e}" depends on "${r}" which does not exist`)}getDependents(e){let n=[];for(let[r,i]of this.nodes.entries())if(i.dependencies.has(e))n.push(r);return n}}function hm(e,n){let r=[],i=[],s=[],a=[],c=[],u=e.Resources||{},d=n.Resources||{},m=new Set([...Object.keys(u),...Object.keys(d)]);for(let g of m){let y=u[g],h=d[g];if(!y&&h)r.push({logicalId:g,action:"add",resourceType:h.Type});else if(y&&!h)i.push({logicalId:g,action:"remove",resourceType:y.Type});else if(y&&h)if(y.Type!==h.Type)a.push({logicalId:g,action:"replace",resourceType:h.Type,reason:`Type changed from ${y.Type} to ${h.Type}`});else{let f=rn(y.Properties||{},h.Properties||{});if(f.length>0)if(Cr(y.Type,f))a.push({logicalId:g,action:"replace",resourceType:h.Type,changes:f,reason:"Property changes require replacement"});else s.push({logicalId:g,action:"update",resourceType:h.Type,changes:f});else c.push(g)}}let p=vr([...i,...a,...s]);return{added:r,removed:i,updated:s,replaced:a,unchanged:c,summary:{totalChanges:r.length+i.length+s.length+a.length,requiresReplacement:a.length>0,dangerousChanges:p}}}function rn(e,n,r=""){let i=[],s=new Set([...Object.keys(e),...Object.keys(n)]);for(let a of s){let c=r?`${r}.${a}`:a,u=e[a],d=n[a];if(u===void 0&&d!==void 0)i.push({path:c,oldValue:void 0,newValue:d});else if(u!==void 0&&d===void 0)i.push({path:c,oldValue:u,newValue:void 0});else if(typeof u!==typeof d)i.push({path:c,oldValue:u,newValue:d});else if(typeof u==="object"&&u!==null)if(Array.isArray(u)&&Array.isArray(d)){if(JSON.stringify(u)!==JSON.stringify(d))i.push({path:c,oldValue:u,newValue:d})}else if(!Array.isArray(u)&&!Array.isArray(d)){let m=rn(u,d,c);i.push(...m)}else i.push({path:c,oldValue:u,newValue:d});else if(u!==d)i.push({path:c,oldValue:u,newValue:d})}return i}function Cr(e,n){let i={"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"])}[e];if(!i)return!1;for(let s of n){let a=s.path.split(".")[0];if(i.has(a))return!0}return!1}function vr(e){let n=[];for(let r of e){if(r.action==="remove"&&(r.resourceType==="AWS::RDS::DBInstance"||r.resourceType==="AWS::DynamoDB::Table"||r.resourceType==="AWS::ElastiCache::CacheCluster"))n.push(`Removing ${r.resourceType} ${r.logicalId} - data loss risk!`);if(r.action==="replace"&&(r.resourceType==="AWS::RDS::DBInstance"||r.resourceType==="AWS::DynamoDB::Table"))n.push(`Replacing ${r.resourceType} ${r.logicalId} - data loss risk!`);if((r.action==="remove"||r.action==="replace")&&r.resourceType==="AWS::S3::Bucket")n.push(`${r.action==="remove"?"Removing":"Replacing"} S3 bucket ${r.logicalId} - data loss risk!`);if(r.action==="replace"&&r.resourceType==="AWS::EC2::Instance")n.push(`Replacing EC2 instance ${r.logicalId} - downtime expected`);if(r.action==="update"&&r.resourceType==="AWS::EC2::SecurityGroup")n.push(`Updating security group ${r.logicalId} - may affect connectivity`);if((r.action==="update"||r.action==="replace")&&(r.resourceType==="AWS::IAM::Role"||r.resourceType==="AWS::IAM::Policy"))n.push(`Modifying IAM ${r.resourceType.split("::")[2]} ${r.logicalId} - may affect permissions`)}return n}function ym(e){let n=[];if(n.push(`=== Stack Update Analysis ===
6
+ `}return i}}function Zd(e){let n=[],r=[],i=[];if(mr(e,n),e.Resources)pr(e.Resources,n,r);else n.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});if(e.Parameters)gr(e.Parameters,n,r);if(e.Outputs)yr(e.Outputs,n);hr(e,n);let s=fr(e);if(s.length>0)for(let a of s)n.push({path:"Resources",message:`Circular dependency detected: ${a.join(" → ")}`,severity:"error"});return Sr(e,r,i),{valid:n.length===0,errors:n,warnings:r,info:i}}function mr(e,n){if(!e.AWSTemplateFormatVersion)n.push({path:"AWSTemplateFormatVersion",message:"Template should specify AWSTemplateFormatVersion",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")n.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion must be "2010-09-09"',severity:"error"})}function pr(e,n,r){let i=Object.keys(e);if(i.length===0){n.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});return}if(i.length>500)r.push({path:"Resources",message:`Template contains ${i.length} resources (limit is 500)`,severity:"warning"});for(let s of i){let a=e[s];if(!/^[a-zA-Z0-9]+$/.test(s))n.push({path:`Resources.${s}`,message:"Logical ID must contain only alphanumeric characters",severity:"error"});if(!a.Type)n.push({path:`Resources.${s}.Type`,message:"Resource Type is required",severity:"error"});else if(!a.Type.startsWith("AWS::")&&!a.Type.startsWith("Custom::"))n.push({path:`Resources.${s}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(a.DeletionPolicy&&!["Delete","Retain","Snapshot"].includes(a.DeletionPolicy))n.push({path:`Resources.${s}.DeletionPolicy`,message:'DeletionPolicy must be "Delete", "Retain", or "Snapshot"',severity:"error"});if(!a.DeletionPolicy&&nn(a.Type))r.push({path:`Resources.${s}.DeletionPolicy`,message:`${a.Type} should specify DeletionPolicy to prevent accidental data loss`,severity:"warning"})}}function gr(e,n,r){let i=Object.keys(e);if(i.length>200)r.push({path:"Parameters",message:`Template contains ${i.length} parameters (limit is 200)`,severity:"warning"});for(let s of i){let a=e[s];if(!a.Type)n.push({path:`Parameters.${s}.Type`,message:"Parameter Type is required",severity:"error"});let c=["String","Number","List<Number>","CommaDelimitedList","AWS::EC2::AvailabilityZone::Name","AWS::EC2::Image::Id","AWS::EC2::Instance::Id","AWS::EC2::KeyPair::KeyName","AWS::EC2::SecurityGroup::GroupName","AWS::EC2::SecurityGroup::Id","AWS::EC2::Subnet::Id","AWS::EC2::Volume::Id","AWS::EC2::VPC::Id","AWS::Route53::HostedZone::Id","List<AWS::EC2::AvailabilityZone::Name>","List<AWS::EC2::Image::Id>","List<AWS::EC2::Instance::Id>","List<AWS::EC2::SecurityGroup::GroupName>","List<AWS::EC2::SecurityGroup::Id>","List<AWS::EC2::Subnet::Id>","List<AWS::EC2::Volume::Id>","List<AWS::EC2::VPC::Id>","List<AWS::Route53::HostedZone::Id>","AWS::SSM::Parameter::Name","AWS::SSM::Parameter::Value<String>","AWS::SSM::Parameter::Value<List<String>>","AWS::SSM::Parameter::Value<CommaDelimitedList>"];if(a.Type&&!c.includes(a.Type))n.push({path:`Parameters.${s}.Type`,message:`Invalid parameter type: ${a.Type}`,severity:"error"})}}function yr(e,n){let r=Object.keys(e);for(let i of r)if(!e[i].Value)n.push({path:`Outputs.${i}.Value`,message:"Output Value is required",severity:"error"})}function hr(e,n){let r=e.Resources||{},i=e.Parameters||{},s=new Set(Object.keys(r)),a=new Set(Object.keys(i));function c(u,d){if(typeof u!=="object"||u===null)return;if(u.Ref){let m=u.Ref;if(!s.has(m)&&!a.has(m)&&m!=="AWS::Region"&&m!=="AWS::AccountId"&&m!=="AWS::StackName"&&m!=="AWS::StackId"&&m!=="AWS::URLSuffix"&&m!=="AWS::Partition"&&m!=="AWS::NoValue")n.push({path:d,message:`Reference to non-existent resource or parameter: ${m}`,severity:"error"})}if(u["Fn::GetAtt"]){let m=u["Fn::GetAtt"];if(Array.isArray(m)&&m.length>=1){let p=m[0];if(!s.has(p))n.push({path:d,message:`GetAtt references non-existent resource: ${p}`,severity:"error"})}}for(let m in u)c(u[m],`${d}.${m}`)}for(let u in r)c(r[u],`Resources.${u}`);if(e.Outputs)for(let u in e.Outputs)c(e.Outputs[u],`Outputs.${u}`)}function fr(e){let n=e.Resources||{},r=new Map;for(let u in n){let d=new Set,m=n[u];if(m.DependsOn)if(Array.isArray(m.DependsOn))m.DependsOn.forEach((g)=>d.add(g));else d.add(m.DependsOn);br(m).forEach((g)=>d.add(g)),r.set(u,d)}let i=[],s=new Set,a=new Set;function c(u,d){s.add(u),a.add(u),d.push(u);let m=r.get(u)||new Set;for(let p of m)if(!s.has(p))c(p,[...d]);else if(a.has(p)){let g=d.indexOf(p),y=[...d.slice(g),p];i.push(y)}a.delete(u)}for(let u of r.keys())if(!s.has(u))c(u,[]);return i}function br(e){let n=new Set;function r(i){if(typeof i!=="object"||i===null)return;if(i.Ref&&typeof i.Ref==="string"){if(!i.Ref.startsWith("AWS::"))n.add(i.Ref)}if(i["Fn::GetAtt"]&&Array.isArray(i["Fn::GetAtt"]))n.add(i["Fn::GetAtt"][0]);for(let s in i)r(i[s])}return r(e),n}function nn(e){return["AWS::S3::Bucket","AWS::DynamoDB::Table","AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::EFS::FileSystem","AWS::OpenSearchService::Domain"].includes(e)}function Sr(e,n,r){let i=e.Resources||{};if(!e.Description)r.push({path:"Description",message:"Consider adding a Description to the template",severity:"info"});for(let s in i){let a=i[s],c=a.Properties;if(c&&!c.Tags&&Ar(a.Type))r.push({path:`Resources.${s}`,message:`Consider adding Tags to ${a.Type}`,severity:"info"});if(nn(a.Type)){if(a.Type==="AWS::S3::Bucket"&&!c?.BucketEncryption)n.push({path:`Resources.${s}`,message:"S3 bucket should enable encryption",severity:"warning"});if(a.Type==="AWS::RDS::DBInstance"&&!c?.StorageEncrypted)n.push({path:`Resources.${s}`,message:"RDS instance should enable storage encryption",severity:"warning"})}}}function Ar(e){return!["AWS::CloudFormation::Stack","AWS::CloudFormation::WaitCondition","AWS::CloudFormation::WaitConditionHandle"].includes(e)}function eu(e){let n=[],r=[],i=[],s=Buffer.byteLength(e,"utf8"),a=s/1024,c=51200,u=460800;if(s>460800)n.push({path:"Template",message:`Template size (${a.toFixed(2)} KB) exceeds maximum size of 450 KB`,severity:"error"});else if(s>51200)r.push({path:"Template",message:`Template size (${a.toFixed(2)} KB) exceeds 50 KB. Must use S3 for deployment.`,severity:"warning"});return{valid:n.length===0,errors:n,warnings:r,info:i}}function tu(e){let n=[],r=[],i=[],s=e.Resources||{},a=e.Parameters||{},c=e.Outputs||{};if(Object.keys(s).length>500)n.push({path:"Resources",message:`Template has ${Object.keys(s).length} resources (limit is 500)`,severity:"error"});if(Object.keys(a).length>200)n.push({path:"Parameters",message:`Template has ${Object.keys(a).length} parameters (limit is 200)`,severity:"error"});if(Object.keys(c).length>200)n.push({path:"Outputs",message:`Template has ${Object.keys(c).length} outputs (limit is 200)`,severity:"error"});return{valid:n.length===0,errors:n,warnings:r,info:i}}var R={Ref:(e)=>({Ref:e}),GetAtt:(e,n)=>({"Fn::GetAtt":[e,n]}),Sub:(e,n)=>{if(n)return{"Fn::Sub":[e,n]};return{"Fn::Sub":e}},Join:(e,n)=>({"Fn::Join":[e,n]}),Select:(e,n)=>({"Fn::Select":[e,n]}),Split:(e,n)=>({"Fn::Split":[e,n]}),GetAZs:(e="")=>({"Fn::GetAZs":e}),ImportValue:(e)=>({"Fn::ImportValue":e}),If:(e,n,r)=>({"Fn::If":[e,n,r]}),Equals:(e,n)=>({"Fn::Equals":[e,n]}),And:(...e)=>({"Fn::And":e}),Or:(...e)=>({"Fn::Or":e}),Not:(e)=>({"Fn::Not":[e]}),Base64:(e)=>({"Fn::Base64":e})},ru={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 l(e){let{slug:n,environment:r,resourceType:i,timestamp:s,suffix:a}=e,c=[n,r,i];if(s)c.push(s);if(a)c.push(a);return c.join("-")}function o(e){return e.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function hm(){return Date.now().toString()}function ym(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function T(e,n){return e.project.stackName??`${e.project.slug}-${n}`}function la(e,n,r,i){return r.stackName??`${e.project.slug}-${i}-${n}-site`}function da(e,n){return`${e.project.slug}-${n}`}function ua(e,n,r,i){if(i)return i;if(r==="main")return`${e}-${n}-site`;return`${e}-${n}-${r}`}function bm(e,n,r,i){return i??`${e}-${n}-${r}`}function Sm(e,n){return`${e}-${n}-deploy`}function xe(e,n){return`${e.project.slug}-${n}-app`}function pa(e,n){return`${e}-${n}-deployments`}function Ni(e,n){return`${e}-${n}-assets`}class nu{nodes=new Map;addResource(e,n){let r=this.extractDependencies(n);this.nodes.set(e,{logicalId:e,resource:n,dependencies:r})}extractDependencies(e){let n=new Set;if(e.DependsOn)if(Array.isArray(e.DependsOn))e.DependsOn.forEach((r)=>n.add(r));else n.add(e.DependsOn);return this.findReferences(e.Properties||{},n),n}findReferences(e,n){if(!e||typeof e!=="object")return;if("Ref"in e&&typeof e.Ref==="string"){if(!e.Ref.startsWith("AWS::"))n.add(e.Ref)}if("Fn::GetAtt"in e&&Array.isArray(e["Fn::GetAtt"]))n.add(e["Fn::GetAtt"][0]);for(let r of Object.values(e))if(typeof r==="object")this.findReferences(r,n)}topologicalSort(){let e=[],n=new Set,r=new Set,i=(s)=>{if(n.has(s))return;if(r.has(s))throw Error(`Circular dependency detected: ${s}`);r.add(s);let a=this.nodes.get(s);if(a)for(let c of a.dependencies)i(c);r.delete(s),n.add(s),e.push(s)};for(let s of this.nodes.keys())i(s);return e}validate(){for(let[e,n]of this.nodes.entries())for(let r of n.dependencies)if(!this.nodes.has(r))throw Error(`Resource "${e}" depends on "${r}" which does not exist`)}getDependents(e){let n=[];for(let[r,i]of this.nodes.entries())if(i.dependencies.has(e))n.push(r);return n}}function vm(e,n){let r=[],i=[],s=[],a=[],c=[],u=e.Resources||{},d=n.Resources||{},m=new Set([...Object.keys(u),...Object.keys(d)]);for(let g of m){let y=u[g],h=d[g];if(!y&&h)r.push({logicalId:g,action:"add",resourceType:h.Type});else if(y&&!h)i.push({logicalId:g,action:"remove",resourceType:y.Type});else if(y&&h)if(y.Type!==h.Type)a.push({logicalId:g,action:"replace",resourceType:h.Type,reason:`Type changed from ${y.Type} to ${h.Type}`});else{let f=rn(y.Properties||{},h.Properties||{});if(f.length>0)if(Cr(y.Type,f))a.push({logicalId:g,action:"replace",resourceType:h.Type,changes:f,reason:"Property changes require replacement"});else s.push({logicalId:g,action:"update",resourceType:h.Type,changes:f});else c.push(g)}}let p=vr([...i,...a,...s]);return{added:r,removed:i,updated:s,replaced:a,unchanged:c,summary:{totalChanges:r.length+i.length+s.length+a.length,requiresReplacement:a.length>0,dangerousChanges:p}}}function rn(e,n,r=""){let i=[],s=new Set([...Object.keys(e),...Object.keys(n)]);for(let a of s){let c=r?`${r}.${a}`:a,u=e[a],d=n[a];if(u===void 0&&d!==void 0)i.push({path:c,oldValue:void 0,newValue:d});else if(u!==void 0&&d===void 0)i.push({path:c,oldValue:u,newValue:void 0});else if(typeof u!==typeof d)i.push({path:c,oldValue:u,newValue:d});else if(typeof u==="object"&&u!==null)if(Array.isArray(u)&&Array.isArray(d)){if(JSON.stringify(u)!==JSON.stringify(d))i.push({path:c,oldValue:u,newValue:d})}else if(!Array.isArray(u)&&!Array.isArray(d)){let m=rn(u,d,c);i.push(...m)}else i.push({path:c,oldValue:u,newValue:d});else if(u!==d)i.push({path:c,oldValue:u,newValue:d})}return i}function Cr(e,n){let i={"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"])}[e];if(!i)return!1;for(let s of n){let a=s.path.split(".")[0];if(i.has(a))return!0}return!1}function vr(e){let n=[];for(let r of e){if(r.action==="remove"&&(r.resourceType==="AWS::RDS::DBInstance"||r.resourceType==="AWS::DynamoDB::Table"||r.resourceType==="AWS::ElastiCache::CacheCluster"))n.push(`Removing ${r.resourceType} ${r.logicalId} - data loss risk!`);if(r.action==="replace"&&(r.resourceType==="AWS::RDS::DBInstance"||r.resourceType==="AWS::DynamoDB::Table"))n.push(`Replacing ${r.resourceType} ${r.logicalId} - data loss risk!`);if((r.action==="remove"||r.action==="replace")&&r.resourceType==="AWS::S3::Bucket")n.push(`${r.action==="remove"?"Removing":"Replacing"} S3 bucket ${r.logicalId} - data loss risk!`);if(r.action==="replace"&&r.resourceType==="AWS::EC2::Instance")n.push(`Replacing EC2 instance ${r.logicalId} - downtime expected`);if(r.action==="update"&&r.resourceType==="AWS::EC2::SecurityGroup")n.push(`Updating security group ${r.logicalId} - may affect connectivity`);if((r.action==="update"||r.action==="replace")&&(r.resourceType==="AWS::IAM::Role"||r.resourceType==="AWS::IAM::Policy"))n.push(`Modifying IAM ${r.resourceType.split("::")[2]} ${r.logicalId} - may affect permissions`)}return n}function Cm(e){let n=[];if(n.push(`=== Stack Update Analysis ===
7
7
  `),e.summary.totalChanges===0)return n.push(`No changes detected.
8
8
  `),n.join(`
9
9
  `);if(n.push(`Total changes: ${e.summary.totalChanges}`),n.push(`Requires replacement: ${e.summary.requiresReplacement?"Yes":"No"}
10
10
  `),e.summary.dangerousChanges.length>0){n.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let r of e.summary.dangerousChanges)n.push(` • ${r}`);n.push("")}if(e.added.length>0){n.push(`✅ Resources to Add (${e.added.length}):`);for(let r of e.added)n.push(` + ${r.logicalId} (${r.resourceType})`);n.push("")}if(e.removed.length>0){n.push(`❌ Resources to Remove (${e.removed.length}):`);for(let r of e.removed)n.push(` - ${r.logicalId} (${r.resourceType})`);n.push("")}if(e.replaced.length>0){n.push(`\uD83D\uDD04 Resources to Replace (${e.replaced.length}):`);for(let r of e.replaced){if(n.push(` ~ ${r.logicalId} (${r.resourceType})`),r.reason)n.push(` Reason: ${r.reason}`);if(r.changes){for(let i of r.changes.slice(0,3))n.push(` • ${i.path}: ${JSON.stringify(i.oldValue)} → ${JSON.stringify(i.newValue)}`);if(r.changes.length>3)n.push(` ... and ${r.changes.length-3} more changes`)}}n.push("")}if(e.updated.length>0){n.push(`\uD83D\uDCDD Resources to Update (${e.updated.length}):`);for(let r of e.updated)if(n.push(` ~ ${r.logicalId} (${r.resourceType})`),r.changes){for(let i of r.changes.slice(0,3))n.push(` • ${i.path}: ${JSON.stringify(i.oldValue)} → ${JSON.stringify(i.newValue)}`);if(r.changes.length>3)n.push(` ... and ${r.changes.length-3} more changes`)}n.push("")}if(e.unchanged.length>0)n.push(`⚪ Unchanged Resources (${e.unchanged.length})`);return n.join(`
11
- `)}import{existsSync as Le,readdirSync as Tr}from"node:fs";import{join as ae}from"node:path";class Fe{static createBucket(e){let{name:n,bucketName:r,slug:i,environment:s,public:a=!1,versioning:c=!1,website:u=!1,encryption:d=!0,intelligentTiering:m=!1,cors:p,lifecycleRules:g}=e,y=r??l({slug:i,environment:s,resourceType:"s3",suffix:n}),h=o(y),f={Type:"AWS::S3::Bucket",Properties:{BucketName:y}};if(d)f.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(c)f.Properties.VersioningConfiguration={Status:"Enabled"};if(u)f.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!a)f.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(p&&p.length>0)f.Properties.CorsConfiguration={CorsRules:p.map((C)=>({AllowedOrigins:C.allowedOrigins,AllowedMethods:C.allowedMethods,AllowedHeaders:C.allowedHeaders,MaxAge:C.maxAge}))};if(g&&g.length>0)f.Properties.LifecycleConfiguration={Rules:g.map((C)=>({Id:C.id,Status:C.enabled?"Enabled":"Disabled",ExpirationInDays:C.expirationDays,Transitions:C.transitions?.map((P)=>({TransitionInDays:P.days,StorageClass:P.storageClass}))}))};if(m&&g){let C={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!f.Properties.LifecycleConfiguration)f.Properties.LifecycleConfiguration={Rules:[]};f.Properties.LifecycleConfiguration.Rules.push({Id:C.id,Status:"Enabled",Transitions:C.transitions?.map((P)=>({TransitionInDays:P.days,StorageClass:P.storageClass}))})}let S;if(a)S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static enableVersioning(e){if(!e.Properties)e.Properties={};return e.Properties.VersioningConfiguration={Status:"Enabled"},e}static enableWebsiteHosting(e,n="index.html",r="error.html"){if(!e.Properties)e.Properties={};return e.Properties.WebsiteConfiguration={IndexDocument:n,ErrorDocument:r},e}static setLifecycleRules(e,n){if(!e.Properties)e.Properties={};return e.Properties.LifecycleConfiguration={Rules:n.map((r)=>({Id:r.id,Status:r.enabled?"Enabled":"Disabled",ExpirationInDays:r.expirationDays,Transitions:r.transitions?.map((i)=>({TransitionInDays:i.days,StorageClass:i.storageClass}))}))},e}static enableIntelligentTiering(e){if(!e.Properties)e.Properties={};if(!e.Properties.LifecycleConfiguration)e.Properties.LifecycleConfiguration={Rules:[]};return e.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),e}static addLambdaNotification(e,n){if(!e.Properties)e.Properties={};if(!e.Properties.NotificationConfiguration)e.Properties.NotificationConfiguration={};if(!e.Properties.NotificationConfiguration.LambdaConfigurations)e.Properties.NotificationConfiguration.LambdaConfigurations=[];let r={Event:n.events[0],Function:n.functionArn};if(n.filter)r.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};for(let i of n.events){let s={...r,Event:i};e.Properties.NotificationConfiguration.LambdaConfigurations.push(s)}return e}static Notifications={onObjectCreated:(e)=>({functionArn:e,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(e)=>({functionArn:e,events:["s3:ObjectRemoved:*"]}),onImageUpload:(e,n)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:n,suffix:".jpg"}}),onFileType:(e,n,r)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:r,suffix:n}}),onFolderUpload:(e,n)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:n.endsWith("/")?n:`${n}/`}})};static createBackupPlan(e){let{name:n,slug:r,environment:i,bucketLogicalIds:s,retentionDays:a,schedule:c="cron(0 5 * * ? *)",vaultName:u,enableContinuousBackup:d=!1,moveToColdStorageAfterDays:m}=e,p=u||l({slug:r,environment:i,resourceType:"backup-vault",suffix:n}),g=o(p),y={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:p}},h=l({slug:r,environment:i,resourceType:"backup-role",suffix:n}),f=o(h),S={Type:"AWS::IAM::Role",Properties:{RoleName:h,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"]}},C=l({slug:r,environment:i,resourceType:"backup-plan",suffix:n}),P=o(C),E={DeleteAfterDays:a};if(m&&m<a)E.MoveToColdStorageAfterDays=m;let v={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:C,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:R.Ref(g),ScheduleExpression:c,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:E,EnableContinuousBackup:d}]}}},I=l({slug:r,environment:i,resourceType:"backup-selection",suffix:n}),D=o(I),x=s.map((M)=>R.GetAtt(M,"Arn")),F={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:R.Ref(P),BackupSelection:{SelectionName:I,IamRoleArn:R.GetAtt(f,"Arn"),Resources:x}}};return{vault:y,plan:v,selection:F,role:S,vaultLogicalId:g,planLogicalId:P,selectionLogicalId:D,roleLogicalId:f}}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(e){let{slug:n,environment:r,sourceDomain:i,targetDomain:s,protocol:a="https"}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"www-redirect"}),u=o(c),d={Type:"AWS::S3::Bucket",Properties:{BucketName:i,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:s,Protocol:a}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},m={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(u),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(u,"Arn"),"/*"])]}]}}};return{bucket:d,bucketPolicy:m,logicalId:u}}static createDocsBucket(e){let{slug:n,environment:r,domain:i}=e,s=i||l({slug:n,environment:r,resourceType:"s3",suffix:"docs"}),a=o(s);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:a}}static createEmailBucket(e){let{slug:n,environment:r}=e,i=l({slug:n,environment:r,resourceType:"s3",suffix:"email"}),s=o(i),a={Type:"AWS::S3::Bucket",Properties:{BucketName:i,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"}]}]}}},c={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:R.Join("",[R.GetAtt(s,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":R.Ref("AWS::AccountId")}}}]}}};return{bucket:a,bucketPolicy:c,logicalId:s}}static docsExist(e={}){let{projectRoot:n=process.cwd(),docsPaths:r=["docs","documentation","doc"]}=e;for(let i of r){let s=ae(n,i);if(Le(s)){let a=["dist","build",".bunpress/dist","_site","out","public"];for(let c of a){let u=ae(s,c);if(Le(u))try{if(Tr(u).length>0)return{exists:!0,path:s,hasDistFolder:!0,distPath:u}}catch{}}return{exists:!0,path:s,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(e){let n=Fe.docsExist({projectRoot:e.projectRoot,docsPaths:e.docsPaths});if(!n.exists)return{bucket:null,logicalId:null,docsInfo:n};let r=Fe.createDocsBucket({slug:e.slug,environment:e.environment,domain:e.domain});return{bucket:r.bucket,bucketPolicy:r.bucketPolicy,logicalId:r.logicalId,docsInfo:n}}static createPrivateBucket(e){let{slug:n,environment:r,enableVersioning:i=!0,retentionDays:s,encryptionKeyArn:a}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"private"}),u=o(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:a?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:a}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:i?{Status:"Enabled"}:void 0,LifecycleConfiguration:s?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:s}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:u}}static checkSourcePaths(e={}){let{projectRoot:n=process.cwd(),paths:r={}}=e,i=r.web||"views/web/dist",s=r.docs||"docs/dist",a=r.private||"private";return{web:{exists:Le(ae(n,i)),path:ae(n,i)},docs:{exists:Le(ae(n,s)),path:ae(n,s)},private:{exists:Le(ae(n,a)),path:ae(n,a)}}}static createDeploymentBuckets(e){let{slug:n,environment:r,domain:i,projectRoot:s,paths:a}=e,c=Fe.checkSourcePaths({projectRoot:s,paths:a}),u={},d={web:!1,docs:!1,private:!1},m=Fe.createBucket({name:"web",slug:n,environment:r,public:!1,versioning:!1,encryption:!0});if(u[m.logicalId]=m.bucket,d.web=!0,c.docs.exists){let p=Fe.createDocsBucket({slug:n,environment:r,domain:i?`docs.${i}`:void 0});if(u[p.logicalId]=p.bucket,p.bucketPolicy)u[`${p.logicalId}Policy`]=p.bucketPolicy;d.docs=!0}if(c.private.exists){let p=Fe.createPrivateBucket({slug:n,environment:r,enableVersioning:!0});u[p.logicalId]=p.bucket,d.private=!0}return{resources:u,created:d,sourcePaths:c}}}class Et{static createRepository(e){let{name:n,slug:r,environment:i,scanOnPush:s=!0,imageMutability:a="MUTABLE",encryption:c="AES256",kmsKey:u,lifecyclePolicy:d,tags:m}=e,p=l({slug:r,environment:i,resourceType:"ecr",suffix:n}),g=o(p),y={Type:"AWS::ECR::Repository",Properties:{RepositoryName:p,ImageTagMutability:a,ImageScanningConfiguration:{ScanOnPush:s},EncryptionConfiguration:{EncryptionType:c,...u&&c==="KMS"?{KmsKey:u}:{}}}};if(d)y.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(Et.generateLifecyclePolicy(d))};if(m)y.Properties.Tags=Object.entries(m).map(([h,f])=>({Key:h,Value:f}));return{repository:y,logicalId:g}}static generateLifecyclePolicy(e){let n=[];if(e.untaggedImageExpireDays!==void 0)n.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(e.maxImageCount!==void 0)n.push({rulePriority:n.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount},action:{type:"expire"}});if(e.maxImageAgeDays!==void 0)n.push({rulePriority:n.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:n}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(e){if(!e.Properties)e.Properties={};return e.Properties.ImageTagMutability="IMMUTABLE",e}static enableScanOnPush(e){if(!e.Properties)e.Properties={};return e.Properties.ImageScanningConfiguration={ScanOnPush:!0},e}static setLifecyclePolicy(e,n){if(!e.Properties)e.Properties={};return e.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(Et.generateLifecyclePolicy(n))},e}static addCrossAccountAccess(e,n){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:n.map((r)=>`arn:aws:iam::${r}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},e}static addLambdaAccess(e){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},e}static generateBunDockerfile(e){let{baseImage:n="oven/bun:1-debian",serverPath:r,port:i=3000,additionalDirs:s=[],healthCheckEndpoint:a="/health",nodeCompatible:c=!1,envVars:u={},buildCommands:d=[],runCommand:m}=e,p=["app","config",...s],g=m||`bun run ${r}`,y=`# Multi-stage build for Bun application
11
+ `)}import{existsSync as Me,readdirSync as Tr}from"node:fs";import{join as ae}from"node:path";class Fe{static createBucket(e){let{name:n,bucketName:r,slug:i,environment:s,public:a=!1,versioning:c=!1,website:u=!1,encryption:d=!0,intelligentTiering:m=!1,cors:p,lifecycleRules:g}=e,y=r??l({slug:i,environment:s,resourceType:"s3",suffix:n}),h=o(y),f={Type:"AWS::S3::Bucket",Properties:{BucketName:y}};if(d)f.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(c)f.Properties.VersioningConfiguration={Status:"Enabled"};if(u)f.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!a)f.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(p&&p.length>0)f.Properties.CorsConfiguration={CorsRules:p.map((C)=>({AllowedOrigins:C.allowedOrigins,AllowedMethods:C.allowedMethods,AllowedHeaders:C.allowedHeaders,MaxAge:C.maxAge}))};if(g&&g.length>0)f.Properties.LifecycleConfiguration={Rules:g.map((C)=>({Id:C.id,Status:C.enabled?"Enabled":"Disabled",ExpirationInDays:C.expirationDays,Transitions:C.transitions?.map((P)=>({TransitionInDays:P.days,StorageClass:P.storageClass}))}))};if(m&&g){let C={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!f.Properties.LifecycleConfiguration)f.Properties.LifecycleConfiguration={Rules:[]};f.Properties.LifecycleConfiguration.Rules.push({Id:C.id,Status:"Enabled",Transitions:C.transitions?.map((P)=>({TransitionInDays:P.days,StorageClass:P.storageClass}))})}let S;if(a)S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static enableVersioning(e){if(!e.Properties)e.Properties={};return e.Properties.VersioningConfiguration={Status:"Enabled"},e}static enableWebsiteHosting(e,n="index.html",r="error.html"){if(!e.Properties)e.Properties={};return e.Properties.WebsiteConfiguration={IndexDocument:n,ErrorDocument:r},e}static setLifecycleRules(e,n){if(!e.Properties)e.Properties={};return e.Properties.LifecycleConfiguration={Rules:n.map((r)=>({Id:r.id,Status:r.enabled?"Enabled":"Disabled",ExpirationInDays:r.expirationDays,Transitions:r.transitions?.map((i)=>({TransitionInDays:i.days,StorageClass:i.storageClass}))}))},e}static enableIntelligentTiering(e){if(!e.Properties)e.Properties={};if(!e.Properties.LifecycleConfiguration)e.Properties.LifecycleConfiguration={Rules:[]};return e.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),e}static addLambdaNotification(e,n){if(!e.Properties)e.Properties={};if(!e.Properties.NotificationConfiguration)e.Properties.NotificationConfiguration={};if(!e.Properties.NotificationConfiguration.LambdaConfigurations)e.Properties.NotificationConfiguration.LambdaConfigurations=[];let r={Event:n.events[0],Function:n.functionArn};if(n.filter)r.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};for(let i of n.events){let s={...r,Event:i};e.Properties.NotificationConfiguration.LambdaConfigurations.push(s)}return e}static Notifications={onObjectCreated:(e)=>({functionArn:e,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(e)=>({functionArn:e,events:["s3:ObjectRemoved:*"]}),onImageUpload:(e,n)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:n,suffix:".jpg"}}),onFileType:(e,n,r)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:r,suffix:n}}),onFolderUpload:(e,n)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:n.endsWith("/")?n:`${n}/`}})};static createBackupPlan(e){let{name:n,slug:r,environment:i,bucketLogicalIds:s,retentionDays:a,schedule:c="cron(0 5 * * ? *)",vaultName:u,enableContinuousBackup:d=!1,moveToColdStorageAfterDays:m}=e,p=u||l({slug:r,environment:i,resourceType:"backup-vault",suffix:n}),g=o(p),y={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:p}},h=l({slug:r,environment:i,resourceType:"backup-role",suffix:n}),f=o(h),S={Type:"AWS::IAM::Role",Properties:{RoleName:h,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"]}},C=l({slug:r,environment:i,resourceType:"backup-plan",suffix:n}),P=o(C),E={DeleteAfterDays:a};if(m&&m<a)E.MoveToColdStorageAfterDays=m;let v={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:C,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:R.Ref(g),ScheduleExpression:c,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:E,EnableContinuousBackup:d}]}}},I=l({slug:r,environment:i,resourceType:"backup-selection",suffix:n}),D=o(I),N=s.map((M)=>R.GetAtt(M,"Arn")),B={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:R.Ref(P),BackupSelection:{SelectionName:I,IamRoleArn:R.GetAtt(f,"Arn"),Resources:N}}};return{vault:y,plan:v,selection:B,role:S,vaultLogicalId:g,planLogicalId:P,selectionLogicalId:D,roleLogicalId:f}}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(e){let{slug:n,environment:r,sourceDomain:i,targetDomain:s,protocol:a="https"}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"www-redirect"}),u=o(c),d={Type:"AWS::S3::Bucket",Properties:{BucketName:i,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:s,Protocol:a}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},m={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(u),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(u,"Arn"),"/*"])]}]}}};return{bucket:d,bucketPolicy:m,logicalId:u}}static createDocsBucket(e){let{slug:n,environment:r,domain:i}=e,s=i||l({slug:n,environment:r,resourceType:"s3",suffix:"docs"}),a=o(s);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:a}}static createEmailBucket(e){let{slug:n,environment:r}=e,i=l({slug:n,environment:r,resourceType:"s3",suffix:"email"}),s=o(i),a={Type:"AWS::S3::Bucket",Properties:{BucketName:i,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"}]}]}}},c={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:R.Join("",[R.GetAtt(s,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":R.Ref("AWS::AccountId")}}}]}}};return{bucket:a,bucketPolicy:c,logicalId:s}}static docsExist(e={}){let{projectRoot:n=process.cwd(),docsPaths:r=["docs","documentation","doc"]}=e;for(let i of r){let s=ae(n,i);if(Me(s)){let a=["dist","build",".bunpress/dist","_site","out","public"];for(let c of a){let u=ae(s,c);if(Me(u))try{if(Tr(u).length>0)return{exists:!0,path:s,hasDistFolder:!0,distPath:u}}catch{}}return{exists:!0,path:s,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(e){let n=Fe.docsExist({projectRoot:e.projectRoot,docsPaths:e.docsPaths});if(!n.exists)return{bucket:null,logicalId:null,docsInfo:n};let r=Fe.createDocsBucket({slug:e.slug,environment:e.environment,domain:e.domain});return{bucket:r.bucket,bucketPolicy:r.bucketPolicy,logicalId:r.logicalId,docsInfo:n}}static createPrivateBucket(e){let{slug:n,environment:r,enableVersioning:i=!0,retentionDays:s,encryptionKeyArn:a}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"private"}),u=o(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:a?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:a}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:i?{Status:"Enabled"}:void 0,LifecycleConfiguration:s?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:s}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:u}}static checkSourcePaths(e={}){let{projectRoot:n=process.cwd(),paths:r={}}=e,i=r.web||"views/web/dist",s=r.docs||"docs/dist",a=r.private||"private";return{web:{exists:Me(ae(n,i)),path:ae(n,i)},docs:{exists:Me(ae(n,s)),path:ae(n,s)},private:{exists:Me(ae(n,a)),path:ae(n,a)}}}static createDeploymentBuckets(e){let{slug:n,environment:r,domain:i,projectRoot:s,paths:a}=e,c=Fe.checkSourcePaths({projectRoot:s,paths:a}),u={},d={web:!1,docs:!1,private:!1},m=Fe.createBucket({name:"web",slug:n,environment:r,public:!1,versioning:!1,encryption:!0});if(u[m.logicalId]=m.bucket,d.web=!0,c.docs.exists){let p=Fe.createDocsBucket({slug:n,environment:r,domain:i?`docs.${i}`:void 0});if(u[p.logicalId]=p.bucket,p.bucketPolicy)u[`${p.logicalId}Policy`]=p.bucketPolicy;d.docs=!0}if(c.private.exists){let p=Fe.createPrivateBucket({slug:n,environment:r,enableVersioning:!0});u[p.logicalId]=p.bucket,d.private=!0}return{resources:u,created:d,sourcePaths:c}}}class Et{static createRepository(e){let{name:n,slug:r,environment:i,scanOnPush:s=!0,imageMutability:a="MUTABLE",encryption:c="AES256",kmsKey:u,lifecyclePolicy:d,tags:m}=e,p=l({slug:r,environment:i,resourceType:"ecr",suffix:n}),g=o(p),y={Type:"AWS::ECR::Repository",Properties:{RepositoryName:p,ImageTagMutability:a,ImageScanningConfiguration:{ScanOnPush:s},EncryptionConfiguration:{EncryptionType:c,...u&&c==="KMS"?{KmsKey:u}:{}}}};if(d)y.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(Et.generateLifecyclePolicy(d))};if(m)y.Properties.Tags=Object.entries(m).map(([h,f])=>({Key:h,Value:f}));return{repository:y,logicalId:g}}static generateLifecyclePolicy(e){let n=[];if(e.untaggedImageExpireDays!==void 0)n.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(e.maxImageCount!==void 0)n.push({rulePriority:n.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount},action:{type:"expire"}});if(e.maxImageAgeDays!==void 0)n.push({rulePriority:n.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:n}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(e){if(!e.Properties)e.Properties={};return e.Properties.ImageTagMutability="IMMUTABLE",e}static enableScanOnPush(e){if(!e.Properties)e.Properties={};return e.Properties.ImageScanningConfiguration={ScanOnPush:!0},e}static setLifecyclePolicy(e,n){if(!e.Properties)e.Properties={};return e.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(Et.generateLifecyclePolicy(n))},e}static addCrossAccountAccess(e,n){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:n.map((r)=>`arn:aws:iam::${r}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},e}static addLambdaAccess(e){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},e}static generateBunDockerfile(e){let{baseImage:n="oven/bun:1-debian",serverPath:r,port:i=3000,additionalDirs:s=[],healthCheckEndpoint:a="/health",nodeCompatible:c=!1,envVars:u={},buildCommands:d=[],runCommand:m}=e,p=["app","config",...s],g=m||`bun run ${r}`,y=`# Multi-stage build for Bun application
12
12
  # Generated by ts-cloud
13
13
 
14
14
  # Builder stage
@@ -91,7 +91,7 @@ echo "Image: $IMAGE_URI:${i}"
91
91
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
92
92
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...e.ecsCluster&&e.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${e.ecsCluster} --service ${e.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
93
93
  ${JSON.stringify(n,null,2).replace(/"/g,"").replace(/,\n/g,`
94
- `)}`}};static DockerfileTemplates={bunServer:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n}),bunWithBuild:(e,n,r=3000)=>Et.generateBunDockerfile({serverPath:e,port:r,buildCommands:[n]}),bunFullStack:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n,healthCheckEndpoint:"/api/health"})}}var la=[400,403,404,416,429,500,502,503,504],Jc=[500,502,503,504],Xc=["GET","HEAD","OPTIONS"],bm="-failover-group",Qc=["default","media-quality-based"],Yc={min:1,max:3},Zc={min:1,max:10};function Mo(e){if(e===void 0)return[...Jc];if(e.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${la.join(", ")}). Omit it to use the default ${Jc.join(", ")}.`);let n=e.filter((r)=>!la.includes(r));if(n.length>0)throw Error(`CloudFront origin failover: ${n.join(", ")} ${n.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${la.join(", ")}.`);return[...new Set(e)].sort((r,i)=>r-i)}function da(e){let{primaryOriginId:n,secondaryOriginId:r}=e;if(!n||!r)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(n===r)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${n}")`);let i=Mo(e.statusCodes);return sn(e.selectionCriteria),{Id:e.groupId??`${n}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:i.length,Items:i}},Members:{Quantity:2,Items:[{OriginId:n},{OriginId:r}]},...e.selectionCriteria?{SelectionCriteria:e.selectionCriteria}:{}}}function sn(e,n="the origin group"){if(e===void 0)return;if(!Qc.includes(e))throw Error(`CloudFront origin failover: ${n} has selection criteria ${JSON.stringify(e)}. Allowed: ${Qc.join(", ")}.`)}function qe(e,n,r){if(typeof e!=="number"||!Number.isInteger(e)||e<n.min||e>n.max)throw Error(`CloudFront origin: ${r} must be a whole number from ${n.min} to ${n.max}, got ${JSON.stringify(e)}.`)}function tt(e,n="the origin"){let r={};if(e?.connectionAttempts!==void 0)qe(e.connectionAttempts,Yc,`${n} connectionAttempts`),r.ConnectionAttempts=e.connectionAttempts;if(e?.connectionTimeout!==void 0)qe(e.connectionTimeout,Zc,`${n} connectionTimeout (seconds)`),r.ConnectionTimeout=e.connectionTimeout;return r}function Uo(e){return{Quantity:1,Items:[da(e)]}}function fn(e,n="the cache behavior"){let i=(Array.isArray(e)?e:e?.Items??[]).filter((s)=>!Xc.includes(s.toUpperCase()));if(i.length>0)throw Error(`CloudFront origin failover: ${n} allows ${i.join(", ")}, but a cache behavior that targets an origin group may only allow ${Xc.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Pi(e){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(e)&&!/s3-website/i.test(e)}function Oe(e){if(!e)return[];if(Array.isArray(e))return e;return e.Items??[]}function re(e){return typeof e==="string"?e:void 0}var Rr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function hn(e,n="the distribution"){let r=Oe(e.Origins),i=new Set(r.map((p)=>re(p.Id)).filter((p)=>!!p)),s=new Map(r.map((p)=>[re(p.Id)??"",p.DomainName])),a=r.some((p)=>re(p.Id)===void 0);for(let p of r){let g=re(p.Id)??"(unnamed origin)";if(p.ConnectionAttempts!==void 0)qe(p.ConnectionAttempts,Yc,`${n} origin "${g}" ConnectionAttempts`);if(p.ConnectionTimeout!==void 0)qe(p.ConnectionTimeout,Zc,`${n} origin "${g}" ConnectionTimeout (seconds)`)}let c=e.OriginGroups,u=Oe(c);if(c&&!Array.isArray(c)&&c.Quantity!==void 0&&c.Quantity!==u.length)throw Error(`CloudFront origin failover: ${n} OriginGroups.Quantity is ${c.Quantity} but it lists ${u.length} group(s).`);let d=new Set;for(let p of u){let g=re(p.Id);if(p.Id===void 0||p.Id==="")throw Error(`CloudFront origin failover: ${n} has an origin group without an Id.`);let y=`${n} origin group "${g??"(intrinsic id)"}"`;if(g){if(d.has(g))throw Error(`CloudFront origin failover: ${n} declares origin group "${g}" twice.`);if(i.has(g))throw Error(`CloudFront origin failover: ${y} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);d.add(g)}let h=p.Members,f=Oe(h);if(f.length!==2||h?.Quantity!==void 0&&h.Quantity!==f.length)throw Error(`CloudFront origin failover: ${y} must have exactly 2 members (a primary and a secondary), it has ${f.length}${h?.Quantity!==void 0&&h.Quantity!==f.length?` with Quantity ${h.Quantity}`:""}.`);let S=f.map((E)=>re(E.OriginId));for(let E of S)if(E&&!i.has(E)&&!a)throw Error(`CloudFront origin failover: ${y} lists member "${E}", which is not an origin of this distribution. Origins: ${[...i].join(", ")||"(none)"}.`);if(S[0]&&S[0]===S[1])throw Error(`CloudFront origin failover: ${y} lists "${S[0]}" as both primary and secondary.`);let C=p.FailoverCriteria?.StatusCodes,P=Oe(C);if(Mo(P),C?.Quantity!==void 0&&C.Quantity!==P.length)throw Error(`CloudFront origin failover: ${y} FailoverCriteria.StatusCodes.Quantity is ${C.Quantity} but it lists ${P.length} code(s).`);if(sn(p.SelectionCriteria,y),p.SelectionCriteria==="media-quality-based")for(let E of S){let v=E?re(s.get(E)):void 0;if(v&&!Rr.test(v))throw Error(`CloudFront origin failover: ${y} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${E}" is ${v}. Use 'default'.`)}}let m=[];if(e.DefaultCacheBehavior)m.push({behavior:e.DefaultCacheBehavior,name:"the default cache behavior"});for(let p of Oe(e.CacheBehaviors))m.push({behavior:p,name:`the cache behavior for ${JSON.stringify(p.PathPattern)}`});for(let{behavior:p,name:g}of m){let y=re(p.TargetOriginId);if(!y)continue;if(d.has(y))fn(p.AllowedMethods??["GET","HEAD"],`${g} of ${n} (origin group "${y}")`);else if(!i.has(y)&&!a&&u.every((h)=>re(h.Id)!==void 0))throw Error(`CloudFront: ${g} of ${n} targets "${y}", which is neither an origin nor an origin group of this distribution.`)}}class Be{static createDistribution(e){let{slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,errorPages:c,cachePolicy:u,edgeFunctions:d,http3:m=!1,comment:p,failoverOrigin:g}=e,y=l({slug:n,environment:r,resourceType:"cdn"}),h=o(y),f={Id:"DefaultOrigin",DomainName:i.domainName,OriginPath:i.originPath||"",...tt(i,"the CDN origin")},S;if(i.type==="s3"){let P=`${h}OAC`;S={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${y}-oac`,Description:`Origin Access Control for ${y}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},f.OriginAccessControlId=R.Ref(P)}else if(i.type==="alb"||i.type==="custom")f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:p||`CDN for ${y}`,DefaultRootObject:"index.html",Origins:[f],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:m?"http2and3":"http2"}}};if(s&&a)C.Properties.DistributionConfig.Aliases=[s],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(c&&c.length>0)C.Properties.DistributionConfig.CustomErrorResponses=c.map((P)=>({ErrorCode:P.errorCode,ResponseCode:P.responseCode,ResponsePagePath:P.responsePagePath}));if(d&&d.length>0)C.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=d.map((P)=>({EventType:P.event,LambdaFunctionARN:P.functionArn}));if(g)Be.addOriginFailover(C,g);return{distribution:C,originAccessControl:S,logicalId:h}}static addOriginFailover(e,n){let r=e.Properties.DistributionConfig,i=r.DefaultCacheBehavior,s=i.TargetOriginId,a=n.id??"FailoverOrigin";if(r.OriginGroups&&r.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(fn(i.AllowedMethods??["GET","HEAD"],"the default cache behavior"),r.Origins.some((p)=>p.Id===a))throw Error(`CloudFront origin failover: an origin with id "${a}" already exists`);let c=da({primaryOriginId:s,secondaryOriginId:a,statusCodes:n.statusCodes,selectionCriteria:n.selectionCriteria}),u=n.type??(Pi(n.domainName)?"s3":"custom"),d={Id:a,DomainName:n.domainName,OriginPath:n.originPath||"",...tt(n,"the failover origin")},m=tt(n.primary,"the primary origin");if(Object.keys(m).length>0){let p=r.Origins.find((g)=>g.Id===s);if(p)Object.assign(p,m)}if(u==="s3"){let p=r.Origins.find((g)=>g.Id===s);if(d.S3OriginConfig={OriginAccessIdentity:""},p?.OriginAccessControlId)d.OriginAccessControlId=p.OriginAccessControlId}else d.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return r.Origins.push(d),r.OriginGroups={Quantity:1,Items:[c]},i.TargetOriginId=c.Id,hn(r),e}static setCustomDomain(e,n,r){return e.Properties.DistributionConfig.Aliases=[n],e.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:r,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},e}static setErrorPages(e,n){return e.Properties.DistributionConfig.CustomErrorResponses=n.map((r)=>({ErrorCode:r.errorCode,ResponseCode:r.responseCode,ResponsePagePath:r.responsePagePath})),e}static enableHttp3(e){return e.Properties.DistributionConfig.HttpVersion="http2and3",e}static addEdgeFunction(e,n,r){if(!e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:n,LambdaFunctionARN:r}),e}static setCachePolicy(e,n){return e.Properties.DistributionConfig.Comment=`${e.Properties.DistributionConfig.Comment||""} (TTL: ${n.default||86400}s)`,e}static createSpaDistribution(e){return Be.createDistribution({...e,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(e){let{slug:n,environment:r}=e,i=l({slug:n,environment:r,resourceType:"edge-docs"}),s=o(i),a=o(`${i}-role`),c=o(`${i}-version`),u={Type:"AWS::IAM::Role",Properties:{RoleName:`${i}-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"]}},d=`
94
+ `)}`}};static DockerfileTemplates={bunServer:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n}),bunWithBuild:(e,n,r=3000)=>Et.generateBunDockerfile({serverPath:e,port:r,buildCommands:[n]}),bunFullStack:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(e,n=3000)=>Et.generateBunDockerfile({serverPath:e,port:n,healthCheckEndpoint:"/api/health"})}}var ma=[400,403,404,416,429,500,502,503,504],Zc=[500,502,503,504],el=["GET","HEAD","OPTIONS"],Tm="-failover-group",tl=["default","media-quality-based"],rl={min:1,max:3},nl={min:1,max:10};function jo(e){if(e===void 0)return[...Zc];if(e.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${ma.join(", ")}). Omit it to use the default ${Zc.join(", ")}.`);let n=e.filter((r)=>!ma.includes(r));if(n.length>0)throw Error(`CloudFront origin failover: ${n.join(", ")} ${n.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${ma.join(", ")}.`);return[...new Set(e)].sort((r,i)=>r-i)}function ga(e){let{primaryOriginId:n,secondaryOriginId:r}=e;if(!n||!r)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(n===r)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${n}")`);let i=jo(e.statusCodes);return sn(e.selectionCriteria),{Id:e.groupId??`${n}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:i.length,Items:i}},Members:{Quantity:2,Items:[{OriginId:n},{OriginId:r}]},...e.selectionCriteria?{SelectionCriteria:e.selectionCriteria}:{}}}function sn(e,n="the origin group"){if(e===void 0)return;if(!tl.includes(e))throw Error(`CloudFront origin failover: ${n} has selection criteria ${JSON.stringify(e)}. Allowed: ${tl.join(", ")}.`)}function qe(e,n,r){if(typeof e!=="number"||!Number.isInteger(e)||e<n.min||e>n.max)throw Error(`CloudFront origin: ${r} must be a whole number from ${n.min} to ${n.max}, got ${JSON.stringify(e)}.`)}function tt(e,n="the origin"){let r={};if(e?.connectionAttempts!==void 0)qe(e.connectionAttempts,rl,`${n} connectionAttempts`),r.ConnectionAttempts=e.connectionAttempts;if(e?.connectionTimeout!==void 0)qe(e.connectionTimeout,nl,`${n} connectionTimeout (seconds)`),r.ConnectionTimeout=e.connectionTimeout;return r}function Vo(e){return{Quantity:1,Items:[ga(e)]}}function bn(e,n="the cache behavior"){let i=(Array.isArray(e)?e:e?.Items??[]).filter((s)=>!el.includes(s.toUpperCase()));if(i.length>0)throw Error(`CloudFront origin failover: ${n} allows ${i.join(", ")}, but a cache behavior that targets an origin group may only allow ${el.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function xi(e){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(e)&&!/s3-website/i.test(e)}function Le(e){if(!e)return[];if(Array.isArray(e))return e;return e.Items??[]}function re(e){return typeof e==="string"?e:void 0}var Rr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function Sn(e,n="the distribution"){let r=Le(e.Origins),i=new Set(r.map((p)=>re(p.Id)).filter((p)=>!!p)),s=new Map(r.map((p)=>[re(p.Id)??"",p.DomainName])),a=r.some((p)=>re(p.Id)===void 0);for(let p of r){let g=re(p.Id)??"(unnamed origin)";if(p.ConnectionAttempts!==void 0)qe(p.ConnectionAttempts,rl,`${n} origin "${g}" ConnectionAttempts`);if(p.ConnectionTimeout!==void 0)qe(p.ConnectionTimeout,nl,`${n} origin "${g}" ConnectionTimeout (seconds)`)}let c=e.OriginGroups,u=Le(c);if(c&&!Array.isArray(c)&&c.Quantity!==void 0&&c.Quantity!==u.length)throw Error(`CloudFront origin failover: ${n} OriginGroups.Quantity is ${c.Quantity} but it lists ${u.length} group(s).`);let d=new Set;for(let p of u){let g=re(p.Id);if(p.Id===void 0||p.Id==="")throw Error(`CloudFront origin failover: ${n} has an origin group without an Id.`);let y=`${n} origin group "${g??"(intrinsic id)"}"`;if(g){if(d.has(g))throw Error(`CloudFront origin failover: ${n} declares origin group "${g}" twice.`);if(i.has(g))throw Error(`CloudFront origin failover: ${y} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);d.add(g)}let h=p.Members,f=Le(h);if(f.length!==2||h?.Quantity!==void 0&&h.Quantity!==f.length)throw Error(`CloudFront origin failover: ${y} must have exactly 2 members (a primary and a secondary), it has ${f.length}${h?.Quantity!==void 0&&h.Quantity!==f.length?` with Quantity ${h.Quantity}`:""}.`);let S=f.map((E)=>re(E.OriginId));for(let E of S)if(E&&!i.has(E)&&!a)throw Error(`CloudFront origin failover: ${y} lists member "${E}", which is not an origin of this distribution. Origins: ${[...i].join(", ")||"(none)"}.`);if(S[0]&&S[0]===S[1])throw Error(`CloudFront origin failover: ${y} lists "${S[0]}" as both primary and secondary.`);let C=p.FailoverCriteria?.StatusCodes,P=Le(C);if(jo(P),C?.Quantity!==void 0&&C.Quantity!==P.length)throw Error(`CloudFront origin failover: ${y} FailoverCriteria.StatusCodes.Quantity is ${C.Quantity} but it lists ${P.length} code(s).`);if(sn(p.SelectionCriteria,y),p.SelectionCriteria==="media-quality-based")for(let E of S){let v=E?re(s.get(E)):void 0;if(v&&!Rr.test(v))throw Error(`CloudFront origin failover: ${y} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${E}" is ${v}. Use 'default'.`)}}let m=[];if(e.DefaultCacheBehavior)m.push({behavior:e.DefaultCacheBehavior,name:"the default cache behavior"});for(let p of Le(e.CacheBehaviors))m.push({behavior:p,name:`the cache behavior for ${JSON.stringify(p.PathPattern)}`});for(let{behavior:p,name:g}of m){let y=re(p.TargetOriginId);if(!y)continue;if(d.has(y))bn(p.AllowedMethods??["GET","HEAD"],`${g} of ${n} (origin group "${y}")`);else if(!i.has(y)&&!a&&u.every((h)=>re(h.Id)!==void 0))throw Error(`CloudFront: ${g} of ${n} targets "${y}", which is neither an origin nor an origin group of this distribution.`)}}class je{static createDistribution(e){let{slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,errorPages:c,cachePolicy:u,edgeFunctions:d,http3:m=!1,comment:p,failoverOrigin:g}=e,y=l({slug:n,environment:r,resourceType:"cdn"}),h=o(y),f={Id:"DefaultOrigin",DomainName:i.domainName,OriginPath:i.originPath||"",...tt(i,"the CDN origin")},S;if(i.type==="s3"){let P=`${h}OAC`;S={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${y}-oac`,Description:`Origin Access Control for ${y}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},f.OriginAccessControlId=R.Ref(P)}else if(i.type==="alb"||i.type==="custom")f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:p||`CDN for ${y}`,DefaultRootObject:"index.html",Origins:[f],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:m?"http2and3":"http2"}}};if(s&&a)C.Properties.DistributionConfig.Aliases=[s],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(c&&c.length>0)C.Properties.DistributionConfig.CustomErrorResponses=c.map((P)=>({ErrorCode:P.errorCode,ResponseCode:P.responseCode,ResponsePagePath:P.responsePagePath}));if(d&&d.length>0)C.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=d.map((P)=>({EventType:P.event,LambdaFunctionARN:P.functionArn}));if(g)je.addOriginFailover(C,g);return{distribution:C,originAccessControl:S,logicalId:h}}static addOriginFailover(e,n){let r=e.Properties.DistributionConfig,i=r.DefaultCacheBehavior,s=i.TargetOriginId,a=n.id??"FailoverOrigin";if(r.OriginGroups&&r.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(bn(i.AllowedMethods??["GET","HEAD"],"the default cache behavior"),r.Origins.some((p)=>p.Id===a))throw Error(`CloudFront origin failover: an origin with id "${a}" already exists`);let c=ga({primaryOriginId:s,secondaryOriginId:a,statusCodes:n.statusCodes,selectionCriteria:n.selectionCriteria}),u=n.type??(xi(n.domainName)?"s3":"custom"),d={Id:a,DomainName:n.domainName,OriginPath:n.originPath||"",...tt(n,"the failover origin")},m=tt(n.primary,"the primary origin");if(Object.keys(m).length>0){let p=r.Origins.find((g)=>g.Id===s);if(p)Object.assign(p,m)}if(u==="s3"){let p=r.Origins.find((g)=>g.Id===s);if(d.S3OriginConfig={OriginAccessIdentity:""},p?.OriginAccessControlId)d.OriginAccessControlId=p.OriginAccessControlId}else d.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return r.Origins.push(d),r.OriginGroups={Quantity:1,Items:[c]},i.TargetOriginId=c.Id,Sn(r),e}static setCustomDomain(e,n,r){return e.Properties.DistributionConfig.Aliases=[n],e.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:r,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},e}static setErrorPages(e,n){return e.Properties.DistributionConfig.CustomErrorResponses=n.map((r)=>({ErrorCode:r.errorCode,ResponseCode:r.responseCode,ResponsePagePath:r.responsePagePath})),e}static enableHttp3(e){return e.Properties.DistributionConfig.HttpVersion="http2and3",e}static addEdgeFunction(e,n,r){if(!e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:n,LambdaFunctionARN:r}),e}static setCachePolicy(e,n){return e.Properties.DistributionConfig.Comment=`${e.Properties.DistributionConfig.Comment||""} (TTL: ${n.default||86400}s)`,e}static createSpaDistribution(e){return je.createDistribution({...e,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(e){let{slug:n,environment:r}=e,i=l({slug:n,environment:r,resourceType:"edge-docs"}),s=o(i),a=o(`${i}-role`),c=o(`${i}-version`),u={Type:"AWS::IAM::Role",Properties:{RoleName:`${i}-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"]}},d=`
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:i,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:R.GetAtt(a,"Arn"),Code:{ZipFile:d},MemorySize:128,Timeout:5}},role:u,functionLogicalId:s,roleLogicalId:a,versionLogicalId:c}}static createDocsDistribution(e){let{slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,lambdaEdgeFunctionArn:c}=e,u=Be.createDistribution({slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,comment:`Docs CDN for ${n}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(c)Be.addEdgeFunction(u.distribution,"origin-request",c);return u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,u}static createApiDistribution(e){let{slug:n,environment:r,albDomainName:i,customDomain:s,certificateArn:a,pathPattern:c="/api/*",forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:d="all",whitelistedCookies:m,customOriginHeaders:p={}}=e,g=l({slug:n,environment:r,resourceType:"cdn-api"}),y=o(g),h=Object.entries(p).map(([P,E])=>({HeaderName:P,HeaderValue:E})),f={Id:"ALBOrigin",DomainName:i,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(h.length>0)f.OriginCustomHeaders=h;let S={Forward:d};if(d==="whitelist"&&m)S.WhitelistedNames=m;let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${g}`,Origins:[f],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:u,Cookies:S}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(s&&a)C.Properties.DistributionConfig.Aliases=[s],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:C,logicalId:y}}static createMultiOriginDistribution(e){let{slug:n,environment:r,s3BucketDomainName:i,albDomainName:s,apiPathPattern:a="/api/*",customDomain:c,certificateArn:u,customOriginHeaders:d={}}=e,m=l({slug:n,environment:r,resourceType:"cdn"}),p=o(m),g=`${p}OAC`,y={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${m}-oac`,Description:`Origin Access Control for ${m}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},h=Object.entries(d).map(([P,E])=>({HeaderName:P,HeaderValue:E})),f={Id:"S3Origin",DomainName:i,OriginAccessControlId:R.Ref(g)},S={Id:"ALBOrigin",DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(h.length>0)S.OriginCustomHeaders=h;let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${m}`,DefaultRootObject:"index.html",Origins:[f,S],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:a,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(c&&u)C.Properties.DistributionConfig.Aliases=[c],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:C,originAccessControl:y,logicalId:p,oacLogicalId:g}}static addAlbOrigin(e,n){let{originId:r,domainName:i,pathPattern:s,customHeaders:a={},forwardHeaders:c=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:u={default:0,max:0,min:0}}=n,d=Object.entries(a).map(([p,g])=>({HeaderName:p,HeaderValue:g})),m={Id:r,DomainName:i,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(d.length>0)m.OriginCustomHeaders=d;if(!e.Properties.DistributionConfig.Origins)e.Properties.DistributionConfig.Origins=[];if(e.Properties.DistributionConfig.Origins.push(m),!e.Properties.DistributionConfig.CacheBehaviors)e.Properties.DistributionConfig.CacheBehaviors=[];return e.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:s,TargetOriginId:r,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:u.default,MaxTTL:u.max,MinTTL:u.min,ForwardedValues:{QueryString:!0,Headers:c,Cookies:{Forward:"all"}}}),e}static addOriginHeader(e,n,r,i){let s=e.Properties.DistributionConfig.Origins?.find((a)=>a.Id===n);if(s){if(!s.OriginCustomHeaders)s.OriginCustomHeaders=[];s.OriginCustomHeaders.push({HeaderName:r,HeaderValue:i})}return e}static EdgeFunctionTemplates={docsOriginRequest:`
127
+ `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:i,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:R.GetAtt(a,"Arn"),Code:{ZipFile:d},MemorySize:128,Timeout:5}},role:u,functionLogicalId:s,roleLogicalId:a,versionLogicalId:c}}static createDocsDistribution(e){let{slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,lambdaEdgeFunctionArn:c}=e,u=je.createDistribution({slug:n,environment:r,origin:i,customDomain:s,certificateArn:a,comment:`Docs CDN for ${n}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(c)je.addEdgeFunction(u.distribution,"origin-request",c);return u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,u.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,u}static createApiDistribution(e){let{slug:n,environment:r,albDomainName:i,customDomain:s,certificateArn:a,pathPattern:c="/api/*",forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:d="all",whitelistedCookies:m,customOriginHeaders:p={}}=e,g=l({slug:n,environment:r,resourceType:"cdn-api"}),y=o(g),h=Object.entries(p).map(([P,E])=>({HeaderName:P,HeaderValue:E})),f={Id:"ALBOrigin",DomainName:i,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(h.length>0)f.OriginCustomHeaders=h;let S={Forward:d};if(d==="whitelist"&&m)S.WhitelistedNames=m;let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${g}`,Origins:[f],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:u,Cookies:S}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(s&&a)C.Properties.DistributionConfig.Aliases=[s],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:C,logicalId:y}}static createMultiOriginDistribution(e){let{slug:n,environment:r,s3BucketDomainName:i,albDomainName:s,apiPathPattern:a="/api/*",customDomain:c,certificateArn:u,customOriginHeaders:d={}}=e,m=l({slug:n,environment:r,resourceType:"cdn"}),p=o(m),g=`${p}OAC`,y={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${m}-oac`,Description:`Origin Access Control for ${m}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},h=Object.entries(d).map(([P,E])=>({HeaderName:P,HeaderValue:E})),f={Id:"S3Origin",DomainName:i,OriginAccessControlId:R.Ref(g)},S={Id:"ALBOrigin",DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(h.length>0)S.OriginCustomHeaders=h;let C={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${m}`,DefaultRootObject:"index.html",Origins:[f,S],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:a,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(c&&u)C.Properties.DistributionConfig.Aliases=[c],C.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:C,originAccessControl:y,logicalId:p,oacLogicalId:g}}static addAlbOrigin(e,n){let{originId:r,domainName:i,pathPattern:s,customHeaders:a={},forwardHeaders:c=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:u={default:0,max:0,min:0}}=n,d=Object.entries(a).map(([p,g])=>({HeaderName:p,HeaderValue:g})),m={Id:r,DomainName:i,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(d.length>0)m.OriginCustomHeaders=d;if(!e.Properties.DistributionConfig.Origins)e.Properties.DistributionConfig.Origins=[];if(e.Properties.DistributionConfig.Origins.push(m),!e.Properties.DistributionConfig.CacheBehaviors)e.Properties.DistributionConfig.CacheBehaviors=[];return e.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:s,TargetOriginId:r,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:u.default,MaxTTL:u.max,MinTTL:u.min,ForwardedValues:{QueryString:!0,Headers:c,Cookies:{Forward:"all"}}}),e}static addOriginHeader(e,n,r,i){let s=e.Properties.DistributionConfig.Origins?.find((a)=>a.Id===n);if(s){if(!s.OriginCustomHeaders)s.OriginCustomHeaders=[];s.OriginCustomHeaders.push({HeaderName:r,HeaderValue:i})}return e}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:(e)=>{let{min:n=0,max:r=86400,default:i=86400}=e;return{MinTTL:n,MaxTTL:r,DefaultTTL:i}},cookies:(e,n)=>{let r={Forward:e==="allowList"?"whitelist":e};if(e==="allowList"&&n)r.WhitelistedNames=n;return r},allowedMethods:(e)=>{let n={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[e]||n.GET_HEAD},cachedMethods:(e)=>{let n={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[e]||n.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:(e)=>{let{ttl:n={min:0,max:86400,default:86400},cookies:r="none",allowedCookies:i,allowedMethods:s="GET_HEAD",cachedMethods:a="GET_HEAD",compress:c=!0,forwardQueryString:u=!0,forwardHeaders:d=[]}=e;return{MinTTL:n.min,MaxTTL:n.max,DefaultTTL:n.default,Compress:c,AllowedMethods:Be.Config.allowedMethods(s),CachedMethods:Be.Config.cachedMethods(a),ForwardedValues:{QueryString:u,Headers:d,Cookies:Be.Config.cookies(r,i)}}}};static applyConfig(e,n){let r=e.Properties.DistributionConfig.DefaultCacheBehavior;if(n.ttl)r.MinTTL=n.ttl.min,r.MaxTTL=n.ttl.max,r.DefaultTTL=n.ttl.default;if(n.compress!==void 0)r.Compress=n.compress;if(n.allowedMethods)r.AllowedMethods=Be.Config.allowedMethods(n.allowedMethods);if(n.cachedMethods)r.CachedMethods=Be.Config.cachedMethods(n.cachedMethods);if(n.cookies){if(!r.ForwardedValues)r.ForwardedValues={QueryString:!0};r.ForwardedValues.Cookies=Be.Config.cookies(n.cookies,n.allowedCookies)}return e}}var eu=[403,404,500,502,503,504],Fo="TsCloud::StorageFailover",Bo="AllowCloudFrontFailoverRead",Pr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,Er=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function ua(e){let{failover:n,primaryBucket:r,primaryRegion:i}=e,s=e.where??"storage failover";if(!n||typeof n!=="object")throw Error(`${s}.failover must be an object such as { region: 'us-west-2' }.`);if(!n.region||!Pr.test(n.region))throw Error(`${s}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(n.region)}.`);if(n.region===i)throw Error(`${s}.failover.region is ${n.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let a=n.bucket??`${r}-${n.region}`;if(!Er.test(a)||a.includes("..")){let c=n.bucket===void 0&&a.length>63?` The default name (<primary bucket>-<region>) is ${a.length} characters; S3 allows 63. Set ${s}.failover.bucket.`:"";throw Error(`${s}.failover: "${a}" is not a valid S3 bucket name.${c}`)}if(a===r)throw Error(`${s}.failover.bucket must differ from the primary bucket "${r}".`);return{replicaBucket:a,replicaRegion:n.region,replicate:n.replicate!==!1,statusCodes:Mo(n.statusCodes??eu),primaryConnection:tt(n,`${s}.failover`)}}function pa(e,n){return`${e}.s3.${n}.amazonaws.com`}function ma(e){let n=`arn:aws:s3:::${e.primaryBucket}`,r=`arn:aws:s3:::${e.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...e.roleName?{RoleName:e.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:n},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${n}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${r}/*`}]}}]}}}function ga(e){return{Role:e.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${e.replicaBucket}`}}]}}function fa(e){return{Sid:Bo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${e.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":e.distributionArn}}}}function ha(e){let r=(typeof e==="string"?JSON.parse(e):e)?.Metadata?.[Fo];return Array.isArray(r)?r:[]}class Te{static createHostedZone(e){let{domain:n,slug:r,environment:i,comment:s}=e,a=l({slug:r,environment:i,resourceType:"hostedzone"}),c=o(`${a}-${n.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:n,HostedZoneConfig:{Comment:s||`Hosted zone for ${n}`}}},logicalId:c}}static createRecord(e){let{hostedZoneId:n,hostedZoneName:r,name:i,type:s,ttl:a,values:c,aliasTarget:u}=e,d=o(`record-${i.replace(/\./g,"")}-${s}`),m={Type:"AWS::Route53::RecordSet",Properties:{Name:i,Type:s}};if(n)m.Properties.HostedZoneId=n;else if(r)m.Properties.HostedZoneName=r;if(u)m.Properties.AliasTarget={DNSName:u.dnsName,HostedZoneId:u.hostedZoneId,EvaluateTargetHealth:u.evaluateTargetHealth??!1};else m.Properties.TTL=a||300,m.Properties.ResourceRecords=c||[];return{record:m,logicalId:d}}static createCloudFrontAlias(e,n,r){return Te.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(e,n,r,i){return Te.createRecord({hostedZoneId:i,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:r,evaluateTargetHealth:!0}})}static createCname(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"CNAME",ttl:i,values:[n]})}static createWwwRedirect(e,n){return Te.createRecord({hostedZoneId:n,name:`www.${e}`,type:"CNAME",ttl:300,values:[e]})}static createMxRecords(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"MX",ttl:i,values:n.map((s)=>`${s.priority} ${s.server}`)})}static createTxtRecord(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"TXT",ttl:i,values:[`"${n}"`]})}static createSpfRecord(e,n,r){return Te.createTxtRecord(e,n,r)}static createDmarcRecord(e,n,r,i){let s=`v=DMARC1; p=${n}; rua=mailto:${r}`;return Te.createTxtRecord(`_dmarc.${e}`,s,i)}static createS3WebsiteAlias(e,n,r,i){return Te.createRecord({hostedZoneId:i,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:r,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(e,n){return`${e}.s3-website-${n}.amazonaws.com`}static createStoreRecord(e,n,r){return Te.createCname(`store.${e}`,n,r)}static createApiRecord(e,n,r){return Te.createCname(`api.${e}`,n,r)}static createDocsRecord(e,n,r){return Te.createCname(`docs.${e}`,n,r)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class j{static createCertificate(e){let{domain:n,subdomains:r=[],slug:i,environment:s,validationMethod:a="DNS",hostedZoneId:c}=e,u=l({slug:i,environment:s,resourceType:"acm"}),d=o(`${u}-${n.replace(/\./g,"")}`),m=[n];for(let g of r)if(g==="*")m.push(`*.${n}`);else m.push(`${g}.${n}`);let p={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:m,ValidationMethod:a}};if(a==="DNS"&&c)p.Properties.DomainValidationOptions=m.map((g)=>({DomainName:g,HostedZoneId:c}));return{certificate:p,logicalId:d}}static createKmsKey(e){let{description:n,slug:r,environment:i,enableRotation:s=!0,multiRegion:a=!1}=e,c=l({slug:r,environment:i,resourceType:"kms"}),u=o(c),d={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:R.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:"*"}]},m={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:s,KeyPolicy:d,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:a}},p=o(`${c}-alias`),g={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${r}-${i}`,TargetKeyId:R.Ref(u)}};return{key:m,alias:g,logicalId:u,aliasId:p}}static createFirewall(e){let{slug:n,environment:r,scope:i="CLOUDFRONT",defaultAction:s="allow"}=e,a=l({slug:n,environment:r,resourceType:"waf"}),c=o(a);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:a,Scope:i,DefaultAction:s==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${n} ${r}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${a}-metric`}}},logicalId:c}}static setRateLimit(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static blockCountries(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{GeoMatchStatement:{CountryCodes:n.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static blockIpAddresses(e,n,r,i){let s=l({slug:r,environment:i,resourceType:"ipset"}),a=o(`${s}-${n.name}`),c={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${s}-${n.name}`,Scope:e.Properties.Scope,IPAddressVersion:n.ipVersion||"IPV4",Addresses:n.ipAddresses,Description:`Blocked IPs for ${n.name}`}};if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{IPSetReferenceStatement:{Arn:R.GetAtt(a,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),{webAcl:e,ipSet:c,ipSetLogicalId:a}}static addManagedRules(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r={ManagedRuleGroupStatement:{VendorName:n.vendorName,Name:n.ruleName}};if(n.excludedRules&&n.excludedRules.length>0)r.ManagedRuleGroupStatement.ExcludedRules=n.excludedRules.map((i)=>({Name:i}));return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:r,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}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(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r=n.paths.map((i)=>({SearchString:i,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:r.map((i)=>({ByteMatchStatement:i}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static setHeaderRateLimit(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r={RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:n.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(n.headerValue)r.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:n.headerValue,FieldToMatch:{SingleHeader:{Name:n.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:r,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static protectLoginEndpoint(e,n){let{loginPaths:r,priority:i,requestsPerMinute:s=10}=n;return j.setPathRateLimit(e,{name:"LoginRateLimit",priority:i,requestsPerWindow:s*5,paths:r}),e}static protectApiEndpoints(e,n){let{apiPaths:r,priority:i,requestsPerMinute:s=100}=n;return j.setPathRateLimit(e,{name:"ApiRateLimit",priority:i,requestsPerWindow:s*5,paths:r}),e}static createProtectedFirewall(e){let{slug:n,environment:r,scope:i="CLOUDFRONT",enableBotControl:s=!1,enableRateLimiting:a=!0,rateLimitPerMinute:c=2000}=e,{webAcl:u,logicalId:d}=j.createFirewall({slug:n,environment:r,scope:i,defaultAction:"allow"}),m=0;if(u=j.addManagedRules(u,{name:"AWSIPReputationList",priority:m++,...j.ManagedRuleGroups.AmazonIpReputation}),u=j.addManagedRules(u,{name:"AWSAnonymousIPList",priority:m++,...j.ManagedRuleGroups.AnonymousIpList}),u=j.addManagedRules(u,{name:"AWSCoreRuleSet",priority:m++,...j.ManagedRuleGroups.CoreRuleSet}),u=j.addManagedRules(u,{name:"AWSKnownBadInputs",priority:m++,...j.ManagedRuleGroups.KnownBadInputs}),u=j.addManagedRules(u,{name:"AWSSQLi",priority:m++,...j.ManagedRuleGroups.SqlDatabase}),s)u=j.addManagedRules(u,{name:"AWSBotControl",priority:m++,...j.ManagedRuleGroups.BotControl});if(a)u=j.setRateLimit(u,{name:"GlobalRateLimit",priority:m++,requestsPerWindow:c*5});return{webAcl:u,logicalId:d}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function tu(e){let n=e.split(".")[0]??"";return n==="a1"||/^[a-z]+\d+g[a-z]*$/.test(n)}function ru(e="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${tu(e)?"arm64":"x86_64"}`}function el(e="t3.micro"){return`{{resolve:ssm:${ru(e)}}}`}class b{static createServer(e){let{slug:n,environment:r,instanceType:i="t3.micro",imageId:s=el(i),keyName:a,securityGroupIds:c,subnetId:u,userData:d,volumeSize:m=20,volumeType:p="gp3",encrypted:g=!0}=e,y=l({slug:n,environment:r,resourceType:"ec2"}),h=o(y),f={Type:"AWS::EC2::Instance",Properties:{ImageId:s,InstanceType:i,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}};if(a)f.Properties.KeyName=a;if(c)f.Properties.SecurityGroupIds=c;if(u)f.Properties.SubnetId=u;if(d)f.Properties.UserData=R.Base64(d);return f.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:m,VolumeType:p,Encrypted:g,DeleteOnTermination:!0}}],{instance:f,logicalId:h}}static createSecurityGroup(e){let{slug:n,environment:r,vpcId:i,description:s,ingress:a=[],egress:c=[]}=e,u=l({slug:n,environment:r,resourceType:"sg"}),d=o(u),m={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:s||`Security group for ${n} ${r}`,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(i)m.Properties.VpcId=i;if(a.length>0)m.Properties.SecurityGroupIngress=a.map((p)=>({IpProtocol:p.protocol,FromPort:p.fromPort,ToPort:p.toPort,CidrIp:p.cidr,SourceSecurityGroupId:p.sourceSecurityGroupId}));if(c.length>0)m.Properties.SecurityGroupEgress=c.map((p)=>({IpProtocol:p.protocol,FromPort:p.fromPort,ToPort:p.toPort,CidrIp:p.cidr,DestinationSecurityGroupId:p.sourceSecurityGroupId}));return{securityGroup:m,logicalId:d}}static createWebServerSecurityGroup(e,n,r){return b.createSecurityGroup({slug:e,environment:n,vpcId:r,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(e){let{slug:n,environment:r,scheme:i="internet-facing",subnets:s,securityGroups:a,type:c="application"}=e,u=l({slug:n,environment:r,resourceType:"alb"}),d=o(u),m={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:u,Scheme:i,Type:c,Subnets:s,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(a)m.Properties.SecurityGroups=a;return{loadBalancer:m,logicalId:d}}static createTargetGroup(e){let{slug:n,environment:r,port:i,protocol:s="HTTP",vpcId:a,targetType:c="ip",healthCheckPath:u="/",healthCheckInterval:d=30,healthCheckTimeout:m=5,healthyThreshold:p=2,unhealthyThreshold:g=3}=e,y=l({slug:n,environment:r,resourceType:"tg"}),h=o(y);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:y,Port:i,Protocol:s,VpcId:a,TargetType:c,HealthCheckEnabled:!0,HealthCheckProtocol:s,HealthCheckPath:u,HealthCheckIntervalSeconds:d,HealthCheckTimeoutSeconds:m,HealthyThresholdCount:p,UnhealthyThresholdCount:g,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}},logicalId:h}}static createListener(e,n){let{port:r,protocol:i="HTTP",certificateArn:s,defaultTargetGroupArn:a}=n,c=o(`listener-${e}-${r}`),u={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:R.Ref(e),Port:r,Protocol:i,DefaultActions:[{Type:"forward",TargetGroupArn:a}]}};if(i==="HTTPS"&&s)u.Properties.Certificates=[{CertificateArn:s}],u.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:u,logicalId:c}}static createEcsCluster(e,n){let r=l({slug:e,environment:n,resourceType:"ecs-cluster"}),i=o(r);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:r,Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static createFargateService(e){let{slug:n,environment:r,image:i,cpu:s="256",memory:a="512",desiredCount:c=1,containerPort:u=8080,environmentVariables:d={},secrets:m=[],healthCheck:p,logGroup:g,subnets:y,securityGroups:h,targetGroupArn:f}=e,{cluster:S,logicalId:C}=b.createEcsCluster(n,r),P=l({slug:n,environment:r,resourceType:"fargate"}),E=o(`${P}-execution-role`),v={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"]}},I=o(`${P}-task-role`),D={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},x=o(`${P}-task`),F={Type:"AWS::ECS::TaskDefinition",Properties:{Family:P,TaskRoleArn:R.GetAtt(I,"Arn"),ExecutionRoleArn:R.GetAtt(E,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:s,Memory:a,ContainerDefinitions:[{Name:n,Image:i,Essential:!0,PortMappings:[{ContainerPort:u,Protocol:"tcp"}],Environment:Object.entries(d).map(([G,U])=>({Name:G,Value:U})),Secrets:m.map((G)=>({Name:G.name,ValueFrom:G.valueFrom}))}],Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}};if(p)F.Properties.ContainerDefinitions[0].HealthCheck={Command:p.command,Interval:p.interval||30,Timeout:p.timeout||5,Retries:p.retries||3,StartPeriod:60};if(g)F.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":g,"awslogs-region":R.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let M=o(`${P}-service`),O={Type:"AWS::ECS::Service",Properties:{ServiceName:P,Cluster:R.Ref(C),TaskDefinition:R.Ref(x),DesiredCount:c,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:y,SecurityGroups:h,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}};if(f)O.Properties.LoadBalancers=[{TargetGroupArn:f,ContainerName:n,ContainerPort:u}];return{cluster:S,taskDefinition:F,service:O,taskRole:D,executionRole:v,clusterLogicalId:C,taskDefinitionLogicalId:x,serviceLogicalId:M,taskRoleLogicalId:I,executionRoleLogicalId:E}}static createLambdaFunction(e){let{slug:n,environment:r,runtime:i,handler:s,code:a,timeout:c=30,memorySize:u=128,environmentVariables:d={},vpcConfig:m}=e,p=l({slug:n,environment:r,resourceType:"lambda"}),g=o(p),y=o(`${p}-role`),h={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(m)h.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let f={Type:"AWS::Lambda::Function",Properties:{FunctionName:p,Runtime:i,Role:R.GetAtt(y,"Arn"),Handler:s,Code:{...a.s3Bucket&&{S3Bucket:a.s3Bucket},...a.s3Key&&{S3Key:a.s3Key},...a.zipFile&&{ZipFile:a.zipFile}},Timeout:c,MemorySize:u,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r}]}};if(Object.keys(d).length>0)f.Properties.Environment={Variables:d};if(m)f.Properties.VpcConfig={SecurityGroupIds:m.securityGroupIds,SubnetIds:m.subnetIds};return{lambdaFunction:f,role:h,logicalId:g,roleLogicalId:y}}static generateNodeServerUserData(e={}){let{nodeVersion:n="20",appRepo:r,environment:i={}}=e,s=Object.entries(i).map(([a,c])=>`echo "export ${a}='${c}'" >> /etc/environment`).join(`
200
+ `.trim()};static Config={ttl:(e)=>{let{min:n=0,max:r=86400,default:i=86400}=e;return{MinTTL:n,MaxTTL:r,DefaultTTL:i}},cookies:(e,n)=>{let r={Forward:e==="allowList"?"whitelist":e};if(e==="allowList"&&n)r.WhitelistedNames=n;return r},allowedMethods:(e)=>{let n={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[e]||n.GET_HEAD},cachedMethods:(e)=>{let n={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[e]||n.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:(e)=>{let{ttl:n={min:0,max:86400,default:86400},cookies:r="none",allowedCookies:i,allowedMethods:s="GET_HEAD",cachedMethods:a="GET_HEAD",compress:c=!0,forwardQueryString:u=!0,forwardHeaders:d=[]}=e;return{MinTTL:n.min,MaxTTL:n.max,DefaultTTL:n.default,Compress:c,AllowedMethods:je.Config.allowedMethods(s),CachedMethods:je.Config.cachedMethods(a),ForwardedValues:{QueryString:u,Headers:d,Cookies:je.Config.cookies(r,i)}}}};static applyConfig(e,n){let r=e.Properties.DistributionConfig.DefaultCacheBehavior;if(n.ttl)r.MinTTL=n.ttl.min,r.MaxTTL=n.ttl.max,r.DefaultTTL=n.ttl.default;if(n.compress!==void 0)r.Compress=n.compress;if(n.allowedMethods)r.AllowedMethods=je.Config.allowedMethods(n.allowedMethods);if(n.cachedMethods)r.CachedMethods=je.Config.cachedMethods(n.cachedMethods);if(n.cookies){if(!r.ForwardedValues)r.ForwardedValues={QueryString:!0};r.ForwardedValues.Cookies=je.Config.cookies(n.cookies,n.allowedCookies)}return e}}var iu=[403,404,500,502,503,504],zo="TsCloud::StorageFailover",Ho="AllowCloudFrontFailoverRead",Pr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,Er=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function fa(e){let{failover:n,primaryBucket:r,primaryRegion:i}=e,s=e.where??"storage failover";if(!n||typeof n!=="object")throw Error(`${s}.failover must be an object such as { region: 'us-west-2' }.`);if(!n.region||!Pr.test(n.region))throw Error(`${s}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(n.region)}.`);if(n.region===i)throw Error(`${s}.failover.region is ${n.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let a=n.bucket??`${r}-${n.region}`;if(!Er.test(a)||a.includes("..")){let c=n.bucket===void 0&&a.length>63?` The default name (<primary bucket>-<region>) is ${a.length} characters; S3 allows 63. Set ${s}.failover.bucket.`:"";throw Error(`${s}.failover: "${a}" is not a valid S3 bucket name.${c}`)}if(a===r)throw Error(`${s}.failover.bucket must differ from the primary bucket "${r}".`);return{replicaBucket:a,replicaRegion:n.region,replicate:n.replicate!==!1,statusCodes:jo(n.statusCodes??iu),primaryConnection:tt(n,`${s}.failover`)}}function ha(e,n){return`${e}.s3.${n}.amazonaws.com`}function ya(e){let n=`arn:aws:s3:::${e.primaryBucket}`,r=`arn:aws:s3:::${e.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...e.roleName?{RoleName:e.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:n},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${n}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${r}/*`}]}}]}}}function ba(e){return{Role:e.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${e.replicaBucket}`}}]}}function Sa(e){return{Sid:Ho,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${e.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":e.distributionArn}}}}function va(e){let r=(typeof e==="string"?JSON.parse(e):e)?.Metadata?.[zo];return Array.isArray(r)?r:[]}class Te{static createHostedZone(e){let{domain:n,slug:r,environment:i,comment:s}=e,a=l({slug:r,environment:i,resourceType:"hostedzone"}),c=o(`${a}-${n.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:n,HostedZoneConfig:{Comment:s||`Hosted zone for ${n}`}}},logicalId:c}}static createRecord(e){let{hostedZoneId:n,hostedZoneName:r,name:i,type:s,ttl:a,values:c,aliasTarget:u}=e,d=o(`record-${i.replace(/\./g,"")}-${s}`),m={Type:"AWS::Route53::RecordSet",Properties:{Name:i,Type:s}};if(n)m.Properties.HostedZoneId=n;else if(r)m.Properties.HostedZoneName=r;if(u)m.Properties.AliasTarget={DNSName:u.dnsName,HostedZoneId:u.hostedZoneId,EvaluateTargetHealth:u.evaluateTargetHealth??!1};else m.Properties.TTL=a||300,m.Properties.ResourceRecords=c||[];return{record:m,logicalId:d}}static createCloudFrontAlias(e,n,r){return Te.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(e,n,r,i){return Te.createRecord({hostedZoneId:i,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:r,evaluateTargetHealth:!0}})}static createCname(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"CNAME",ttl:i,values:[n]})}static createWwwRedirect(e,n){return Te.createRecord({hostedZoneId:n,name:`www.${e}`,type:"CNAME",ttl:300,values:[e]})}static createMxRecords(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"MX",ttl:i,values:n.map((s)=>`${s.priority} ${s.server}`)})}static createTxtRecord(e,n,r,i=300){return Te.createRecord({hostedZoneId:r,name:e,type:"TXT",ttl:i,values:[`"${n}"`]})}static createSpfRecord(e,n,r){return Te.createTxtRecord(e,n,r)}static createDmarcRecord(e,n,r,i){let s=`v=DMARC1; p=${n}; rua=mailto:${r}`;return Te.createTxtRecord(`_dmarc.${e}`,s,i)}static createS3WebsiteAlias(e,n,r,i){return Te.createRecord({hostedZoneId:i,name:e,type:"A",aliasTarget:{dnsName:n,hostedZoneId:r,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(e,n){return`${e}.s3-website-${n}.amazonaws.com`}static createStoreRecord(e,n,r){return Te.createCname(`store.${e}`,n,r)}static createApiRecord(e,n,r){return Te.createCname(`api.${e}`,n,r)}static createDocsRecord(e,n,r){return Te.createCname(`docs.${e}`,n,r)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class j{static createCertificate(e){let{domain:n,subdomains:r=[],slug:i,environment:s,validationMethod:a="DNS",hostedZoneId:c}=e,u=l({slug:i,environment:s,resourceType:"acm"}),d=o(`${u}-${n.replace(/\./g,"")}`),m=[n];for(let g of r)if(g==="*")m.push(`*.${n}`);else m.push(`${g}.${n}`);let p={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:m,ValidationMethod:a}};if(a==="DNS"&&c)p.Properties.DomainValidationOptions=m.map((g)=>({DomainName:g,HostedZoneId:c}));return{certificate:p,logicalId:d}}static createKmsKey(e){let{description:n,slug:r,environment:i,enableRotation:s=!0,multiRegion:a=!1}=e,c=l({slug:r,environment:i,resourceType:"kms"}),u=o(c),d={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:R.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:"*"}]},m={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:s,KeyPolicy:d,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:a}},p=o(`${c}-alias`),g={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${r}-${i}`,TargetKeyId:R.Ref(u)}};return{key:m,alias:g,logicalId:u,aliasId:p}}static createFirewall(e){let{slug:n,environment:r,scope:i="CLOUDFRONT",defaultAction:s="allow"}=e,a=l({slug:n,environment:r,resourceType:"waf"}),c=o(a);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:a,Scope:i,DefaultAction:s==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${n} ${r}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${a}-metric`}}},logicalId:c}}static setRateLimit(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static blockCountries(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{GeoMatchStatement:{CountryCodes:n.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static blockIpAddresses(e,n,r,i){let s=l({slug:r,environment:i,resourceType:"ipset"}),a=o(`${s}-${n.name}`),c={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${s}-${n.name}`,Scope:e.Properties.Scope,IPAddressVersion:n.ipVersion||"IPV4",Addresses:n.ipAddresses,Description:`Blocked IPs for ${n.name}`}};if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{IPSetReferenceStatement:{Arn:R.GetAtt(a,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),{webAcl:e,ipSet:c,ipSetLogicalId:a}}static addManagedRules(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r={ManagedRuleGroupStatement:{VendorName:n.vendorName,Name:n.ruleName}};if(n.excludedRules&&n.excludedRules.length>0)r.ManagedRuleGroupStatement.ExcludedRules=n.excludedRules.map((i)=>({Name:i}));return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:r,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}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(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r=n.paths.map((i)=>({SearchString:i,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:r.map((i)=>({ByteMatchStatement:i}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static setHeaderRateLimit(e,n){if(!e.Properties.Rules)e.Properties.Rules=[];let r={RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:n.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(n.headerValue)r.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:n.headerValue,FieldToMatch:{SingleHeader:{Name:n.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return e.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:r,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),e}static protectLoginEndpoint(e,n){let{loginPaths:r,priority:i,requestsPerMinute:s=10}=n;return j.setPathRateLimit(e,{name:"LoginRateLimit",priority:i,requestsPerWindow:s*5,paths:r}),e}static protectApiEndpoints(e,n){let{apiPaths:r,priority:i,requestsPerMinute:s=100}=n;return j.setPathRateLimit(e,{name:"ApiRateLimit",priority:i,requestsPerWindow:s*5,paths:r}),e}static createProtectedFirewall(e){let{slug:n,environment:r,scope:i="CLOUDFRONT",enableBotControl:s=!1,enableRateLimiting:a=!0,rateLimitPerMinute:c=2000}=e,{webAcl:u,logicalId:d}=j.createFirewall({slug:n,environment:r,scope:i,defaultAction:"allow"}),m=0;if(u=j.addManagedRules(u,{name:"AWSIPReputationList",priority:m++,...j.ManagedRuleGroups.AmazonIpReputation}),u=j.addManagedRules(u,{name:"AWSAnonymousIPList",priority:m++,...j.ManagedRuleGroups.AnonymousIpList}),u=j.addManagedRules(u,{name:"AWSCoreRuleSet",priority:m++,...j.ManagedRuleGroups.CoreRuleSet}),u=j.addManagedRules(u,{name:"AWSKnownBadInputs",priority:m++,...j.ManagedRuleGroups.KnownBadInputs}),u=j.addManagedRules(u,{name:"AWSSQLi",priority:m++,...j.ManagedRuleGroups.SqlDatabase}),s)u=j.addManagedRules(u,{name:"AWSBotControl",priority:m++,...j.ManagedRuleGroups.BotControl});if(a)u=j.setRateLimit(u,{name:"GlobalRateLimit",priority:m++,requestsPerWindow:c*5});return{webAcl:u,logicalId:d}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function ou(e){let n=e.split(".")[0]??"";return n==="a1"||/^[a-z]+\d+g[a-z]*$/.test(n)}function su(e="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${ou(e)?"arm64":"x86_64"}`}function il(e="t3.micro"){return`{{resolve:ssm:${su(e)}}}`}class b{static createServer(e){let{slug:n,environment:r,instanceType:i="t3.micro",imageId:s=il(i),keyName:a,securityGroupIds:c,subnetId:u,userData:d,volumeSize:m=20,volumeType:p="gp3",encrypted:g=!0}=e,y=l({slug:n,environment:r,resourceType:"ec2"}),h=o(y),f={Type:"AWS::EC2::Instance",Properties:{ImageId:s,InstanceType:i,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}};if(a)f.Properties.KeyName=a;if(c)f.Properties.SecurityGroupIds=c;if(u)f.Properties.SubnetId=u;if(d)f.Properties.UserData=R.Base64(d);return f.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:m,VolumeType:p,Encrypted:g,DeleteOnTermination:!0}}],{instance:f,logicalId:h}}static createSecurityGroup(e){let{slug:n,environment:r,vpcId:i,description:s,ingress:a=[],egress:c=[]}=e,u=l({slug:n,environment:r,resourceType:"sg"}),d=o(u),m={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:s||`Security group for ${n} ${r}`,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(i)m.Properties.VpcId=i;if(a.length>0)m.Properties.SecurityGroupIngress=a.map((p)=>({IpProtocol:p.protocol,FromPort:p.fromPort,ToPort:p.toPort,CidrIp:p.cidr,SourceSecurityGroupId:p.sourceSecurityGroupId}));if(c.length>0)m.Properties.SecurityGroupEgress=c.map((p)=>({IpProtocol:p.protocol,FromPort:p.fromPort,ToPort:p.toPort,CidrIp:p.cidr,DestinationSecurityGroupId:p.sourceSecurityGroupId}));return{securityGroup:m,logicalId:d}}static createWebServerSecurityGroup(e,n,r){return b.createSecurityGroup({slug:e,environment:n,vpcId:r,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(e){let{slug:n,environment:r,scheme:i="internet-facing",subnets:s,securityGroups:a,type:c="application"}=e,u=l({slug:n,environment:r,resourceType:"alb"}),d=o(u),m={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:u,Scheme:i,Type:c,Subnets:s,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(a)m.Properties.SecurityGroups=a;return{loadBalancer:m,logicalId:d}}static createTargetGroup(e){let{slug:n,environment:r,port:i,protocol:s="HTTP",vpcId:a,targetType:c="ip",healthCheckPath:u="/",healthCheckInterval:d=30,healthCheckTimeout:m=5,healthyThreshold:p=2,unhealthyThreshold:g=3}=e,y=l({slug:n,environment:r,resourceType:"tg"}),h=o(y);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:y,Port:i,Protocol:s,VpcId:a,TargetType:c,HealthCheckEnabled:!0,HealthCheckProtocol:s,HealthCheckPath:u,HealthCheckIntervalSeconds:d,HealthCheckTimeoutSeconds:m,HealthyThresholdCount:p,UnhealthyThresholdCount:g,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}},logicalId:h}}static createListener(e,n){let{port:r,protocol:i="HTTP",certificateArn:s,defaultTargetGroupArn:a}=n,c=o(`listener-${e}-${r}`),u={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:R.Ref(e),Port:r,Protocol:i,DefaultActions:[{Type:"forward",TargetGroupArn:a}]}};if(i==="HTTPS"&&s)u.Properties.Certificates=[{CertificateArn:s}],u.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:u,logicalId:c}}static createEcsCluster(e,n){let r=l({slug:e,environment:n,resourceType:"ecs-cluster"}),i=o(r);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:r,Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static createFargateService(e){let{slug:n,environment:r,image:i,cpu:s="256",memory:a="512",desiredCount:c=1,containerPort:u=8080,environmentVariables:d={},secrets:m=[],healthCheck:p,logGroup:g,subnets:y,securityGroups:h,targetGroupArn:f}=e,{cluster:S,logicalId:C}=b.createEcsCluster(n,r),P=l({slug:n,environment:r,resourceType:"fargate"}),E=o(`${P}-execution-role`),v={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"]}},I=o(`${P}-task-role`),D={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},N=o(`${P}-task`),B={Type:"AWS::ECS::TaskDefinition",Properties:{Family:P,TaskRoleArn:R.GetAtt(I,"Arn"),ExecutionRoleArn:R.GetAtt(E,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:s,Memory:a,ContainerDefinitions:[{Name:n,Image:i,Essential:!0,PortMappings:[{ContainerPort:u,Protocol:"tcp"}],Environment:Object.entries(d).map(([G,U])=>({Name:G,Value:U})),Secrets:m.map((G)=>({Name:G.name,ValueFrom:G.valueFrom}))}],Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}};if(p)B.Properties.ContainerDefinitions[0].HealthCheck={Command:p.command,Interval:p.interval||30,Timeout:p.timeout||5,Retries:p.retries||3,StartPeriod:60};if(g)B.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":g,"awslogs-region":R.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let M=o(`${P}-service`),O={Type:"AWS::ECS::Service",Properties:{ServiceName:P,Cluster:R.Ref(C),TaskDefinition:R.Ref(N),DesiredCount:c,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:y,SecurityGroups:h,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}};if(f)O.Properties.LoadBalancers=[{TargetGroupArn:f,ContainerName:n,ContainerPort:u}];return{cluster:S,taskDefinition:B,service:O,taskRole:D,executionRole:v,clusterLogicalId:C,taskDefinitionLogicalId:N,serviceLogicalId:M,taskRoleLogicalId:I,executionRoleLogicalId:E}}static createLambdaFunction(e){let{slug:n,environment:r,runtime:i,handler:s,code:a,timeout:c=30,memorySize:u=128,environmentVariables:d={},vpcConfig:m}=e,p=l({slug:n,environment:r,resourceType:"lambda"}),g=o(p),y=o(`${p}-role`),h={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(m)h.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let f={Type:"AWS::Lambda::Function",Properties:{FunctionName:p,Runtime:i,Role:R.GetAtt(y,"Arn"),Handler:s,Code:{...a.s3Bucket&&{S3Bucket:a.s3Bucket},...a.s3Key&&{S3Key:a.s3Key},...a.zipFile&&{ZipFile:a.zipFile}},Timeout:c,MemorySize:u,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r}]}};if(Object.keys(d).length>0)f.Properties.Environment={Variables:d};if(m)f.Properties.VpcConfig={SecurityGroupIds:m.securityGroupIds,SubnetIds:m.subnetIds};return{lambdaFunction:f,role:h,logicalId:g,roleLogicalId:y}}static generateNodeServerUserData(e={}){let{nodeVersion:n="20",appRepo:r,environment:i={}}=e,s=Object.entries(i).map(([a,c])=>`echo "export ${a}='${c}'" >> /etc/environment`).join(`
201
201
  `);return`#!/bin/bash
202
202
  # Update system
203
203
  yum update -y
@@ -298,19 +298,19 @@ systemctl enable caddy
298
298
  systemctl start caddy
299
299
 
300
300
  echo "Bun server setup complete!"
301
- `}static createLaunchConfiguration(e){let{slug:n,environment:r,imageId:i,instanceType:s,keyName:a,securityGroups:c,userData:u,volumeSize:d=20,volumeType:m="gp3",encrypted:p=!0,iamInstanceProfile:g}=e,y=l({slug:n,environment:r,resourceType:"launch-config"}),h=o(y),f={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:i,InstanceType:s,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:d,VolumeType:m,Encrypted:p,DeleteOnTermination:!0}}]}};if(a)f.Properties.KeyName=a;if(c)f.Properties.SecurityGroups=c;if(u)f.Properties.UserData=R.Base64(u);if(g)f.Properties.IamInstanceProfile=g;return{launchConfiguration:f,logicalId:h}}static createAutoScalingGroup(e){let{slug:n,environment:r,launchConfigurationName:i,minSize:s,maxSize:a,desiredCapacity:c,vpcZoneIdentifier:u,targetGroupArns:d,healthCheckType:m="EC2",healthCheckGracePeriod:p=300,cooldown:g=300,tags:y={}}=e,h=l({slug:n,environment:r,resourceType:"asg"}),f=o(h),S={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:h,LaunchConfigurationName:i,MinSize:s,MaxSize:a,HealthCheckType:m,HealthCheckGracePeriod:p,Cooldown:g,Tags:[{Key:"Name",Value:h,PropagateAtLaunch:!0},{Key:"Environment",Value:r,PropagateAtLaunch:!0},...Object.entries(y).map(([C,P])=>({Key:C,Value:P,PropagateAtLaunch:!0}))]}};if(c!==void 0)S.Properties.DesiredCapacity=c;if(u)S.Properties.VPCZoneIdentifier=u;if(d)S.Properties.TargetGroupARNs=d;return S.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,s-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:S,logicalId:f}}static createScalingPolicy(e){let{slug:n,environment:r,autoScalingGroupName:i,policyType:s="TargetTrackingScaling",targetValue:a=70,predefinedMetricType:c="ASGAverageCPUUtilization"}=e,u=l({slug:n,environment:r,resourceType:"scaling-policy"}),d=o(u),m={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:i,PolicyType:s}};if(s==="TargetTrackingScaling")m.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:c},TargetValue:a};return{scalingPolicy:m,logicalId:d}}static AutoScaling={smallWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(e,n,r,i=70)=>b.createScalingPolicy({slug:e,environment:n,autoScalingGroupName:r,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:i}),requestCountScaling:(e,n,r,i=1000)=>b.createScalingPolicy({slug:e,environment:n,autoScalingGroupName:r,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:i})};static Secrets={fromSecretsManager:(e)=>Object.entries(e).map(([n,r])=>({name:n,valueFrom:r})),fromJsonSecret:(e,n)=>`${e}:${n}::`,fromSecretVersion:(e,n)=>`${e}::${n}:`,fromSecretVersionStage:(e,n)=>`${e}:::${n}`,createAccessPolicy:(e)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:e}]}}),createKmsPolicy:(e)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:e}]}}),buildSecretArn:(e)=>`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretName}`,buildSecretArnPattern:(e)=>{let n=e.region||"*",r=e.accountId||"*";return`arn:aws:secretsmanager:${n}:${r}:secret:${e.secretNamePrefix}*`},commonAppSecrets:(e)=>({DATABASE_URL:`${e}/database-url`,DATABASE_PASSWORD:`${e}/database-password`,REDIS_URL:`${e}/redis-url`,REDIS_PASSWORD:`${e}/redis-password`,API_KEY:`${e}/api-key`,JWT_SECRET:`${e}/jwt-secret`,ENCRYPTION_KEY:`${e}/encryption-key`,AWS_ACCESS_KEY_ID:`${e}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${e}/aws-secret-access-key`,MAIL_PASSWORD:`${e}/mail-password`,STRIPE_SECRET_KEY:`${e}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${e}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(e){let{secretArns:n=[],kmsKeyArns:r=[],...i}=e,s=b.createFargateService(i);if(n.length>0){if(!s.executionRole.Properties.Policies)s.executionRole.Properties.Policies=[];if(s.executionRole.Properties.Policies.push(b.Secrets.createAccessPolicy(n)),r.length>0)s.executionRole.Properties.Policies.push(b.Secrets.createKmsPolicy(r))}return s}static generateSecretReferences(e){return e.secrets.map((n)=>{let r=`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretPrefix}/${n}`;return{name:n.toUpperCase().replace(/-/g,"_"),valueFrom:r}})}static EnvSecrets={database:(e)=>[{name:"DB_HOST",valueFrom:`${e}:host::`},{name:"DB_PORT",valueFrom:`${e}:port::`},{name:"DB_USERNAME",valueFrom:`${e}:username::`},{name:"DB_PASSWORD",valueFrom:`${e}:password::`},{name:"DB_NAME",valueFrom:`${e}:dbname::`}],redis:(e)=>[{name:"REDIS_HOST",valueFrom:`${e}:host::`},{name:"REDIS_PORT",valueFrom:`${e}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${e}:password::`}],apiCredentials:(e)=>[{name:"API_KEY",valueFrom:`${e}:apiKey::`},{name:"API_SECRET",valueFrom:`${e}:apiSecret::`}],mail:(e)=>[{name:"MAIL_HOST",valueFrom:`${e}:host::`},{name:"MAIL_PORT",valueFrom:`${e}:port::`},{name:"MAIL_USERNAME",valueFrom:`${e}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${e}:password::`}],awsCredentials:(e)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${e}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${e}:secretAccessKey::`}]};static createJumpBox(e){let{slug:n,environment:r,vpcId:i,subnetId:s,keyName:a,instanceType:c="t3.micro",imageId:u=el(c),mountEfs:d,databaseTools:m=!1}=e,p=e.allowedCidrs??(a?["0.0.0.0/0"]:[]),g=l({slug:n,environment:r,resourceType:"jumpbox"}),y=o(`${g}-sg`),h={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${g}-sg`,GroupDescription:`Security group for ${g} JumpBox access`,VpcId:i,SecurityGroupIngress:p.map((x)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:x,Description:`SSH access from ${x}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${g}-sg`},{Key:"Environment",Value:r}]}},f=o(`${g}-role`),S={Type:"AWS::IAM::Role",Properties:{RoleName:`${g}-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:d?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},C=o(`${g}-profile`),P={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${g}-profile`,Roles:[R.Ref(f)]}},E=`#!/bin/bash
301
+ `}static createLaunchConfiguration(e){let{slug:n,environment:r,imageId:i,instanceType:s,keyName:a,securityGroups:c,userData:u,volumeSize:d=20,volumeType:m="gp3",encrypted:p=!0,iamInstanceProfile:g}=e,y=l({slug:n,environment:r,resourceType:"launch-config"}),h=o(y),f={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:i,InstanceType:s,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:d,VolumeType:m,Encrypted:p,DeleteOnTermination:!0}}]}};if(a)f.Properties.KeyName=a;if(c)f.Properties.SecurityGroups=c;if(u)f.Properties.UserData=R.Base64(u);if(g)f.Properties.IamInstanceProfile=g;return{launchConfiguration:f,logicalId:h}}static createAutoScalingGroup(e){let{slug:n,environment:r,launchConfigurationName:i,minSize:s,maxSize:a,desiredCapacity:c,vpcZoneIdentifier:u,targetGroupArns:d,healthCheckType:m="EC2",healthCheckGracePeriod:p=300,cooldown:g=300,tags:y={}}=e,h=l({slug:n,environment:r,resourceType:"asg"}),f=o(h),S={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:h,LaunchConfigurationName:i,MinSize:s,MaxSize:a,HealthCheckType:m,HealthCheckGracePeriod:p,Cooldown:g,Tags:[{Key:"Name",Value:h,PropagateAtLaunch:!0},{Key:"Environment",Value:r,PropagateAtLaunch:!0},...Object.entries(y).map(([C,P])=>({Key:C,Value:P,PropagateAtLaunch:!0}))]}};if(c!==void 0)S.Properties.DesiredCapacity=c;if(u)S.Properties.VPCZoneIdentifier=u;if(d)S.Properties.TargetGroupARNs=d;return S.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,s-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:S,logicalId:f}}static createScalingPolicy(e){let{slug:n,environment:r,autoScalingGroupName:i,policyType:s="TargetTrackingScaling",targetValue:a=70,predefinedMetricType:c="ASGAverageCPUUtilization"}=e,u=l({slug:n,environment:r,resourceType:"scaling-policy"}),d=o(u),m={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:i,PolicyType:s}};if(s==="TargetTrackingScaling")m.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:c},TargetValue:a};return{scalingPolicy:m,logicalId:d}}static AutoScaling={smallWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(e,n,r,i,s)=>b.createAutoScalingGroup({slug:e,environment:n,launchConfigurationName:r,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:i,targetGroupArns:s,healthCheckType:s?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(e,n,r,i=70)=>b.createScalingPolicy({slug:e,environment:n,autoScalingGroupName:r,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:i}),requestCountScaling:(e,n,r,i=1000)=>b.createScalingPolicy({slug:e,environment:n,autoScalingGroupName:r,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:i})};static Secrets={fromSecretsManager:(e)=>Object.entries(e).map(([n,r])=>({name:n,valueFrom:r})),fromJsonSecret:(e,n)=>`${e}:${n}::`,fromSecretVersion:(e,n)=>`${e}::${n}:`,fromSecretVersionStage:(e,n)=>`${e}:::${n}`,createAccessPolicy:(e)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:e}]}}),createKmsPolicy:(e)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:e}]}}),buildSecretArn:(e)=>`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretName}`,buildSecretArnPattern:(e)=>{let n=e.region||"*",r=e.accountId||"*";return`arn:aws:secretsmanager:${n}:${r}:secret:${e.secretNamePrefix}*`},commonAppSecrets:(e)=>({DATABASE_URL:`${e}/database-url`,DATABASE_PASSWORD:`${e}/database-password`,REDIS_URL:`${e}/redis-url`,REDIS_PASSWORD:`${e}/redis-password`,API_KEY:`${e}/api-key`,JWT_SECRET:`${e}/jwt-secret`,ENCRYPTION_KEY:`${e}/encryption-key`,AWS_ACCESS_KEY_ID:`${e}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${e}/aws-secret-access-key`,MAIL_PASSWORD:`${e}/mail-password`,STRIPE_SECRET_KEY:`${e}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${e}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(e){let{secretArns:n=[],kmsKeyArns:r=[],...i}=e,s=b.createFargateService(i);if(n.length>0){if(!s.executionRole.Properties.Policies)s.executionRole.Properties.Policies=[];if(s.executionRole.Properties.Policies.push(b.Secrets.createAccessPolicy(n)),r.length>0)s.executionRole.Properties.Policies.push(b.Secrets.createKmsPolicy(r))}return s}static generateSecretReferences(e){return e.secrets.map((n)=>{let r=`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretPrefix}/${n}`;return{name:n.toUpperCase().replace(/-/g,"_"),valueFrom:r}})}static EnvSecrets={database:(e)=>[{name:"DB_HOST",valueFrom:`${e}:host::`},{name:"DB_PORT",valueFrom:`${e}:port::`},{name:"DB_USERNAME",valueFrom:`${e}:username::`},{name:"DB_PASSWORD",valueFrom:`${e}:password::`},{name:"DB_NAME",valueFrom:`${e}:dbname::`}],redis:(e)=>[{name:"REDIS_HOST",valueFrom:`${e}:host::`},{name:"REDIS_PORT",valueFrom:`${e}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${e}:password::`}],apiCredentials:(e)=>[{name:"API_KEY",valueFrom:`${e}:apiKey::`},{name:"API_SECRET",valueFrom:`${e}:apiSecret::`}],mail:(e)=>[{name:"MAIL_HOST",valueFrom:`${e}:host::`},{name:"MAIL_PORT",valueFrom:`${e}:port::`},{name:"MAIL_USERNAME",valueFrom:`${e}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${e}:password::`}],awsCredentials:(e)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${e}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${e}:secretAccessKey::`}]};static createJumpBox(e){let{slug:n,environment:r,vpcId:i,subnetId:s,keyName:a,instanceType:c="t3.micro",imageId:u=il(c),mountEfs:d,databaseTools:m=!1}=e,p=e.allowedCidrs??(a?["0.0.0.0/0"]:[]),g=l({slug:n,environment:r,resourceType:"jumpbox"}),y=o(`${g}-sg`),h={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${g}-sg`,GroupDescription:`Security group for ${g} JumpBox access`,VpcId:i,SecurityGroupIngress:p.map((N)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:N,Description:`SSH access from ${N}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${g}-sg`},{Key:"Environment",Value:r}]}},f=o(`${g}-role`),S={Type:"AWS::IAM::Role",Properties:{RoleName:`${g}-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:d?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},C=o(`${g}-profile`),P={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${g}-profile`,Roles:[R.Ref(f)]}},E=`#!/bin/bash
302
302
  dnf install -y amazon-efs-utils nfs-utils jq wget htop
303
303
  `;if(m)E+=`
304
304
  # Database clients: psql, mysql (MariaDB), redis-cli
305
305
  dnf install -y postgresql16 mariadb105 redis6
306
- `;if(d){let x=d.mountPath||"/mnt/efs";E+=`
306
+ `;if(d){let N=d.mountPath||"/mnt/efs";E+=`
307
307
  # Mount EFS
308
- mkdir -p ${x}
308
+ mkdir -p ${N}
309
309
  for attempt in $(seq 1 30); do
310
- mount -t efs -o tls \${FileSystemId}:/ ${x} && break
310
+ mount -t efs -o tls \${FileSystemId}:/ ${N} && break
311
311
  sleep 10
312
312
  done
313
- echo "\${FileSystemId}:/ ${x} efs _netdev,tls,nofail 0 0" >> /etc/fstab
313
+ echo "\${FileSystemId}:/ ${N} efs _netdev,tls,nofail 0 0" >> /etc/fstab
314
314
  `}let v=o(g),I={Type:"AWS::EC2::Instance",DependsOn:[C],Properties:{ImageId:u,InstanceType:c,SubnetId:s,SecurityGroupIds:[R.Ref(y)],IamInstanceProfile:R.Ref(C),UserData:d?{"Fn::Base64":R.Sub(E,{FileSystemId:d.fileSystemId})}:R.Base64(E),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:r},{Key:"Purpose",Value:"JumpBox/Bastion"}]}};if(a)I.Properties.KeyName=a;let D={[y]:h,[f]:S,[C]:P,[v]:I};return{instance:I,securityGroup:h,instanceProfile:P,instanceRole:S,instanceLogicalId:v,securityGroupLogicalId:y,instanceProfileLogicalId:C,instanceRoleLogicalId:f,resources:D}}static JumpBox={withEfsMount:(e)=>b.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,instanceType:e.instanceType,allowedCidrs:e.allowedCidrs,mountEfs:{fileSystemId:e.fileSystemId,mountPath:e.mountPath||"/mnt/efs"}}),minimal:(e)=>b.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,instanceType:"t3.nano",allowedCidrs:e.allowedCidrs}),withDatabaseTools:(e)=>b.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,instanceType:e.instanceType,allowedCidrs:e.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:(e,n="t3")=>`${n}.${e}`,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:(e)=>{let n={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 n[e]||n.medium},toLambdaMemory:(e)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[e]||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:(e)=>{let{size:n,type:r="ssd",encrypted:i=!0,iops:s,throughput:a,deleteOnTermination:c=!0}=e,d={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[r]||"gp3",m={VolumeSize:n,VolumeType:d,Encrypted:i,DeleteOnTermination:c};if((d==="io1"||d==="io2"||d==="gp3")&&s)m.Iops=s;if(d==="gp3"&&a)m.Throughput=a;return m},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:(e)=>{let{maxPrice:n,spotInstanceType:r="one-time",interruptionBehavior:i="terminate",blockDurationMinutes:s}=e,a={SpotInstanceType:r,InstanceInterruptionBehavior:i};if(n)a.MaxPrice=n;if(s)a.BlockDurationMinutes=s;return{SpotOptions:a}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(e)=>{let{instanceTypes:n,baseCapacity:r=0,onDemandPercentage:i=20,spotAllocationStrategy:s="capacity-optimized",spotMaxPrice:a}=e,c={OnDemandBaseCapacity:r,OnDemandPercentageAboveBaseCapacity:i,SpotAllocationStrategy:s};if(a)c.SpotMaxPrice=a;let u=n.map(({size:d,weight:m})=>{let p={InstanceType:b.InstanceSize.toInstanceType(d)};if(m)p.WeightedCapacity=String(m);return p});return{MixedInstancesPolicy:{InstancesDistribution:c,LaunchTemplate:{Overrides:u}}}},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:(e)=>{let{min:n,max:r,desired:i=n,scaleUpThreshold:s=70,scaleDownThreshold:a=30,cooldownSeconds:c=300,targetMetric:u="cpu"}=e,d={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:n,maxSize:r,desiredCapacity:i,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:s,predefinedMetricType:d[u]||d.cpu,scaleInCooldown:c,scaleOutCooldown:c}]}},forEcs:(e)=>{let{min:n,max:r,cpuTarget:i=70,memoryTarget:s}=e,a=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:i}];if(s)a.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:s});return{minCapacity:n,maxCapacity:r,targetTrackingPolicies:a}},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:(e)=>{let{path:n="/",interval:r=30,timeout:i=5,healthyThreshold:s=2,unhealthyThreshold:a=5,protocol:c="HTTP"}=e,u={HealthCheckIntervalSeconds:r,HealthCheckTimeoutSeconds:i,HealthyThresholdCount:s,UnhealthyThresholdCount:a};if(c!=="TCP")u.HealthCheckPath=n,u.HealthCheckProtocol=c;return u},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:(e)=>{let{certificateArn:n,targetGroupArn:r,port:i=443,sslPolicy:s="ELBSecurityPolicy-TLS13-1-2-2021-06"}=e;return{Port:i,Protocol:"HTTPS",Certificates:[{CertificateArn:n}],SslPolicy:s,DefaultActions:[{Type:"forward",TargetGroupArn:r}]}},httpRedirectListener:(e=80)=>({Port:e,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:(e)=>{let{handler:n,runtime:r="nodejs20.x",timeout:i=30,memorySize:s=256,environmentVariables:a,reservedConcurrency:c}=e,u={Handler:n,Runtime:r,Timeout:i,MemorySize:s};if(a)u.Environment={Variables:a};if(c)u.ReservedConcurrentExecutions=c;return u},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:(e)=>{let{runtime:n="bun",runtimeVersion:r="latest",webServer:i="nginx",processManager:s="systemd",enableSsl:a=!0,sslEmail:c="admin@example.com",domain:u,appPort:d=3000,installDatabaseClients:m=!1,installRedis:p=!1,extraPackages:g=[]}=e,y=`#!/bin/bash
315
315
  set -e
316
316
 
@@ -569,7 +569,7 @@ ufw default allow outgoing
569
569
  ${e.map((n)=>`ufw allow ${n}`).join(`
570
570
  `)}
571
571
  ufw --force enable
572
- `},Presets:{bunWithNginx:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:e,appPort:n,enableSsl:!0}),bunWithCaddy:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:e,appPort:n,enableSsl:!1}),nodeWithPm2:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:e,appPort:n,enableSsl:!0}),worker:(e="bun")=>b.UserData.generateAppServerScript({runtime:e,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(e){let{slug:n,environment:r,domain:i,instanceLogicalId:s}=e,a=l({slug:n,environment:r,resourceType:"eip"}),c=o(a),u={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:r},...i?[{Key:"Domain",Value:i}]:[]]}},d={[c]:u},m,p;if(s)p=o(`${a}-assoc`),m={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:R.GetAtt(c,"AllocationId"),InstanceId:R.Ref(s)}},d[p]=m;return{eip:u,eipAssociation:m,eipLogicalId:c,associationLogicalId:p,resources:d}}static createServerModeStack(e){let{slug:n,environment:r,vpcId:i,subnetId:s,instanceType:a="t3.small",imageId:c="ami-0f3caa1cf4417e51b",keyName:u,domain:d,userData:m,allowedPorts:p=[22,80,443],volumeSize:g=20,volumeType:y="gp3"}=e,h={},f=l({slug:n,environment:r,resourceType:"server-sg"}),S=o(f),C={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:f,GroupDescription:`Security group for ${n} server`,VpcId:i,SecurityGroupIngress:p.map((K)=>({IpProtocol:"tcp",FromPort:K,ToPort:K,CidrIp:"0.0.0.0/0",Description:`Port ${K}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:r}]}};h[S]=C;let P=l({slug:n,environment:r,resourceType:"server-role"}),E=o(P),v={Type:"AWS::IAM::Role",Properties:{RoleName:P,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:"*"}]}}]}};h[E]=v;let I=l({slug:n,environment:r,resourceType:"server-profile"}),D=o(I),x={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:I,Roles:[R.Ref(E)]}};h[D]=x;let F=l({slug:n,environment:r,resourceType:"server"}),M=o(F),O={Type:"AWS::EC2::Instance",DependsOn:[D],Properties:{ImageId:c,InstanceType:a,KeyName:u,SubnetId:s,SecurityGroupIds:[R.Ref(S)],IamInstanceProfile:R.Ref(D),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:g,VolumeType:y,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:F},{Key:"Environment",Value:r},...d?[{Key:"Domain",Value:d}]:[]]}};if(m)O.Properties.UserData=R.Base64(m);h[M]=O;let{eip:G,eipAssociation:U,eipLogicalId:ve,associationLogicalId:z,resources:le}=b.createElasticIp({slug:n,environment:r,domain:d,instanceLogicalId:M});return Object.assign(h,le),{instance:O,securityGroup:C,eip:G,eipAssociation:U,instanceRole:v,instanceProfile:x,resources:h,outputs:{instanceLogicalId:M,securityGroupLogicalId:S,eipLogicalId:ve,associationLogicalId:z,roleLogicalId:E,profileLogicalId:D}}}static ServerMode={webServer:(e)=>{let n=b.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:e.webServer||"nginx",domain:e.domain,enableSsl:!0});return b.createServerModeStack({...e,userData:n,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(e)=>{let n=b.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:"none",installRedis:e.installRedis});return b.createServerModeStack({...e,userData:n,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(e)=>b.createServerModeStack({...e,userData:`#!/bin/bash
572
+ `},Presets:{bunWithNginx:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:e,appPort:n,enableSsl:!0}),bunWithCaddy:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:e,appPort:n,enableSsl:!1}),nodeWithPm2:(e,n=3000)=>b.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:e,appPort:n,enableSsl:!0}),worker:(e="bun")=>b.UserData.generateAppServerScript({runtime:e,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(e){let{slug:n,environment:r,domain:i,instanceLogicalId:s}=e,a=l({slug:n,environment:r,resourceType:"eip"}),c=o(a),u={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:r},...i?[{Key:"Domain",Value:i}]:[]]}},d={[c]:u},m,p;if(s)p=o(`${a}-assoc`),m={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:R.GetAtt(c,"AllocationId"),InstanceId:R.Ref(s)}},d[p]=m;return{eip:u,eipAssociation:m,eipLogicalId:c,associationLogicalId:p,resources:d}}static createServerModeStack(e){let{slug:n,environment:r,vpcId:i,subnetId:s,instanceType:a="t3.small",imageId:c="ami-0f3caa1cf4417e51b",keyName:u,domain:d,userData:m,allowedPorts:p=[22,80,443],volumeSize:g=20,volumeType:y="gp3"}=e,h={},f=l({slug:n,environment:r,resourceType:"server-sg"}),S=o(f),C={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:f,GroupDescription:`Security group for ${n} server`,VpcId:i,SecurityGroupIngress:p.map((K)=>({IpProtocol:"tcp",FromPort:K,ToPort:K,CidrIp:"0.0.0.0/0",Description:`Port ${K}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:r}]}};h[S]=C;let P=l({slug:n,environment:r,resourceType:"server-role"}),E=o(P),v={Type:"AWS::IAM::Role",Properties:{RoleName:P,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:"*"}]}}]}};h[E]=v;let I=l({slug:n,environment:r,resourceType:"server-profile"}),D=o(I),N={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:I,Roles:[R.Ref(E)]}};h[D]=N;let B=l({slug:n,environment:r,resourceType:"server"}),M=o(B),O={Type:"AWS::EC2::Instance",DependsOn:[D],Properties:{ImageId:c,InstanceType:a,KeyName:u,SubnetId:s,SecurityGroupIds:[R.Ref(S)],IamInstanceProfile:R.Ref(D),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:g,VolumeType:y,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:r},...d?[{Key:"Domain",Value:d}]:[]]}};if(m)O.Properties.UserData=R.Base64(m);h[M]=O;let{eip:G,eipAssociation:U,eipLogicalId:ve,associationLogicalId:z,resources:le}=b.createElasticIp({slug:n,environment:r,domain:d,instanceLogicalId:M});return Object.assign(h,le),{instance:O,securityGroup:C,eip:G,eipAssociation:U,instanceRole:v,instanceProfile:N,resources:h,outputs:{instanceLogicalId:M,securityGroupLogicalId:S,eipLogicalId:ve,associationLogicalId:z,roleLogicalId:E,profileLogicalId:D}}}static ServerMode={webServer:(e)=>{let n=b.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:e.webServer||"nginx",domain:e.domain,enableSsl:!0});return b.createServerModeStack({...e,userData:n,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(e)=>{let n=b.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:"none",installRedis:e.installRedis});return b.createServerModeStack({...e,userData:n,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(e)=>b.createServerModeStack({...e,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 L{static createVpc(e){let{slug:n,environment:r,cidr:i="10.0.0.0/16",enableDnsHostnames:s=!0,enableDnsSupport:a=!0}=e,c=l({slug:n,environment:r,resourceType:"vpc"}),u=o(c);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:i,EnableDnsHostnames:s,EnableDnsSupport:a,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r}]}},logicalId:u}}static createSubnet(e){let{slug:n,environment:r,vpcId:i,type:s,cidr:a,availabilityZone:c,mapPublicIp:u=s==="public"}=e,d=l({slug:n,environment:r,resourceType:`subnet-${s}`}),m=o(`${d}-${c}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:i,CidrBlock:a,AvailabilityZone:c,MapPublicIpOnLaunch:u,Tags:[{Key:"Name",Value:`${d}-${c}`},{Key:"Environment",Value:r},{Key:"Type",Value:s}]}},logicalId:m}}static createInternetGateway(e,n){let r=l({slug:e,environment:n,resourceType:"igw"}),i=o(r);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static attachInternetGateway(e,n){let r=o(`${e}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:R.Ref(e),InternetGatewayId:R.Ref(n)}},logicalId:r}}static createEip(e,n){let r=l({slug:e,environment:n,resourceType:"eip"}),i=o(r);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static createNatGateway(e,n){let{slug:r,environment:i,subnetId:s}=e,a=l({slug:r,environment:i,resourceType:"nat"}),c=o(a);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:R.GetAtt(n,"AllocationId"),SubnetId:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:c}}static createRouteTable(e,n,r,i){let s=l({slug:e,environment:n,resourceType:`rt-${i}`}),a=o(s);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:R.Ref(r),Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:n},{Key:"Type",Value:i}]}},logicalId:a}}static createRoute(e,n,r){let i=o(`${e}-route-${r.type}`),s={Type:"AWS::EC2::Route",Properties:{RouteTableId:R.Ref(e),DestinationCidrBlock:n}};if(r.type==="igw")s.Properties.GatewayId=R.Ref(r.logicalId);else if(r.type==="nat")s.Properties.NatGatewayId=R.Ref(r.logicalId);else if(r.type==="instance")s.Properties.InstanceId=R.Ref(r.logicalId);return{route:s,logicalId:i}}static associateSubnetWithRouteTable(e,n){let r=o(`${e}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:R.Ref(e),RouteTableId:R.Ref(n)}},logicalId:r}}static enableFlowLogs(e){let{slug:n,environment:r,resourceId:i,resourceType:s,trafficType:a="ALL",logGroupName:c}=e,u=l({slug:n,environment:r,resourceType:"flowlog"}),d=o(u);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:s,ResourceIds:[i],TrafficType:a,LogDestinationType:"cloud-watch-logs",LogGroupName:c||`/aws/vpc/${n}-${r}`,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}},logicalId:d}}static calculateSubnetCidrs(e,n,r=3){let[i,s]=e.split("/"),a=Number.parseInt(s,10),c=Math.ceil(Math.log2(n*r)),u=a+c;if(u>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[d,m,p,g]=i.split(".").map(Number),y=(d<<24)+(m<<16)+(p<<8)+g,h=2**(32-u),f=[];for(let S=0;S<n*r;S++){let C=y+S*h,P=[C>>>24&255,C>>>16&255,C>>>8&255,C&255].join(".");f.push(`${P}/${u}`)}return f}static getAvailabilityZones(e,n){return["a","b","c","d","e","f"].slice(0,n).map((i)=>`${e}${i}`)}static createMultiAzNetwork(e){let{slug:n,environment:r,region:i,cidr:s="10.0.0.0/16",zones:a=3,enableNatGateway:c=!1,singleNatGateway:u=!1,enableFlowLogs:d=!1}=e,m={},p=[],g=[],y=[],{vpc:h,logicalId:f}=L.createVpc({slug:n,environment:r,cidr:s});m[f]=h;let{internetGateway:S,logicalId:C}=L.createInternetGateway(n,r);m[C]=S;let{attachment:P,logicalId:E}=L.attachInternetGateway(f,C);m[E]=P;let{routeTable:v,logicalId:I}=L.createRouteTable(n,r,f,"public");m[I]=v;let{route:D,logicalId:x}=L.createRoute(I,"0.0.0.0/0",{type:"igw",logicalId:C});D.DependsOn=E,m[x]=D;let F=L.calculateSubnetCidrs(s,a,2),M=L.getAvailabilityZones(i,a),O=[];for(let G=0;G<a;G++){let U=M[G],ve=F[G*2],z=F[G*2+1],{subnet:le,logicalId:K}=L.createSubnet({slug:n,environment:r,vpcId:R.Ref(f),type:"public",cidr:ve,availabilityZone:U});m[K]=le,p.push(K);let{association:ot,logicalId:ct}=L.associateSubnetWithRouteTable(K,I);m[ct]=ot;let{subnet:lt,logicalId:Z}=L.createSubnet({slug:n,environment:r,vpcId:R.Ref(f),type:"private",cidr:z,availabilityZone:U});if(m[Z]=lt,g.push(Z),c&&(!u||G===0)){let{eip:Q,logicalId:ee}=L.createEip(`${n}-${U}`,r);m[ee]=Q;let{natGateway:ue,logicalId:te}=L.createNatGateway({slug:`${n}-${U}`,environment:r,subnetId:R.Ref(K)},ee);ue.DependsOn=E,m[te]=ue,y.push(te);let{routeTable:se,logicalId:ye}=L.createRouteTable(`${n}-${U}`,r,f,"private");m[ye]=se,O.push(ye);let{route:De,logicalId:k}=L.createRoute(ye,"0.0.0.0/0",{type:"nat",logicalId:te});m[k]=De;let{association:_,logicalId:V}=L.associateSubnetWithRouteTable(Z,ye);m[V]=_}else if(c&&u&&G>0){let{association:Q,logicalId:ee}=L.associateSubnetWithRouteTable(Z,O[0]);m[ee]=Q}else{let{routeTable:Q,logicalId:ee}=L.createRouteTable(`${n}-${U}-isolated`,r,f,"private");m[ee]=Q;let{association:ue,logicalId:te}=L.associateSubnetWithRouteTable(Z,ee);m[te]=ue}}if(d){let{flowLog:G,logicalId:U}=L.enableFlowLogs({slug:n,environment:r,resourceId:R.Ref(f),resourceType:"VPC"});m[U]=G}return{resources:m,outputs:{vpcId:f,publicSubnetIds:p,privateSubnetIds:g,natGatewayIds:y.length>0?y:void 0}}}static NatGatewayCostWarning=`
580
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class L{static createVpc(e){let{slug:n,environment:r,cidr:i="10.0.0.0/16",enableDnsHostnames:s=!0,enableDnsSupport:a=!0}=e,c=l({slug:n,environment:r,resourceType:"vpc"}),u=o(c);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:i,EnableDnsHostnames:s,EnableDnsSupport:a,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r}]}},logicalId:u}}static createSubnet(e){let{slug:n,environment:r,vpcId:i,type:s,cidr:a,availabilityZone:c,mapPublicIp:u=s==="public"}=e,d=l({slug:n,environment:r,resourceType:`subnet-${s}`}),m=o(`${d}-${c}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:i,CidrBlock:a,AvailabilityZone:c,MapPublicIpOnLaunch:u,Tags:[{Key:"Name",Value:`${d}-${c}`},{Key:"Environment",Value:r},{Key:"Type",Value:s}]}},logicalId:m}}static createInternetGateway(e,n){let r=l({slug:e,environment:n,resourceType:"igw"}),i=o(r);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static attachInternetGateway(e,n){let r=o(`${e}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:R.Ref(e),InternetGatewayId:R.Ref(n)}},logicalId:r}}static createEip(e,n){let r=l({slug:e,environment:n,resourceType:"eip"}),i=o(r);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:r},{Key:"Environment",Value:n}]}},logicalId:i}}static createNatGateway(e,n){let{slug:r,environment:i,subnetId:s}=e,a=l({slug:r,environment:i,resourceType:"nat"}),c=o(a);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:R.GetAtt(n,"AllocationId"),SubnetId:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:c}}static createRouteTable(e,n,r,i){let s=l({slug:e,environment:n,resourceType:`rt-${i}`}),a=o(s);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:R.Ref(r),Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:n},{Key:"Type",Value:i}]}},logicalId:a}}static createRoute(e,n,r){let i=o(`${e}-route-${r.type}`),s={Type:"AWS::EC2::Route",Properties:{RouteTableId:R.Ref(e),DestinationCidrBlock:n}};if(r.type==="igw")s.Properties.GatewayId=R.Ref(r.logicalId);else if(r.type==="nat")s.Properties.NatGatewayId=R.Ref(r.logicalId);else if(r.type==="instance")s.Properties.InstanceId=R.Ref(r.logicalId);return{route:s,logicalId:i}}static associateSubnetWithRouteTable(e,n){let r=o(`${e}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:R.Ref(e),RouteTableId:R.Ref(n)}},logicalId:r}}static enableFlowLogs(e){let{slug:n,environment:r,resourceId:i,resourceType:s,trafficType:a="ALL",logGroupName:c}=e,u=l({slug:n,environment:r,resourceType:"flowlog"}),d=o(u);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:s,ResourceIds:[i],TrafficType:a,LogDestinationType:"cloud-watch-logs",LogGroupName:c||`/aws/vpc/${n}-${r}`,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}},logicalId:d}}static calculateSubnetCidrs(e,n,r=3){let[i,s]=e.split("/"),a=Number.parseInt(s,10),c=Math.ceil(Math.log2(n*r)),u=a+c;if(u>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[d,m,p,g]=i.split(".").map(Number),y=(d<<24)+(m<<16)+(p<<8)+g,h=2**(32-u),f=[];for(let S=0;S<n*r;S++){let C=y+S*h,P=[C>>>24&255,C>>>16&255,C>>>8&255,C&255].join(".");f.push(`${P}/${u}`)}return f}static getAvailabilityZones(e,n){return["a","b","c","d","e","f"].slice(0,n).map((i)=>`${e}${i}`)}static createMultiAzNetwork(e){let{slug:n,environment:r,region:i,cidr:s="10.0.0.0/16",zones:a=3,enableNatGateway:c=!1,singleNatGateway:u=!1,enableFlowLogs:d=!1}=e,m={},p=[],g=[],y=[],{vpc:h,logicalId:f}=L.createVpc({slug:n,environment:r,cidr:s});m[f]=h;let{internetGateway:S,logicalId:C}=L.createInternetGateway(n,r);m[C]=S;let{attachment:P,logicalId:E}=L.attachInternetGateway(f,C);m[E]=P;let{routeTable:v,logicalId:I}=L.createRouteTable(n,r,f,"public");m[I]=v;let{route:D,logicalId:N}=L.createRoute(I,"0.0.0.0/0",{type:"igw",logicalId:C});D.DependsOn=E,m[N]=D;let B=L.calculateSubnetCidrs(s,a,2),M=L.getAvailabilityZones(i,a),O=[];for(let G=0;G<a;G++){let U=M[G],ve=B[G*2],z=B[G*2+1],{subnet:le,logicalId:K}=L.createSubnet({slug:n,environment:r,vpcId:R.Ref(f),type:"public",cidr:ve,availabilityZone:U});m[K]=le,p.push(K);let{association:ot,logicalId:ct}=L.associateSubnetWithRouteTable(K,I);m[ct]=ot;let{subnet:lt,logicalId:Z}=L.createSubnet({slug:n,environment:r,vpcId:R.Ref(f),type:"private",cidr:z,availabilityZone:U});if(m[Z]=lt,g.push(Z),c&&(!u||G===0)){let{eip:Q,logicalId:ee}=L.createEip(`${n}-${U}`,r);m[ee]=Q;let{natGateway:ue,logicalId:te}=L.createNatGateway({slug:`${n}-${U}`,environment:r,subnetId:R.Ref(K)},ee);ue.DependsOn=E,m[te]=ue,y.push(te);let{routeTable:se,logicalId:ye}=L.createRouteTable(`${n}-${U}`,r,f,"private");m[ye]=se,O.push(ye);let{route:De,logicalId:x}=L.createRoute(ye,"0.0.0.0/0",{type:"nat",logicalId:te});m[x]=De;let{association:_,logicalId:V}=L.associateSubnetWithRouteTable(Z,ye);m[V]=_}else if(c&&u&&G>0){let{association:Q,logicalId:ee}=L.associateSubnetWithRouteTable(Z,O[0]);m[ee]=Q}else{let{routeTable:Q,logicalId:ee}=L.createRouteTable(`${n}-${U}-isolated`,r,f,"private");m[ee]=Q;let{association:ue,logicalId:te}=L.associateSubnetWithRouteTable(Z,ee);m[te]=ue}}if(d){let{flowLog:G,logicalId:U}=L.enableFlowLogs({slug:n,environment:r,resourceId:R.Ref(f),resourceType:"VPC"});m[U]=G}return{resources:m,outputs:{vpcId:f,publicSubnetIds:p,privateSubnetIds:g,natGatewayIds:y.length>0?y: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 rt{static createFileSystem(e){let{slug:n,environment:r,encrypted:i=!0,kmsKeyId:s,performanceMode:a="generalPurpose",throughputMode:c="bursting",provisionedThroughput:u,enableBackup:d=!0}=e,m=l({slug:n,environment:r,resourceType:"efs"}),p=o(m),g={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:i,PerformanceMode:a,ThroughputMode:c,FileSystemTags:[{Key:"Name",Value:m},{Key:"Environment",Value:r}]}};if(s)g.Properties.KmsKeyId=s;if(c==="provisioned"&&u)g.Properties.ProvisionedThroughputInMibps=u;if(d)g.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:g,logicalId:p}}static createMountTarget(e,n){let{slug:r,environment:i,subnetId:s,securityGroups:a,ipAddress:c}=n,u=l({slug:r,environment:i,resourceType:"efs-mt"}),d=o(`${u}-${s}`),m={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:R.Ref(e),SubnetId:s,SecurityGroups:a}};if(c)m.Properties.IpAddress=c;return{mountTarget:m,logicalId:d}}static createAccessPoint(e,n){let{slug:r,environment:i,path:s="/",uid:a="1000",gid:c="1000",permissions:u="755"}=n,d=l({slug:r,environment:i,resourceType:"efs-ap"}),m=o(`${d}-${s.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:R.Ref(e),PosixUser:{Uid:a,Gid:c},RootDirectory:{Path:s,CreationInfo:{OwnerUid:a,OwnerGid:c,Permissions:u}},AccessPointTags:[{Key:"Name",Value:`${d}-${s}`},{Key:"Environment",Value:i}]}},logicalId:m}}static setLifecyclePolicy(e,n){let{transitionToIA:r,transitionToPrimary:i=!1}=n;if(!e.Properties)e.Properties={};if(e.Properties.LifecyclePolicies=[],r){let s=`AFTER_${r}_DAYS`;e.Properties.LifecyclePolicies.push({TransitionToIA:s})}if(i)e.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return e}static enableBackup(e){if(!e.Properties)e.Properties={};return e.Properties.BackupPolicy={Status:"ENABLED"},e}static disableBackup(e){if(!e.Properties)e.Properties={};return e.Properties.BackupPolicy={Status:"DISABLED"},e}static setProvisionedThroughput(e,n){if(!e.Properties)e.Properties={};return e.Properties.ThroughputMode="provisioned",e.Properties.ProvisionedThroughputInMibps=n,e}static setElasticThroughput(e){if(!e.Properties)e.Properties={};return e.Properties.ThroughputMode="elastic",e}static enableMaxIO(e){if(!e.Properties)e.Properties={};return e.Properties.PerformanceMode="maxIO",e}static createEfsSecurityGroup(e){let{slug:n,environment:r,vpcId:i,sourceSecurityGroupIds:s=[],sourceCidrBlocks:a=[],description:c}=e,u=l({slug:n,environment:r,resourceType:"efs-sg"}),d=o(u),m=[];for(let g of s)m.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:g,Description:"NFS from security group"});for(let g of a)m.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:g,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:u,GroupDescription:c||`Security group for EFS mount targets - ${n} ${r}`,VpcId:i,SecurityGroupIngress:m,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}},logicalId:d}}static createMultiAzMountTargets(e,n){let{slug:r,environment:i,subnetIds:s,securityGroupId:a}=n,c=[],u=[];for(let d=0;d<s.length;d++){let m=s[d],p=l({slug:r,environment:i,resourceType:"efs-mt"}),g=o(`${p}-az${d+1}`),y={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:R.Ref(e),SubnetId:m,SecurityGroups:[a]}};c.push(y),u.push(g)}return{mountTargets:c,logicalIds:u}}static createCompleteFileSystem(e){let{slug:n,environment:r,vpcId:i,subnetIds:s,sourceSecurityGroupIds:a=[],encrypted:c=!0,performanceMode:u="generalPurpose",throughputMode:d="elastic",enableBackup:m=!0,transitionToIA:p}=e,g={},{fileSystem:y,logicalId:h}=rt.createFileSystem({slug:n,environment:r,encrypted:c,performanceMode:u,throughputMode:d,enableBackup:m});if(p)rt.setLifecyclePolicy(y,{transitionToIA:p,transitionToPrimary:!0});g[h]=y;let{securityGroup:f,logicalId:S}=rt.createEfsSecurityGroup({slug:n,environment:r,vpcId:i,sourceSecurityGroupIds:a});g[S]=f;let{mountTargets:C,logicalIds:P}=rt.createMultiAzMountTargets(h,{slug:n,environment:r,subnetIds:s,securityGroupId:R.Ref(S)});for(let E=0;E<C.length;E++)g[P[E]]=C[E];return{resources:g,outputs:{fileSystemId:h,securityGroupId:S,mountTargetIds:P}}}}class N{static verifyDomain(e){let{domain:n,slug:r,environment:i,enableDkim:s=!0,dkimKeyLength:a="RSA_2048_BIT"}=e,c=l({slug:r,environment:i,resourceType:"ses-identity"}),u=o(`${c}-${n.replace(/\./g,"")}`),d={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(s)d.Properties.DkimSigningAttributes={NextSigningKeyLength:a};return{emailIdentity:d,logicalId:u}}static createDkimRecords(e,n,r){let i=[];for(let s=0;s<n.length;s++){let a=n[s],c=o(`dkim-${e.replace(/\./g,"")}-${s+1}`),u={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:r,Name:`${a}._domainkey.${e}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${a}.dkim.amazonses.com`]}};i.push({record:u,logicalId:c})}return i}static createConfigurationSet(e){let{slug:n,environment:r,name:i,reputationMetrics:s=!0,sendingEnabled:a=!0,suppressBounces:c=!0,suppressComplaints:u=!0}=e,d=i||l({slug:n,environment:r,resourceType:"ses-config"}),m=o(d),p=[];if(c)p.push("BOUNCE");if(u)p.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:d,ReputationOptions:{ReputationMetricsEnabled:s},SendingOptions:{SendingEnabled:a},SuppressionOptions:{SuppressedReasons:p}}},logicalId:m}}static createReceiptRuleSet(e){let{slug:n,environment:r,name:i}=e,s=i||l({slug:n,environment:r,resourceType:"ses-ruleset"}),a=o(s);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:s}},logicalId:a}}static createReceiptRule(e,n){let{slug:r,environment:i,ruleSetName:s,recipients:a,enabled:c=!0,scanEnabled:u=!0,tlsPolicy:d="Require",s3Action:m,lambdaAction:p,snsAction:g}=n,y=l({slug:r,environment:i,resourceType:"ses-rule"}),h=o(y),f=[];if(m)f.push({S3Action:{BucketName:m.bucketName,ObjectKeyPrefix:m.prefix,KmsKeyArn:m.kmsKeyArn}});if(p)f.push({LambdaAction:{FunctionArn:p.functionArn,InvocationType:p.invocationType||"Event"}});if(g)f.push({SNSAction:{TopicArn:g.topicArn,Encoding:g.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:s,Rule:{Name:y,Enabled:c,ScanEnabled:u,TlsPolicy:d,Recipients:a,Actions:f.length>0?f:void 0}}},logicalId:h}}static createMxRecord(e,n,r){let i=o(`mx-${e.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:e,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${r}.amazonaws.com`]}},logicalId:i}}static createVerificationRecord(e,n,r){let i=o(`verification-${e.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:r,Name:`_amazonses.${e}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${n}"`]}},logicalId:i}}static getSmtpEndpoint(e){return`email-smtp.${e}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(e,n,r){let{includeDomains:i=[],softFail:s=!1}=r||{},a=o(`spf-${e.replace(/\./g,"")}`),c="v=spf1 include:amazonses.com";for(let d of i)c+=` include:${d}`;return c+=s?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:e,Type:"TXT",TTL:300,ResourceRecords:[`"${c}"`]}},logicalId:a}}static createDmarcRecord(e,n,r){let{policy:i="none",subdomainPolicy:s,percentage:a=100,reportingEmail:c,forensicEmail:u}=r||{},d=o(`dmarc-${e.replace(/\./g,"")}`),m=`v=DMARC1; p=${i}; pct=${a}`;if(s)m+=`; sp=${s}`;if(c)m+=`; rua=mailto:${c}`;if(u)m+=`; ruf=mailto:${u}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:`_dmarc.${e}`,Type:"TXT",TTL:300,ResourceRecords:[`"${m}"`]}},logicalId:d}}static createInboundEmailSetup(e){let{slug:n,environment:r,domain:i,s3BucketName:s,s3KeyPrefix:a="inbound/",region:c,hostedZoneId:u,lambdaFunctionArn:d,snsTopicArn:m}=e,p={},{ruleSet:g,logicalId:y}=N.createReceiptRuleSet({slug:n,environment:r});p[y]=g;let{receiptRule:h,logicalId:f}=N.createReceiptRule(y,{slug:n,environment:r,ruleSetName:g.Properties.RuleSetName||`${n}-${r}-receipt-rule-set`,recipients:[i],s3Action:{bucketName:s,prefix:a},lambdaAction:d?{functionArn:d,invocationType:"Event"}:void 0,snsAction:m?{topicArn:m}:void 0});p[f]=h;let{record:S,logicalId:C}=N.createMxRecord(i,u,c);return p[C]=S,{resources:p,outputs:{ruleSetLogicalId:y,ruleLogicalId:f,mxRecordLogicalId:C}}}static createCompleteDomainSetup(e){let{slug:n,environment:r,domain:i,hostedZoneId:s,region:a,enableInbound:c=!1,inboundS3Bucket:u,dmarcReportingEmail:d}=e,m={},{emailIdentity:p,logicalId:g}=N.verifyDomain({domain:i,slug:n,environment:r});m[g]=p;let{configurationSet:y,logicalId:h}=N.createConfigurationSet({slug:n,environment:r});m[h]=y;let{record:f,logicalId:S}=N.createSpfRecord(i,s);m[S]=f;let{record:C,logicalId:P}=N.createDmarcRecord(i,s,{policy:"none",reportingEmail:d||`dmarc-reports@${i}`});if(m[P]=C,c&&u){let E=N.createInboundEmailSetup({slug:n,environment:r,domain:i,s3BucketName:u,region:a,hostedZoneId:s});Object.assign(m,E.resources)}return{resources:m,outputs:{identityLogicalId:g,configSetLogicalId:h}}}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(e){return e in N.InboundSmtpEndpoints}static createEmailLambdaRole(e){let{slug:n,environment:r,s3BucketArn:i,sesIdentityArn:s}=e,a=l({slug:n,environment:r,resourceType:"email-lambda-role"}),c=o(a),u=o(`${a}-policy`),d={Type:"AWS::IAM::Role",Properties:{RoleName:a,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:a},{Key:"Environment",Value:r}]}},m=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[i,`${i}/*`]}];if(s)m.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:s});let p={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${a}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:m},Roles:[R.Ref(c)]}};return{role:d,policy:p,roleLogicalId:c,policyLogicalId:u}}static createOutboundEmailLambda(e){let{slug:n,environment:r,roleArn:i,domain:s,configurationSetName:a,timeout:c=30,memorySize:u=256}=e,d=l({slug:n,environment:r,resourceType:"outbound-email"}),m=o(d);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{DOMAIN:s,CONFIGURATION_SET:a||""}},Code:{ZipFile:N.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:m}}static createInboundEmailLambda(e){let{slug:n,environment:r,roleArn:i,s3BucketName:s,organizedPrefix:a="organized/",timeout:c=60,memorySize:u=512}=e,d=l({slug:n,environment:r,resourceType:"inbound-email"}),m=o(d),p=o(`${d}-permission`),g={Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{S3_BUCKET:s,ORGANIZED_PREFIX:a}},Code:{ZipFile:N.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"InboundEmail"}]}},y={Type:"AWS::Lambda::Permission",Properties:{FunctionName:R.Ref(m),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:R.Ref("AWS::AccountId")}};return{function:g,permission:y,logicalId:m,permissionLogicalId:p}}static createEmailConversionLambda(e){let{slug:n,environment:r,roleArn:i,s3BucketName:s,convertedPrefix:a="converted/",timeout:c=60,memorySize:u=512}=e,d=l({slug:n,environment:r,resourceType:"email-conversion"}),m=o(d);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{S3_BUCKET:s,CONVERTED_PREFIX:a}},Code:{ZipFile:N.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:m}}static createEmailBucketNotification(e){let{lambdaArn:n,prefix:r="inbound/",suffix:i,events:s}=e,a=s??["s3:ObjectCreated:*"],c={};if(r||i){if(c.S3Key={Rules:[]},r)c.S3Key.Rules.push({Name:"prefix",Value:r});if(i)c.S3Key.Rules.push({Name:"suffix",Value:i})}return{notificationConfiguration:{LambdaConfigurations:[{Event:a[0],Function:n,Filter:Object.keys(c).length>0?c:void 0}]}}}static createS3LambdaPermission(e){let{slug:n,environment:r,lambdaLogicalId:i,s3BucketArn:s}=e,a=l({slug:n,environment:r,resourceType:"s3-lambda-permission"}),c=o(a);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:R.Ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:s}},logicalId:c}}static createEmailProcessingStack(e){let{slug:n,environment:r,domain:i,s3BucketName:s,s3BucketArn:a,configurationSetName:c,enableInbound:u=!0,enableConversion:d=!0}=e,m={},{role:p,policy:g,roleLogicalId:y,policyLogicalId:h}=N.createEmailLambdaRole({slug:n,environment:r,s3BucketArn:a,sesIdentityArn:`arn:aws:ses:*:*:identity/${i}`});m[y]=p,m[h]=g;let{function:f,logicalId:S}=N.createOutboundEmailLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),domain:i,configurationSetName:c});m[S]=f;let C={roleLogicalId:y,outboundLambdaLogicalId:S};if(u){let{function:P,permission:E,logicalId:v,permissionLogicalId:I}=N.createInboundEmailLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),s3BucketName:s});m[v]=P,m[I]=E;let{permission:D,logicalId:x}=N.createS3LambdaPermission({slug:n,environment:r,lambdaLogicalId:v,s3BucketArn:a});m[x]=D,C.inboundLambdaLogicalId=v}if(d){let{function:P,logicalId:E}=N.createEmailConversionLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),s3BucketName:s});m[E]=P,C.conversionLambdaLogicalId=E}return{resources:m,outputs:C}}static LambdaCode={outboundEmail:`
588
+ `}class rt{static createFileSystem(e){let{slug:n,environment:r,encrypted:i=!0,kmsKeyId:s,performanceMode:a="generalPurpose",throughputMode:c="bursting",provisionedThroughput:u,enableBackup:d=!0}=e,m=l({slug:n,environment:r,resourceType:"efs"}),p=o(m),g={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:i,PerformanceMode:a,ThroughputMode:c,FileSystemTags:[{Key:"Name",Value:m},{Key:"Environment",Value:r}]}};if(s)g.Properties.KmsKeyId=s;if(c==="provisioned"&&u)g.Properties.ProvisionedThroughputInMibps=u;if(d)g.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:g,logicalId:p}}static createMountTarget(e,n){let{slug:r,environment:i,subnetId:s,securityGroups:a,ipAddress:c}=n,u=l({slug:r,environment:i,resourceType:"efs-mt"}),d=o(`${u}-${s}`),m={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:R.Ref(e),SubnetId:s,SecurityGroups:a}};if(c)m.Properties.IpAddress=c;return{mountTarget:m,logicalId:d}}static createAccessPoint(e,n){let{slug:r,environment:i,path:s="/",uid:a="1000",gid:c="1000",permissions:u="755"}=n,d=l({slug:r,environment:i,resourceType:"efs-ap"}),m=o(`${d}-${s.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:R.Ref(e),PosixUser:{Uid:a,Gid:c},RootDirectory:{Path:s,CreationInfo:{OwnerUid:a,OwnerGid:c,Permissions:u}},AccessPointTags:[{Key:"Name",Value:`${d}-${s}`},{Key:"Environment",Value:i}]}},logicalId:m}}static setLifecyclePolicy(e,n){let{transitionToIA:r,transitionToPrimary:i=!1}=n;if(!e.Properties)e.Properties={};if(e.Properties.LifecyclePolicies=[],r){let s=`AFTER_${r}_DAYS`;e.Properties.LifecyclePolicies.push({TransitionToIA:s})}if(i)e.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return e}static enableBackup(e){if(!e.Properties)e.Properties={};return e.Properties.BackupPolicy={Status:"ENABLED"},e}static disableBackup(e){if(!e.Properties)e.Properties={};return e.Properties.BackupPolicy={Status:"DISABLED"},e}static setProvisionedThroughput(e,n){if(!e.Properties)e.Properties={};return e.Properties.ThroughputMode="provisioned",e.Properties.ProvisionedThroughputInMibps=n,e}static setElasticThroughput(e){if(!e.Properties)e.Properties={};return e.Properties.ThroughputMode="elastic",e}static enableMaxIO(e){if(!e.Properties)e.Properties={};return e.Properties.PerformanceMode="maxIO",e}static createEfsSecurityGroup(e){let{slug:n,environment:r,vpcId:i,sourceSecurityGroupIds:s=[],sourceCidrBlocks:a=[],description:c}=e,u=l({slug:n,environment:r,resourceType:"efs-sg"}),d=o(u),m=[];for(let g of s)m.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:g,Description:"NFS from security group"});for(let g of a)m.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:g,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:u,GroupDescription:c||`Security group for EFS mount targets - ${n} ${r}`,VpcId:i,SecurityGroupIngress:m,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}},logicalId:d}}static createMultiAzMountTargets(e,n){let{slug:r,environment:i,subnetIds:s,securityGroupId:a}=n,c=[],u=[];for(let d=0;d<s.length;d++){let m=s[d],p=l({slug:r,environment:i,resourceType:"efs-mt"}),g=o(`${p}-az${d+1}`),y={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:R.Ref(e),SubnetId:m,SecurityGroups:[a]}};c.push(y),u.push(g)}return{mountTargets:c,logicalIds:u}}static createCompleteFileSystem(e){let{slug:n,environment:r,vpcId:i,subnetIds:s,sourceSecurityGroupIds:a=[],encrypted:c=!0,performanceMode:u="generalPurpose",throughputMode:d="elastic",enableBackup:m=!0,transitionToIA:p}=e,g={},{fileSystem:y,logicalId:h}=rt.createFileSystem({slug:n,environment:r,encrypted:c,performanceMode:u,throughputMode:d,enableBackup:m});if(p)rt.setLifecyclePolicy(y,{transitionToIA:p,transitionToPrimary:!0});g[h]=y;let{securityGroup:f,logicalId:S}=rt.createEfsSecurityGroup({slug:n,environment:r,vpcId:i,sourceSecurityGroupIds:a});g[S]=f;let{mountTargets:C,logicalIds:P}=rt.createMultiAzMountTargets(h,{slug:n,environment:r,subnetIds:s,securityGroupId:R.Ref(S)});for(let E=0;E<C.length;E++)g[P[E]]=C[E];return{resources:g,outputs:{fileSystemId:h,securityGroupId:S,mountTargetIds:P}}}}class k{static verifyDomain(e){let{domain:n,slug:r,environment:i,enableDkim:s=!0,dkimKeyLength:a="RSA_2048_BIT"}=e,c=l({slug:r,environment:i,resourceType:"ses-identity"}),u=o(`${c}-${n.replace(/\./g,"")}`),d={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(s)d.Properties.DkimSigningAttributes={NextSigningKeyLength:a};return{emailIdentity:d,logicalId:u}}static createDkimRecords(e,n,r){let i=[];for(let s=0;s<n.length;s++){let a=n[s],c=o(`dkim-${e.replace(/\./g,"")}-${s+1}`),u={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:r,Name:`${a}._domainkey.${e}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${a}.dkim.amazonses.com`]}};i.push({record:u,logicalId:c})}return i}static createConfigurationSet(e){let{slug:n,environment:r,name:i,reputationMetrics:s=!0,sendingEnabled:a=!0,suppressBounces:c=!0,suppressComplaints:u=!0}=e,d=i||l({slug:n,environment:r,resourceType:"ses-config"}),m=o(d),p=[];if(c)p.push("BOUNCE");if(u)p.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:d,ReputationOptions:{ReputationMetricsEnabled:s},SendingOptions:{SendingEnabled:a},SuppressionOptions:{SuppressedReasons:p}}},logicalId:m}}static createReceiptRuleSet(e){let{slug:n,environment:r,name:i}=e,s=i||l({slug:n,environment:r,resourceType:"ses-ruleset"}),a=o(s);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:s}},logicalId:a}}static createReceiptRule(e,n){let{slug:r,environment:i,ruleSetName:s,recipients:a,enabled:c=!0,scanEnabled:u=!0,tlsPolicy:d="Require",s3Action:m,lambdaAction:p,snsAction:g}=n,y=l({slug:r,environment:i,resourceType:"ses-rule"}),h=o(y),f=[];if(m)f.push({S3Action:{BucketName:m.bucketName,ObjectKeyPrefix:m.prefix,KmsKeyArn:m.kmsKeyArn}});if(p)f.push({LambdaAction:{FunctionArn:p.functionArn,InvocationType:p.invocationType||"Event"}});if(g)f.push({SNSAction:{TopicArn:g.topicArn,Encoding:g.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:s,Rule:{Name:y,Enabled:c,ScanEnabled:u,TlsPolicy:d,Recipients:a,Actions:f.length>0?f:void 0}}},logicalId:h}}static createMxRecord(e,n,r){let i=o(`mx-${e.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:e,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${r}.amazonaws.com`]}},logicalId:i}}static createVerificationRecord(e,n,r){let i=o(`verification-${e.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:r,Name:`_amazonses.${e}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${n}"`]}},logicalId:i}}static getSmtpEndpoint(e){return`email-smtp.${e}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(e,n,r){let{includeDomains:i=[],softFail:s=!1}=r||{},a=o(`spf-${e.replace(/\./g,"")}`),c="v=spf1 include:amazonses.com";for(let d of i)c+=` include:${d}`;return c+=s?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:e,Type:"TXT",TTL:300,ResourceRecords:[`"${c}"`]}},logicalId:a}}static createDmarcRecord(e,n,r){let{policy:i="none",subdomainPolicy:s,percentage:a=100,reportingEmail:c,forensicEmail:u}=r||{},d=o(`dmarc-${e.replace(/\./g,"")}`),m=`v=DMARC1; p=${i}; pct=${a}`;if(s)m+=`; sp=${s}`;if(c)m+=`; rua=mailto:${c}`;if(u)m+=`; ruf=mailto:${u}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:`_dmarc.${e}`,Type:"TXT",TTL:300,ResourceRecords:[`"${m}"`]}},logicalId:d}}static createInboundEmailSetup(e){let{slug:n,environment:r,domain:i,s3BucketName:s,s3KeyPrefix:a="inbound/",region:c,hostedZoneId:u,lambdaFunctionArn:d,snsTopicArn:m}=e,p={},{ruleSet:g,logicalId:y}=k.createReceiptRuleSet({slug:n,environment:r});p[y]=g;let{receiptRule:h,logicalId:f}=k.createReceiptRule(y,{slug:n,environment:r,ruleSetName:g.Properties.RuleSetName||`${n}-${r}-receipt-rule-set`,recipients:[i],s3Action:{bucketName:s,prefix:a},lambdaAction:d?{functionArn:d,invocationType:"Event"}:void 0,snsAction:m?{topicArn:m}:void 0});p[f]=h;let{record:S,logicalId:C}=k.createMxRecord(i,u,c);return p[C]=S,{resources:p,outputs:{ruleSetLogicalId:y,ruleLogicalId:f,mxRecordLogicalId:C}}}static createCompleteDomainSetup(e){let{slug:n,environment:r,domain:i,hostedZoneId:s,region:a,enableInbound:c=!1,inboundS3Bucket:u,dmarcReportingEmail:d}=e,m={},{emailIdentity:p,logicalId:g}=k.verifyDomain({domain:i,slug:n,environment:r});m[g]=p;let{configurationSet:y,logicalId:h}=k.createConfigurationSet({slug:n,environment:r});m[h]=y;let{record:f,logicalId:S}=k.createSpfRecord(i,s);m[S]=f;let{record:C,logicalId:P}=k.createDmarcRecord(i,s,{policy:"none",reportingEmail:d||`dmarc-reports@${i}`});if(m[P]=C,c&&u){let E=k.createInboundEmailSetup({slug:n,environment:r,domain:i,s3BucketName:u,region:a,hostedZoneId:s});Object.assign(m,E.resources)}return{resources:m,outputs:{identityLogicalId:g,configSetLogicalId:h}}}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(e){return e in k.InboundSmtpEndpoints}static createEmailLambdaRole(e){let{slug:n,environment:r,s3BucketArn:i,sesIdentityArn:s}=e,a=l({slug:n,environment:r,resourceType:"email-lambda-role"}),c=o(a),u=o(`${a}-policy`),d={Type:"AWS::IAM::Role",Properties:{RoleName:a,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:a},{Key:"Environment",Value:r}]}},m=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[i,`${i}/*`]}];if(s)m.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:s});let p={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${a}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:m},Roles:[R.Ref(c)]}};return{role:d,policy:p,roleLogicalId:c,policyLogicalId:u}}static createOutboundEmailLambda(e){let{slug:n,environment:r,roleArn:i,domain:s,configurationSetName:a,timeout:c=30,memorySize:u=256}=e,d=l({slug:n,environment:r,resourceType:"outbound-email"}),m=o(d);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{DOMAIN:s,CONFIGURATION_SET:a||""}},Code:{ZipFile:k.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:m}}static createInboundEmailLambda(e){let{slug:n,environment:r,roleArn:i,s3BucketName:s,organizedPrefix:a="organized/",timeout:c=60,memorySize:u=512}=e,d=l({slug:n,environment:r,resourceType:"inbound-email"}),m=o(d),p=o(`${d}-permission`),g={Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{S3_BUCKET:s,ORGANIZED_PREFIX:a}},Code:{ZipFile:k.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"InboundEmail"}]}},y={Type:"AWS::Lambda::Permission",Properties:{FunctionName:R.Ref(m),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:R.Ref("AWS::AccountId")}};return{function:g,permission:y,logicalId:m,permissionLogicalId:p}}static createEmailConversionLambda(e){let{slug:n,environment:r,roleArn:i,s3BucketName:s,convertedPrefix:a="converted/",timeout:c=60,memorySize:u=512}=e,d=l({slug:n,environment:r,resourceType:"email-conversion"}),m=o(d);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:d,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c,MemorySize:u,Environment:{Variables:{S3_BUCKET:s,CONVERTED_PREFIX:a}},Code:{ZipFile:k.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:m}}static createEmailBucketNotification(e){let{lambdaArn:n,prefix:r="inbound/",suffix:i,events:s}=e,a=s??["s3:ObjectCreated:*"],c={};if(r||i){if(c.S3Key={Rules:[]},r)c.S3Key.Rules.push({Name:"prefix",Value:r});if(i)c.S3Key.Rules.push({Name:"suffix",Value:i})}return{notificationConfiguration:{LambdaConfigurations:[{Event:a[0],Function:n,Filter:Object.keys(c).length>0?c:void 0}]}}}static createS3LambdaPermission(e){let{slug:n,environment:r,lambdaLogicalId:i,s3BucketArn:s}=e,a=l({slug:n,environment:r,resourceType:"s3-lambda-permission"}),c=o(a);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:R.Ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:s}},logicalId:c}}static createEmailProcessingStack(e){let{slug:n,environment:r,domain:i,s3BucketName:s,s3BucketArn:a,configurationSetName:c,enableInbound:u=!0,enableConversion:d=!0}=e,m={},{role:p,policy:g,roleLogicalId:y,policyLogicalId:h}=k.createEmailLambdaRole({slug:n,environment:r,s3BucketArn:a,sesIdentityArn:`arn:aws:ses:*:*:identity/${i}`});m[y]=p,m[h]=g;let{function:f,logicalId:S}=k.createOutboundEmailLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),domain:i,configurationSetName:c});m[S]=f;let C={roleLogicalId:y,outboundLambdaLogicalId:S};if(u){let{function:P,permission:E,logicalId:v,permissionLogicalId:I}=k.createInboundEmailLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),s3BucketName:s});m[v]=P,m[I]=E;let{permission:D,logicalId:N}=k.createS3LambdaPermission({slug:n,environment:r,lambdaLogicalId:v,s3BucketArn:a});m[N]=D,C.inboundLambdaLogicalId=v}if(d){let{function:P,logicalId:E}=k.createEmailConversionLambda({slug:n,environment:r,roleArn:R.GetAtt(y,"Arn"),s3BucketName:s});m[E]=P,C.conversionLambdaLogicalId=E}return{resources:m,outputs:C}}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 tl={};Xt(tl,{default:()=>Ir,handler:()=>pt});var pt=`
1134
+ `}}var ol={};Xt(ol,{default:()=>Ir,handler:()=>pt});var pt=`
1135
1135
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1136
1136
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1137
1137
 
@@ -1668,7 +1668,7 @@ catch (error) {
1668
1668
  }
1669
1669
 
1670
1670
  run()
1671
- `}static async generateJobManifest(e){let n=await Ht.discoverJobs(e),r=n.filter((i)=>i.schedule&&i.enabled);return{jobs:n,scheduledCount:r.length,totalCount:n.length}}}var Sm={loadJobs:Ht.discoverJobs,loadActions:Ht.discoverActions,generateScheduledJobs:Ht.generateScheduledJobResources,generateRunner:Ht.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}};var cn=`
1671
+ `}static async generateJobManifest(e){let n=await Ht.discoverJobs(e),r=n.filter((i)=>i.schedule&&i.enabled);return{jobs:n,scheduledCount:r.length,totalCount:n.length}}}var Em={loadJobs:Ht.discoverJobs,loadActions:Ht.discoverActions,generateScheduledJobs:Ht.generateScheduledJobResources,generateRunner:Ht.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
 
@@ -1943,7 +1943,7 @@ catch (error) {
1943
1943
 
1944
1944
  return { statusCode: 200, body: 'OK' };
1945
1945
  };
1946
- `;var rl={};Xt(rl,{default:()=>wr,handler:()=>gt});var gt=`
1946
+ `;var sl={};Xt(sl,{default:()=>wr,handler:()=>gt});var gt=`
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');
@@ -2271,14 +2271,14 @@ function resolveTemplate(template, data) {
2271
2271
  }
2272
2272
  return result;
2273
2273
  }
2274
- `;class Ee{static LambdaCode={send:gt,receive:ln,deliveryStatus:cn};static createPinpointApp(e){return{[`${e.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:e.name||`${e.slug}-sms`}}}}static createSmsChannel(e){let n={ApplicationId:e.applicationId,Enabled:e.enabled!==!1};if(e.senderId)n.SenderId=e.senderId;if(e.shortCode)n.ShortCode=e.shortCode;return{[`${e.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(e){return{[`${e.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:e.pinpointAppId,MESSAGE_LOG_TABLE:e.messageLogTable||"",SMS_SENDER_ID:e.senderId||"",SMS_ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static createReceiveLambda(e){return{[`${e.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:e.optOutTable||"",MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createDeliveryStatusLambda(e){return{[`${e.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createMessageLogTable(e){return{[`${e.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(e){return{[`${e.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(e){return{[`${e.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-sms-notifications`}}}}static createCompleteSetup(e){let n={},r={};Object.assign(n,Ee.createPinpointApp({slug:e.slug})),Object.assign(n,Ee.createSmsChannel({slug:e.slug,applicationId:{Ref:`${e.slug}PinpointApp`},senderId:e.senderId})),Object.assign(n,Ee.createSmsLambdaRole({slug:e.slug})),Object.assign(n,Ee.createMessageLogTable({slug:e.slug})),Object.assign(n,Ee.createOptOutTable({slug:e.slug})),Object.assign(n,Ee.createNotificationTopic({slug:e.slug}));let i={"Fn::GetAtt":[`${e.slug}SmsLambdaRole`,"Arn"]},s={Ref:`${e.slug}PinpointApp`},a={Ref:`${e.slug}SmsMessageLogTable`},c={Ref:`${e.slug}SmsOptOutTable`},u={Ref:`${e.slug}SmsNotificationTopic`};if(Object.assign(n,Ee.createSendLambda({slug:e.slug,roleArn:i,pinpointAppId:s,messageLogTable:a,senderId:e.senderId,originationNumber:e.originationNumber})),e.twoWayEnabled)Object.assign(n,Ee.createReceiveLambda({slug:e.slug,roleArn:i,optOutTable:c,messageLogTable:a,notificationTopicArn:u,webhookUrl:e.webhookUrl}));return Object.assign(n,Ee.createDeliveryStatusLambda({slug:e.slug,roleArn:i,messageLogTable:a,notificationTopicArn:u,webhookUrl:e.webhookUrl})),r[`${e.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${e.slug}PinpointApp`}},r[`${e.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${e.slug}SmsSendLambda`,"Arn"]}},r[`${e.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${e.slug}SmsNotificationTopic`}},r[`${e.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${e.slug}SmsMessageLogTable`}},{resources:n,outputs:r}}}function yt(e){return e.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function Dr(e,n){let r=(e||n).replace(/^\/+|\/+$/g,"");if(!r||r.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return r}function Nr(e){let n=e.storage;if(n?.type==="efs"){let i="fileSystemId"in n?n.fileSystemId:void 0;if(!i||typeof i==="string"&&!i.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:i,posixProfile:n.posixProfile}}let r=(n?.type==="s3"?n.bucket??e.bucket:e.bucket)?.trim();if(!r)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:r}}function kr(e,n,r){let i=n.posixProfile??r;if(!i)throw Error(`sftp: user ${e} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let s of[i.uid,i.gid,...i.secondaryGids??[]])if(!Number.isInteger(s)||s<0||s>4294967295)throw Error(`sftp: user ${e} has an invalid posixProfile id ${s}`);return{Uid:i.uid,Gid:i.gid,...i.secondaryGids?.length?{SecondaryGids:i.secondaryGids}:{}}}function Mr(e,n){return typeof e==="string"?`/${e}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:e}]}}function Br(e){return typeof e==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",e)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:e}]}}class jo{static create(e){let n=Nr(e),r=n.type==="efs"?"EFS":"S3",i=e.endpointType??"PUBLIC";if(i==="VPC"&&(!e.endpointDetails?.vpcId||!e.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let s=`${yt(e.slug)}${yt(e.environment)}Sftp`,a=`${s}Server`,c={},u;if(e.logging!==!1){let d=`${s}LoggingRole`;c[d]={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/*"}]}}]}},u={"Fn::GetAtt":[d,"Arn"]}}c[a]={Type:"AWS::Transfer::Server",Properties:{Domain:r,EndpointType:i,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...i==="VPC"?{EndpointDetails:{VpcId:e.endpointDetails.vpcId,SubnetIds:e.endpointDetails.subnetIds,...e.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:e.endpointDetails.securityGroupIds}:{},...e.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:e.endpointDetails.addressAllocationIds}:{}}}:{},...e.securityPolicyName?{SecurityPolicyName:e.securityPolicyName}:{},...u?{LoggingRole:u}:{},Tags:[{Key:"Project",Value:e.slug},{Key:"Environment",Value:e.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[d,m]of Object.entries(e.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(d))throw Error(`sftp: invalid username ${d}`);if(!m.sshPublicKeys.length)throw Error(`sftp: user ${d} requires at least one SSH public key`);let p=yt(d),g=Dr(m.homeDirectory,d),y=`${s}${p}User`,h=m.roleArn;if(!h){let f=`${s}${p}Role`,S;if(n.type==="efs")S=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Br(n.fileSystemId)}];else{let C=`arn:aws:s3:::${n.bucket}`;S=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:C,Condition:{StringLike:{"s3:prefix":[g,`${g}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${C}/${g}/*`}]}c[f]={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:S}}]}},h={"Fn::GetAtt":[f,"Arn"]}}c[y]={Type:"AWS::Transfer::User",DependsOn:[a],Properties:{ServerId:{Ref:a},UserName:d,Role:h,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?Mr(n.fileSystemId,g):`/${n.bucket}/${g}`,...n.type==="efs"?{PosixProfile:kr(d,m,n.posixProfile)}:{},SshPublicKeys:m.sshPublicKeys}}}return{resources:c,serverLogicalId:a,domain:r}}}class je{static createBedrockRole(e,n){let{slug:r,environment:i,name:s,models:a=["*"],allowStreaming:c=!0}=n,u=s||l({slug:r,environment:i,resourceType:"bedrock-role"}),d=o(u),m=["bedrock:InvokeModel"];if(c)m.push("bedrock:InvokeModelWithResponseStream");let p=a.map((y)=>y==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${y}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:e},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${u}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:m,Resource:p}]}}],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}},logicalId:d}}static createBedrockPolicy(e){let{slug:n,environment:r,name:i,models:s=["*"],allowInvoke:a=!0,allowStreaming:c=!0,allowAsync:u=!1}=e,d=i||l({slug:n,environment:r,resourceType:"bedrock-policy"}),m=o(d),p=[];if(a)p.push("bedrock:InvokeModel");if(c)p.push("bedrock:InvokeModelWithResponseStream");if(u)p.push("bedrock:InvokeModelAsync");let g=s.map((h)=>h==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${h}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:d,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:p,Resource:g}]}}},logicalId:m}}static enableBedrockForLambda(e){return je.createBedrockRole("lambda.amazonaws.com",e)}static enableBedrockForEcs(e){return je.createBedrockRole("ecs-tasks.amazonaws.com",e)}static enableBedrockForEc2(e){return je.createBedrockRole("ec2.amazonaws.com",e)}static addBedrockPermissions(e,n=["*"],r=!0){let i=["bedrock:InvokeModel"];if(r)i.push("bedrock:InvokeModelWithResponseStream");let s=n.map((a)=>a==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${a}`);if(!e.Properties.Policies)e.Properties.Policies=[];return e.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:s}]}}),e}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 Gt{static createPostgres(e){return Gt.createRDSInstance("postgres","16.2",e)}static createMysql(e){return Gt.createRDSInstance("mysql","8.0.35",e)}static createRDSInstance(e,n,r){let{slug:i,environment:s,instanceClass:a="db.t3.micro",allocatedStorage:c=20,storageType:u="gp3",masterUsername:d="admin",masterPassword:m,databaseName:p,subnetIds:g,securityGroupIds:y,encrypted:h=!0,kmsKeyId:f,multiAz:S=!1,backupRetentionDays:C=7,publiclyAccessible:P=!1,enableCloudwatchLogs:E=!0,deletionProtection:v=!0}=r,I=l({slug:i,environment:s,resourceType:`${e}-db`}),D=o(I),x,F;if(g&&g.length>0){let O=l({slug:i,environment:s,resourceType:"db-subnet-group"});F=o(O),x={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:O,DBSubnetGroupDescription:`Subnet group for ${I}`,SubnetIds:g,Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:s}]}}}let M={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:I,DBInstanceClass:a,Engine:e,EngineVersion:n,MasterUsername:d,MasterUserPassword:m,AllocatedStorage:c,StorageType:u,StorageEncrypted:h,MultiAZ:S,BackupRetentionPeriod:C,PubliclyAccessible:P,DeletionProtection:v,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(p)M.Properties.DBName=p;if(f)M.Properties.KmsKeyId=f;if(F)M.Properties.DBSubnetGroupName=R.Ref(F);if(y&&y.length>0)M.Properties.VPCSecurityGroups=y;if(E)M.Properties.EnableCloudwatchLogsExports=e==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:M,subnetGroup:x,logicalId:D,subnetGroupId:F}}static createReadReplica(e,n){let{slug:r,environment:i,instanceClass:s="db.t3.micro",securityGroupIds:a,publiclyAccessible:c=!1}=n,u=l({slug:r,environment:i,resourceType:"db-replica"}),d=o(u),m={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:u,DBInstanceClass:s,SourceDBInstanceIdentifier:R.Ref(e),PubliclyAccessible:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Type",Value:"ReadReplica"}]}};if(a&&a.length>0)m.Properties.VPCSecurityGroups=a;return{replica:m,logicalId:d}}static createParameterGroup(e,n,r){let{slug:i,environment:s,parameters:a={}}=r,c=l({slug:i,environment:s,resourceType:"db-params"}),u=o(c),d=e==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:c,Description:`Parameter group for ${c}`,Family:d,Parameters:a,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static enableBackup(e,n=7){return e.Properties.BackupRetentionPeriod=n,e}static createTable(e){let{slug:n,environment:r,tableName:i,partitionKey:s,sortKey:a,billingMode:c="PAY_PER_REQUEST",readCapacity:u=5,writeCapacity:d=5,streamEnabled:m=!1,streamViewType:p="NEW_AND_OLD_IMAGES",encrypted:g=!0,kmsKeyId:y,pointInTimeRecovery:h=!0,ttlAttribute:f}=e,S=i||l({slug:n,environment:r,resourceType:"table"}),C=o(S),P=[{AttributeName:s.name,AttributeType:s.type}];if(a)P.push({AttributeName:a.name,AttributeType:a.type});let E=[{AttributeName:s.name,KeyType:"HASH"}];if(a)E.push({AttributeName:a.name,KeyType:"RANGE"});let v={Type:"AWS::DynamoDB::Table",Properties:{TableName:S,BillingMode:c,AttributeDefinitions:P,KeySchema:E,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:r}]}};if(c==="PROVISIONED")v.Properties.ProvisionedThroughput={ReadCapacityUnits:u,WriteCapacityUnits:d};if(m)v.Properties.StreamSpecification={StreamViewType:p};if(g)v.Properties.SSESpecification={SSEEnabled:!0,SSEType:y?"KMS":"AES256",KMSMasterKeyId:y};if(h)v.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(f)v.Properties.TimeToLiveSpecification={AttributeName:f,Enabled:!0};return{table:v,logicalId:C}}static addGlobalSecondaryIndex(e,n){let{indexName:r,partitionKey:i,sortKey:s,projectionType:a="ALL",nonKeyAttributes:c,readCapacity:u=5,writeCapacity:d=5}=n;if(!e.Properties.AttributeDefinitions.some((g)=>g.AttributeName===i.name))e.Properties.AttributeDefinitions.push({AttributeName:i.name,AttributeType:i.type});if(s&&!e.Properties.AttributeDefinitions.some((g)=>g.AttributeName===s.name))e.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});let m=[{AttributeName:i.name,KeyType:"HASH"}];if(s)m.push({AttributeName:s.name,KeyType:"RANGE"});let p={IndexName:r,KeySchema:m,Projection:{ProjectionType:a,NonKeyAttributes:a==="INCLUDE"?c:void 0},ProvisionedThroughput:void 0};if(e.Properties.BillingMode==="PROVISIONED")p.ProvisionedThroughput={ReadCapacityUnits:u,WriteCapacityUnits:d};if(!e.Properties.GlobalSecondaryIndexes)e.Properties.GlobalSecondaryIndexes=[];return e.Properties.GlobalSecondaryIndexes.push(p),e}static enableStreams(e,n="NEW_AND_OLD_IMAGES"){return e.Properties.StreamSpecification={StreamViewType:n},e}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 Di{static createRedis(e){let{slug:n,environment:r,nodeType:i="cache.t3.micro",engineVersion:s="7.1",port:a=6379,subnetIds:c,securityGroupIds:u,numCacheClusters:d=2,automaticFailover:m=!0,multiAz:p=!0,clusterMode:g=!1,numNodeGroups:y=1,replicasPerNodeGroup:h=1,atRestEncryption:f=!0,transitEncryption:S=!0,authToken:C,kmsKeyId:P,snapshotRetentionDays:E=7,snapshotWindow:v,maintenanceWindow:I}=e,D=l({slug:n,environment:r,resourceType:"redis"}),x=o(D),F,M;if(c&&c.length>0){let G=l({slug:n,environment:r,resourceType:"cache-subnet-group"});M=o(G),F={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:G,Description:`Subnet group for ${D}`,SubnetIds:c,Tags:[{Key:"Name",Value:G},{Key:"Environment",Value:r}]}}}let O={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:D,ReplicationGroupDescription:`Redis cluster for ${n} ${r}`,Engine:"redis",EngineVersion:s,CacheNodeType:i,Port:a,AutomaticFailoverEnabled:m,MultiAZEnabled:p,AtRestEncryptionEnabled:f,TransitEncryptionEnabled:S,SnapshotRetentionLimit:E,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:r}]}};if(g)O.Properties.NumNodeGroups=y,O.Properties.ReplicasPerNodeGroup=h;else O.Properties.NumCacheClusters=d;if(C)O.Properties.AuthToken=C;if(P)O.Properties.KmsKeyId=P;if(M)O.Properties.CacheSubnetGroupName=R.Ref(M);if(u&&u.length>0)O.Properties.SecurityGroupIds=u;if(v)O.Properties.SnapshotWindow=v;if(I)O.Properties.PreferredMaintenanceWindow=I;return{replicationGroup:O,subnetGroup:F,logicalId:x,subnetGroupId:M}}static createMemcached(e){let{slug:n,environment:r,nodeType:i="cache.t3.micro",engineVersion:s="1.6.22",port:a=11211,numCacheNodes:c=2,subnetIds:u,securityGroupIds:d,azMode:m="cross-az",preferredAzs:p,maintenanceWindow:g}=e,y=l({slug:n,environment:r,resourceType:"memcached"}),h=o(y),f,S;if(u&&u.length>0){let P=l({slug:n,environment:r,resourceType:"cache-subnet-group"});S=o(P),f={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:P,Description:`Subnet group for ${y}`,SubnetIds:u,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}}}let C={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:y,CacheNodeType:i,Engine:"memcached",EngineVersion:s,NumCacheNodes:c,Port:a,AZMode:m,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}};if(S)C.Properties.CacheSubnetGroupName=R.Ref(S);if(d&&d.length>0)C.Properties.VpcSecurityGroupIds=d;if(p&&p.length>0)C.Properties.PreferredAvailabilityZones=p;if(g)C.Properties.PreferredMaintenanceWindow=g;return{cluster:C,subnetGroup:f,logicalId:h,subnetGroupId:S}}static enableClusterMode(e,n=3,r=2){return delete e.Properties.NumCacheClusters,e.Properties.NumNodeGroups=n,e.Properties.ReplicasPerNodeGroup=r,e}static createRedisParameterGroup(e,n){let{slug:r,environment:i,parameters:s={}}=n,a=l({slug:r,environment:i,resourceType:"redis-params"}),c=o(a);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${e.split(".")[0]}.x`,Description:`Parameter group for ${a}`,Properties:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i}]}},logicalId:c}}static createMemcachedParameterGroup(e,n){let{slug:r,environment:i,parameters:s={}}=n,a=l({slug:r,environment:i,resourceType:"memcached-params"}),c=o(a);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${e.split(".")[0]}.${e.split(".")[1]}`,Description:`Parameter group for ${a}`,Properties:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i}]}},logicalId:c}}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 we{static createUser(e){let{slug:n,environment:r,userName:i,groups:s,managedPolicyArns:a}=e,c=i||l({slug:n,environment:r,resourceType:"user"}),u=o(c),d={Type:"AWS::IAM::User",Properties:{UserName:c,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r}]}};if(s&&s.length>0)d.Properties.Groups=s;if(a&&a.length>0)d.Properties.ManagedPolicyArns=a;return{user:d,logicalId:u}}static createRole(e){let{slug:n,environment:r,roleName:i,servicePrincipal:s,awsPrincipal:a,managedPolicyArns:c}=e,u=i||l({slug:n,environment:r,resourceType:"role"}),d=o(u),m={};if(s)m.Service=s;if(a)m.AWS=a;let p={Type:"AWS::IAM::Role",Properties:{RoleName:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:m,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(c&&c.length>0)p.Properties.ManagedPolicyArns=c;return{role:p,logicalId:d}}static createGroup(e){let{slug:n,environment:r,groupName:i,managedPolicyArns:s}=e,a=i||l({slug:n,environment:r,resourceType:"group"}),c=o(a),u={Type:"AWS::IAM::Group",Properties:{GroupName:a}};if(s&&s.length>0)u.Properties.ManagedPolicyArns=s;return{group:u,logicalId:c}}static createPolicy(e){let{slug:n,environment:r,policyName:i,description:s,statements:a}=e,c=i||l({slug:n,environment:r,resourceType:"policy"}),u=o(c),d=a.map((p)=>({Sid:p.sid,Effect:p.effect||"Allow",Action:p.actions,Resource:p.resources,Condition:p.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:c,Description:s||`Managed policy for ${c}`,PolicyDocument:{Version:"2012-10-17",Statement:d}}},logicalId:u}}static attachPolicyToRole(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static attachPolicyToUser(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static attachPolicyToGroup(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static addInlinePolicyToRole(e,n,r){if(!e.Properties.Policies)e.Properties.Policies=[];let i=r.map((s)=>({Effect:s.effect||"Allow",Action:s.actions,Resource:s.resources}));return e.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:i}}),e}static addInlinePolicyToUser(e,n,r){if(!e.Properties.Policies)e.Properties.Policies=[];let i=r.map((s)=>({Effect:s.effect||"Allow",Action:s.actions,Resource:s.resources}));return e.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:i}}),e}static createAccessKey(e,n){let{slug:r,environment:i,status:s="Active"}=n,a=l({slug:r,environment:i,resourceType:"access-key"}),c=o(a);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:R.Ref(e),Status:s}},logicalId:c}}static createInstanceProfile(e,n){let{slug:r,environment:i,profileName:s}=n,a=s||l({slug:r,environment:i,resourceType:"instance-profile"}),c=o(a);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:a,Roles:[R.Ref(e)]}},logicalId:c}}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(e){let{slug:n,environment:r,permissions:i,createAccessKey:s=!0}=e,a={},c=[];if(i.s3Buckets&&i.s3Buckets.length>0)c.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...i.s3Buckets,...i.s3Buckets.map((h)=>`${h}/*`)]});if(i.cloudFrontDistributions&&i.cloudFrontDistributions.length>0)c.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:i.cloudFrontDistributions});if(i.ecrRepositories&&i.ecrRepositories.length>0)c.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:i.ecrRepositories}),c.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(i.ecsServices&&i.ecsServices.length>0)c.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:i.ecsServices}),c.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),c.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(i.cloudFormationStacks&&i.cloudFormationStacks.length>0)c.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:i.cloudFormationStacks});if(i.lambdaFunctions&&i.lambdaFunctions.length>0)c.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:i.lambdaFunctions});if(i.secretsManagerSecrets&&i.secretsManagerSecrets.length>0)c.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:i.secretsManagerSecrets});let{policy:u,logicalId:d}=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${r})`,statements:c});a[d]=u;let{user:m,logicalId:p}=we.createUser({slug:n,environment:r,userName:l({slug:n,environment:r,resourceType:"cicd-user"}),managedPolicyArns:[R.Ref(d)]});a[p]=m;let g,y;if(s){let h=we.createAccessKey(p,{slug:n,environment:r});g=h.accessKey,y=h.logicalId,a[y]=g}return{user:m,accessKey:g,policy:u,userLogicalId:p,accessKeyLogicalId:y,policyLogicalId:d,resources:a}}static createCrossAccountRole(e){let{slug:n,environment:r,trustedAccountIds:i,externalId:s,permissions:a,maxSessionDuration:c=3600}=e,u={},{policy:d,logicalId:m}=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${r})`,statements:a});u[m]=d;let p=l({slug:n,environment:r,resourceType:"cross-account-role"}),g=o(p),y={};if(s)y.StringEquals={"sts:ExternalId":s};let h={Type:"AWS::IAM::Role",Properties:{RoleName:p,MaxSessionDuration:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:i.map((f)=>`arn:aws:iam::${f}:root`)},Action:"sts:AssumeRole",...Object.keys(y).length>0?{Condition:y}:{}}]},ManagedPolicyArns:[R.Ref(m)],Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r},{Key:"Purpose",Value:"Cross-Account Access"}]}};return u[g]=h,{role:h,policy:d,roleLogicalId:g,policyLogicalId:m,resources:u}}static createCliUser(e){let{slug:n,environment:r,permissions:i="readonly"}=e,s={},a=[],c=[];switch(i){case"readonly":c=[we.ManagedPolicies.ReadOnlyAccess];break;case"deploy":a=[{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":c=[we.ManagedPolicies.AdministratorAccess];break}let u,d;if(a.length>0){let h=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${r})`,statements:a});u=h.policy,d=h.logicalId,s[d]=u,c=[R.Ref(d)]}let{user:m,logicalId:p}=we.createUser({slug:n,environment:r,userName:l({slug:n,environment:r,resourceType:"cli-user"}),managedPolicyArns:c});s[p]=m;let{accessKey:g,logicalId:y}=we.createAccessKey(p,{slug:n,environment:r});return s[y]=g,{user:m,accessKey:g,policy:u,userLogicalId:p,accessKeyLogicalId:y,policyLogicalId:d,resources:s}}static CiCdPolicies={s3Deployment:(e)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:e},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:e.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(e)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:e}],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:(e)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:e}],lambdaDeployment:(e)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:e}],cloudFormationDeployment:(e)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:e}]}}class Vo{static createRestApi(e){let{slug:n,environment:r,name:i,description:s,endpointType:a="REGIONAL",binaryMediaTypes:c,compressionSize:u}=e,d=i||l({slug:n,environment:r,resourceType:"rest-api"}),m=o(d),p={Type:"AWS::ApiGateway::RestApi",Properties:{Name:d,Description:s||`REST API for ${n} ${r}`,EndpointConfiguration:{Types:[a]},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r}]}};if(c&&c.length>0)p.Properties.BinaryMediaTypes=c;if(u!==void 0)p.Properties.MinimumCompressionSize=u;return{restApi:p,logicalId:m}}static createHttpApi(e){let{slug:n,environment:r,name:i,description:s,corsEnabled:a=!0,corsOrigins:c=["*"],corsMethods:u=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:d=["*"],corsMaxAge:m=86400,corsAllowCredentials:p=!1}=e,g=i||l({slug:n,environment:r,resourceType:"http-api"}),y=o(g),h={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:g,Description:s||`HTTP API for ${n} ${r}`,ProtocolType:"HTTP",Tags:{Name:g,Environment:r}}};if(a)h.Properties.CorsConfiguration={AllowOrigins:c,AllowMethods:u,AllowHeaders:d,MaxAge:m,AllowCredentials:p};return{httpApi:h,logicalId:y}}static createWebSocketApi(e){let{slug:n,environment:r,name:i,description:s}=e,a=i||l({slug:n,environment:r,resourceType:"ws-api"}),c=o(a);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:a,Description:s||`WebSocket API for ${n} ${r}`,ProtocolType:"WEBSOCKET",Tags:{Name:a,Environment:r}}},logicalId:c}}static createDeployment(e,n){let{slug:r,environment:i,description:s}=n,a=l({slug:r,environment:i,resourceType:"api-deployment"}),c=o(a);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:R.Ref(e),Description:s||`Deployment for ${a}`}},logicalId:c}}static createStage(e,n,r){let{slug:i,environment:s,stageName:a,description:c,cacheEnabled:u=!1,cacheSize:d="0.5",variables:m,throttling:p}=r,g=l({slug:i,environment:s,resourceType:"api-stage"}),y=o(g),h={Type:"AWS::ApiGateway::Stage",Properties:{StageName:a||s,RestApiId:R.Ref(e),DeploymentId:R.Ref(n),Description:c,CacheClusterEnabled:u,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u)h.Properties.CacheClusterSize=d;if(m)h.Properties.Variables=m;if(p)h.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:p.burstLimit,ThrottlingRateLimit:p.rateLimit}];return{stage:h,logicalId:y}}static createAuthorizer(e,n){let{slug:r,environment:i,name:s,type:a,functionArn:c,identitySource:u,userPoolArns:d,ttl:m=300}=n,p=s||l({slug:r,environment:i,resourceType:"api-authorizer"}),g=o(p),y={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:p,Type:a,RestApiId:R.Ref(e),AuthorizerResultTtlInSeconds:m}};if(a==="TOKEN"||a==="REQUEST"){if(!c)throw Error("Lambda authorizer requires functionArn");y.Properties.AuthorizerUri=c,y.Properties.IdentitySource=u||"method.request.header.Authorization"}if(a==="COGNITO_USER_POOLS"){if(!d||d.length===0)throw Error("Cognito authorizer requires userPoolArns");y.Properties.ProviderARNs=d,y.Properties.IdentitySource=u||"method.request.header.Authorization"}return{authorizer:y,logicalId:g}}static setCors(e,n={}){let{origins:r=["*"],methods:i=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:s=["*"],maxAge:a=86400,allowCredentials:c=!1}=n;return e.Properties.CorsConfiguration={AllowOrigins:r,AllowMethods:i,AllowHeaders:s,MaxAge:a,AllowCredentials:c},e}static addThrottling(e,n=5000,r=1e4){if(!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:r}),e}static enableCaching(e,n="0.5",r=300){if(e.Properties.CacheClusterEnabled=!0,e.Properties.CacheClusterSize=n,!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:r}),e}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 xe{static createTopic(e){let{slug:n,environment:r,topicName:i,displayName:s,encrypted:a=!1,kmsKeyId:c}=e,u=i||l({slug:n,environment:r,resourceType:"topic"}),d=o(u),m={Type:"AWS::SNS::Topic",Properties:{TopicName:u,DisplayName:s||u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(a&&c)m.Properties.KmsMasterKeyId=c;return{topic:m,logicalId:d}}static subscribe(e,n){let{slug:r,environment:i,protocol:s,endpoint:a,filterPolicy:c,rawMessageDelivery:u=!1}=n,d=l({slug:r,environment:i,resourceType:"subscription"}),m=a.replace(/[^a-zA-Z0-9]/g,""),p=m.length>12?m.slice(-12):m,g=o(`${d}-${s}-${p}`),y={Type:"AWS::SNS::Subscription",Properties:{TopicArn:R.Ref(e),Protocol:s,Endpoint:a,RawMessageDelivery:u}};if(c)y.Properties.FilterPolicy=c;return{subscription:y,logicalId:g}}static subscribeEmail(e,n,r){return xe.subscribe(e,{...r,protocol:"email",endpoint:n})}static subscribeLambda(e,n,r){return xe.subscribe(e,{...r,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(e,n,r){return xe.subscribe(e,{...r,protocol:"sqs",endpoint:n})}static subscribeHttp(e,n,r){let i=n.startsWith("https://")?"https":"http";return xe.subscribe(e,{...r,protocol:i,endpoint:n})}static subscribeSms(e,n,r){return xe.subscribe(e,{...r,protocol:"sms",endpoint:n})}static setTopicPolicy(e,n){let{slug:r,environment:i,allowedPrincipals:s,allowedServices:a,actions:c="SNS:Publish"}=n,u=l({slug:r,environment:i,resourceType:"topic-policy"}),d=o(u),m={};if(s)m.AWS=s;if(a)m.Service=a;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[R.Ref(e)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:m,Action:c,Resource:R.Ref(e)}]}}},logicalId:d}}static allowCloudWatchAlarms(e,n){return xe.setTopicPolicy(e,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(e,n){return xe.setTopicPolicy(e,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(e,n){return xe.setTopicPolicy(e,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(e,n){if(!e.Properties)e.Properties={};return e.Properties.KmsMasterKeyId=n,e}static addInlineSubscription(e,n,r){if(!e.Properties)e.Properties={};if(!e.Properties.Subscription)e.Properties.Subscription=[];return e.Properties.Subscription.push({Protocol:n,Endpoint:r}),e}static FilterPolicies={eventType:(e)=>({eventType:e}),status:(e)=>({status:e}),numericRange:(e,n,r)=>({[e]:[{numeric:[">=",n,"<=",r]}]}),prefix:(e,n)=>({[e]:[{prefix:n}]}),and:(...e)=>Object.assign({},...e),exists:(e,n)=>({[e]:[{exists:n}]})};static UseCases={createAlertTopic:(e)=>xe.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-alerts`,displayName:e.displayName||"Alert Notifications"}),createEventFanout:(e)=>xe.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-events`,displayName:e.displayName||"Event Fanout"}),createNotificationTopic:(e)=>xe.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-notifications`,displayName:e.displayName||"User Notifications"})}}class nu{static createStateMachine(e){let{slug:n,environment:r,stateMachineName:i,type:s="STANDARD",definition:a,roleArn:c,loggingConfiguration:u,tracingConfiguration:d}=e,m=i||l({slug:n,environment:r,resourceType:"state-machine"}),p=o(m),g,y,h;if(c)h=c;else{let S=l({slug:n,environment:r,resourceType:"state-machine-role"});y=o(S),g={Type:"AWS::IAM::Role",Properties:{RoleName:S,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:S},{Key:"Environment",Value:r}]}},h=R.GetAtt(y,"Arn")}let f={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:m,StateMachineType:s,DefinitionString:JSON.stringify(a),RoleArn:h,Tags:[{Key:"Name",Value:m},{Key:"Environment",Value:r}]}};if(u)f.Properties.LoggingConfiguration={Level:u.level,IncludeExecutionData:u.includeExecutionData,Destinations:u.destinations?.map((S)=>({CloudWatchLogsLogGroup:{LogGroupArn:S}}))};if(d)f.Properties.TracingConfiguration={Enabled:d.enabled};return{stateMachine:f,logicalId:p,role:g,roleLogicalId:y}}static createLambdaTask(e,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:e,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(e,n,r,i){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"}[e],Parameters:{TableName:n,...r},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSNSPublishTask(e,n,r){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:e,Message:n},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createSQSSendMessageTask(e,n,r){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:e,MessageBody:n},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createPassState(e){return{Type:"Pass",Result:e?.result,ResultPath:e?.resultPath,Parameters:e?.parameters,Next:e?.next,End:e?.end}}static createWaitState(e){return{Type:"Wait",Seconds:e.seconds,Timestamp:e.timestamp,SecondsPath:e.secondsPath,TimestampPath:e.timestampPath,Next:e.next,End:e.end}}static createChoiceState(e,n){return{Type:"Choice",Choices:e,Default:n}}static createParallelState(e,n){return{Type:"Parallel",Branches:e,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(e,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:e,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(e,n){return{Type:"Fail",Error:e,Cause:n}}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:(e,n,r,i)=>({ErrorEquals:e,IntervalSeconds:n,MaxAttempts:r,BackoffRate:i})};static CatchPolicies={all:(e,n)=>({ErrorEquals:["States.ALL"],Next:e,ResultPath:n||"$.error"}),specific:(e,n,r)=>({ErrorEquals:e,Next:n,ResultPath:r||"$.error"})};static Patterns={sequential:(e,n,r)=>{let i={};return r.forEach((s,a)=>{let c=a===r.length-1;i[s.name]={...s.state,Next:c?void 0:r[a+1].name,End:c}}),{Comment:"Sequential workflow",StartAt:r[0].name,States:i}},fanout:(e,n,r)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:r.map((i)=>i.definition),End:!0}}}),map:(e,n,r,i)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:r,MaxConcurrency:i,End:!0}}}),withErrorHandling:(e,n,r,i)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...r,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:i,Success:{Type:"Succeed"}}})}}class Ni{static createAlarm(e){let{slug:n,environment:r,alarmName:i,metricName:s,namespace:a,statistic:c="Average",period:u=300,evaluationPeriods:d=1,threshold:m,comparisonOperator:p,treatMissingData:g="notBreaching",actionsEnabled:y=!0,alarmActions:h,okActions:f,insufficientDataActions:S,dimensions:C,unit:P,datapointsToAlarm:E}=e,v=i||l({slug:n,environment:r,resourceType:"alarm"}),I=o(v),D={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:v,MetricName:s,Namespace:a,Statistic:c,Period:u,EvaluationPeriods:d,Threshold:m,ComparisonOperator:p,TreatMissingData:g,ActionsEnabled:y}};if(h&&h.length>0)D.Properties.AlarmActions=h;if(f&&f.length>0)D.Properties.OKActions=f;if(S&&S.length>0)D.Properties.InsufficientDataActions=S;if(C)D.Properties.Dimensions=Object.entries(C).map(([x,F])=>({Name:x,Value:F}));if(P)D.Properties.Unit=P;if(E!==void 0)D.Properties.DatapointsToAlarm=E;return{alarm:D,logicalId:I}}static createCompositeAlarm(e){let{slug:n,environment:r,alarmName:i,alarmRule:s,actionsEnabled:a=!0,alarmActions:c,okActions:u,insufficientDataActions:d}=e,m=i||l({slug:n,environment:r,resourceType:"composite-alarm"}),p=o(m),g={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:m,AlarmRule:s,ActionsEnabled:a}};if(c&&c.length>0)g.Properties.AlarmActions=c;if(u&&u.length>0)g.Properties.OKActions=u;if(d&&d.length>0)g.Properties.InsufficientDataActions=d;return{alarm:g,logicalId:p}}static createDashboard(e){let{slug:n,environment:r,dashboardName:i,widgets:s}=e,a=i||l({slug:n,environment:r,resourceType:"dashboard"}),c=o(a),u={widgets:s.map((m)=>({type:m.type,x:m.x,y:m.y,width:m.width,height:m.height,properties:m.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:a,DashboardBody:JSON.stringify(u)}},logicalId:c}}static createLogGroup(e){let{slug:n,environment:r,logGroupName:i,retentionInDays:s,kmsKeyId:a}=e,c=i||l({slug:n,environment:r,resourceType:"log-group"}),u=o(c),d={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:c}};if(s!==void 0)d.Properties.RetentionInDays=s;if(a)d.Properties.KmsKeyId=a;return{logGroup:d,logicalId:u}}static createLogStream(e,n){let{slug:r,environment:i,logStreamName:s}=n,a=s||l({slug:r,environment:i,resourceType:"log-stream"}),c=o(a);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:R.Ref(e),LogStreamName:a}},logicalId:c}}static createMetricFilter(e,n){let{slug:r,environment:i,filterName:s,filterPattern:a,metricTransformations:c}=n,u=s||l({slug:r,environment:i,resourceType:"metric-filter"}),d=o(u);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:R.Ref(e),FilterPattern:a,MetricTransformations:c.map((p)=>({MetricName:p.metricName,MetricNamespace:p.metricNamespace,MetricValue:p.metricValue,DefaultValue:p.defaultValue,Unit:p.unit}))}},logicalId:d}}static AlarmTypes={highCpu:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0}),highMemory:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0}),highDisk:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:s?[s]:void 0}),lambdaErrors:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:r},alarmActions:s?[s]:void 0}),lambdaThrottles:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:r},alarmActions:s?[s]:void 0}),apiGateway5xxErrors:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:r},alarmActions:s?[s]:void 0}),apiGateway4xxErrors:(e,n,r,i=50,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:r},alarmActions:s?[s]:void 0}),dynamoDBThrottles:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:r},alarmActions:s?[s]:void 0}),rdsCpu:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:r},alarmActions:s?[s]:void 0}),rdsFreeStorage:(e,n,r,i=5368709120,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:r},alarmActions:s?[s]:void 0,unit:"Bytes"}),sqsQueueDepth:(e,n,r,i=100,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:r},alarmActions:s?[s]:void 0}),albUnhealthyTargets:(e,n,r,i,s=1,a)=>({slug:e,environment:n,alarmName:`${e}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:r,TargetGroup:i},alarmActions:a?[a]:void 0}),sesBounceRate:(e,n,r=5,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:r/100,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),sesComplaintRate:(e,n,r=0.1,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:r/100,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),smsDeliveryFailure:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:r},alarmActions:s?[s]:void 0}),smsSpendLimit:(e,n,r=100,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),connectMissedCalls:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0})};static DashboardWidgets={metric:(e,n,r,i,s,a)=>({type:"metric",x:e,y:n,width:r,height:i,properties:{metrics:s,title:a||"Metrics",region:"us-east-1",period:300}}),text:(e,n,r,i,s)=>({type:"text",x:e,y:n,width:r,height:i,properties:{markdown:s}}),log:(e,n,r,i,s,a)=>({type:"log",x:e,y:n,width:r,height:i,properties:{query:`SOURCE '${s.join("' | SOURCE '")}'
2274
+ `;class Ee{static LambdaCode={send:gt,receive:ln,deliveryStatus:cn};static createPinpointApp(e){return{[`${e.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:e.name||`${e.slug}-sms`}}}}static createSmsChannel(e){let n={ApplicationId:e.applicationId,Enabled:e.enabled!==!1};if(e.senderId)n.SenderId=e.senderId;if(e.shortCode)n.ShortCode=e.shortCode;return{[`${e.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(e){return{[`${e.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:e.pinpointAppId,MESSAGE_LOG_TABLE:e.messageLogTable||"",SMS_SENDER_ID:e.senderId||"",SMS_ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static createReceiveLambda(e){return{[`${e.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:e.optOutTable||"",MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createDeliveryStatusLambda(e){return{[`${e.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createMessageLogTable(e){return{[`${e.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(e){return{[`${e.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(e){return{[`${e.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-sms-notifications`}}}}static createCompleteSetup(e){let n={},r={};Object.assign(n,Ee.createPinpointApp({slug:e.slug})),Object.assign(n,Ee.createSmsChannel({slug:e.slug,applicationId:{Ref:`${e.slug}PinpointApp`},senderId:e.senderId})),Object.assign(n,Ee.createSmsLambdaRole({slug:e.slug})),Object.assign(n,Ee.createMessageLogTable({slug:e.slug})),Object.assign(n,Ee.createOptOutTable({slug:e.slug})),Object.assign(n,Ee.createNotificationTopic({slug:e.slug}));let i={"Fn::GetAtt":[`${e.slug}SmsLambdaRole`,"Arn"]},s={Ref:`${e.slug}PinpointApp`},a={Ref:`${e.slug}SmsMessageLogTable`},c={Ref:`${e.slug}SmsOptOutTable`},u={Ref:`${e.slug}SmsNotificationTopic`};if(Object.assign(n,Ee.createSendLambda({slug:e.slug,roleArn:i,pinpointAppId:s,messageLogTable:a,senderId:e.senderId,originationNumber:e.originationNumber})),e.twoWayEnabled)Object.assign(n,Ee.createReceiveLambda({slug:e.slug,roleArn:i,optOutTable:c,messageLogTable:a,notificationTopicArn:u,webhookUrl:e.webhookUrl}));return Object.assign(n,Ee.createDeliveryStatusLambda({slug:e.slug,roleArn:i,messageLogTable:a,notificationTopicArn:u,webhookUrl:e.webhookUrl})),r[`${e.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${e.slug}PinpointApp`}},r[`${e.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${e.slug}SmsSendLambda`,"Arn"]}},r[`${e.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${e.slug}SmsNotificationTopic`}},r[`${e.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${e.slug}SmsMessageLogTable`}},{resources:n,outputs:r}}}function yt(e){return e.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function Dr(e,n){let r=(e||n).replace(/^\/+|\/+$/g,"");if(!r||r.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return r}function Nr(e){let n=e.storage;if(n?.type==="efs"){let i="fileSystemId"in n?n.fileSystemId:void 0;if(!i||typeof i==="string"&&!i.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:i,posixProfile:n.posixProfile}}let r=(n?.type==="s3"?n.bucket??e.bucket:e.bucket)?.trim();if(!r)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:r}}function xr(e,n,r){let i=n.posixProfile??r;if(!i)throw Error(`sftp: user ${e} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let s of[i.uid,i.gid,...i.secondaryGids??[]])if(!Number.isInteger(s)||s<0||s>4294967295)throw Error(`sftp: user ${e} has an invalid posixProfile id ${s}`);return{Uid:i.uid,Gid:i.gid,...i.secondaryGids?.length?{SecondaryGids:i.secondaryGids}:{}}}function kr(e,n){return typeof e==="string"?`/${e}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:e}]}}function Or(e){return typeof e==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",e)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:e}]}}class Go{static create(e){let n=Nr(e),r=n.type==="efs"?"EFS":"S3",i=e.endpointType??"PUBLIC";if(i==="VPC"&&(!e.endpointDetails?.vpcId||!e.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let s=`${yt(e.slug)}${yt(e.environment)}Sftp`,a=`${s}Server`,c={},u;if(e.logging!==!1){let d=`${s}LoggingRole`;c[d]={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/*"}]}}]}},u={"Fn::GetAtt":[d,"Arn"]}}c[a]={Type:"AWS::Transfer::Server",Properties:{Domain:r,EndpointType:i,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...i==="VPC"?{EndpointDetails:{VpcId:e.endpointDetails.vpcId,SubnetIds:e.endpointDetails.subnetIds,...e.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:e.endpointDetails.securityGroupIds}:{},...e.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:e.endpointDetails.addressAllocationIds}:{}}}:{},...e.securityPolicyName?{SecurityPolicyName:e.securityPolicyName}:{},...u?{LoggingRole:u}:{},Tags:[{Key:"Project",Value:e.slug},{Key:"Environment",Value:e.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[d,m]of Object.entries(e.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(d))throw Error(`sftp: invalid username ${d}`);if(!m.sshPublicKeys.length)throw Error(`sftp: user ${d} requires at least one SSH public key`);let p=yt(d),g=Dr(m.homeDirectory,d),y=`${s}${p}User`,h=m.roleArn;if(!h){let f=`${s}${p}Role`,S;if(n.type==="efs")S=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Or(n.fileSystemId)}];else{let C=`arn:aws:s3:::${n.bucket}`;S=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:C,Condition:{StringLike:{"s3:prefix":[g,`${g}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${C}/${g}/*`}]}c[f]={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:S}}]}},h={"Fn::GetAtt":[f,"Arn"]}}c[y]={Type:"AWS::Transfer::User",DependsOn:[a],Properties:{ServerId:{Ref:a},UserName:d,Role:h,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?kr(n.fileSystemId,g):`/${n.bucket}/${g}`,...n.type==="efs"?{PosixProfile:xr(d,m,n.posixProfile)}:{},SshPublicKeys:m.sshPublicKeys}}}return{resources:c,serverLogicalId:a,domain:r}}}class Ve{static createBedrockRole(e,n){let{slug:r,environment:i,name:s,models:a=["*"],allowStreaming:c=!0}=n,u=s||l({slug:r,environment:i,resourceType:"bedrock-role"}),d=o(u),m=["bedrock:InvokeModel"];if(c)m.push("bedrock:InvokeModelWithResponseStream");let p=a.map((y)=>y==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${y}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:e},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${u}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:m,Resource:p}]}}],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}},logicalId:d}}static createBedrockPolicy(e){let{slug:n,environment:r,name:i,models:s=["*"],allowInvoke:a=!0,allowStreaming:c=!0,allowAsync:u=!1}=e,d=i||l({slug:n,environment:r,resourceType:"bedrock-policy"}),m=o(d),p=[];if(a)p.push("bedrock:InvokeModel");if(c)p.push("bedrock:InvokeModelWithResponseStream");if(u)p.push("bedrock:InvokeModelAsync");let g=s.map((h)=>h==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${h}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:d,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:p,Resource:g}]}}},logicalId:m}}static enableBedrockForLambda(e){return Ve.createBedrockRole("lambda.amazonaws.com",e)}static enableBedrockForEcs(e){return Ve.createBedrockRole("ecs-tasks.amazonaws.com",e)}static enableBedrockForEc2(e){return Ve.createBedrockRole("ec2.amazonaws.com",e)}static addBedrockPermissions(e,n=["*"],r=!0){let i=["bedrock:InvokeModel"];if(r)i.push("bedrock:InvokeModelWithResponseStream");let s=n.map((a)=>a==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${a}`);if(!e.Properties.Policies)e.Properties.Policies=[];return e.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:s}]}}),e}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 Gt{static createPostgres(e){return Gt.createRDSInstance("postgres","16.2",e)}static createMysql(e){return Gt.createRDSInstance("mysql","8.0.35",e)}static createRDSInstance(e,n,r){let{slug:i,environment:s,instanceClass:a="db.t3.micro",allocatedStorage:c=20,storageType:u="gp3",masterUsername:d="admin",masterPassword:m,databaseName:p,subnetIds:g,securityGroupIds:y,encrypted:h=!0,kmsKeyId:f,multiAz:S=!1,backupRetentionDays:C=7,publiclyAccessible:P=!1,enableCloudwatchLogs:E=!0,deletionProtection:v=!0}=r,I=l({slug:i,environment:s,resourceType:`${e}-db`}),D=o(I),N,B;if(g&&g.length>0){let O=l({slug:i,environment:s,resourceType:"db-subnet-group"});B=o(O),N={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:O,DBSubnetGroupDescription:`Subnet group for ${I}`,SubnetIds:g,Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:s}]}}}let M={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:I,DBInstanceClass:a,Engine:e,EngineVersion:n,MasterUsername:d,MasterUserPassword:m,AllocatedStorage:c,StorageType:u,StorageEncrypted:h,MultiAZ:S,BackupRetentionPeriod:C,PubliclyAccessible:P,DeletionProtection:v,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(p)M.Properties.DBName=p;if(f)M.Properties.KmsKeyId=f;if(B)M.Properties.DBSubnetGroupName=R.Ref(B);if(y&&y.length>0)M.Properties.VPCSecurityGroups=y;if(E)M.Properties.EnableCloudwatchLogsExports=e==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:M,subnetGroup:N,logicalId:D,subnetGroupId:B}}static createReadReplica(e,n){let{slug:r,environment:i,instanceClass:s="db.t3.micro",securityGroupIds:a,publiclyAccessible:c=!1}=n,u=l({slug:r,environment:i,resourceType:"db-replica"}),d=o(u),m={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:u,DBInstanceClass:s,SourceDBInstanceIdentifier:R.Ref(e),PubliclyAccessible:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Type",Value:"ReadReplica"}]}};if(a&&a.length>0)m.Properties.VPCSecurityGroups=a;return{replica:m,logicalId:d}}static createParameterGroup(e,n,r){let{slug:i,environment:s,parameters:a={}}=r,c=l({slug:i,environment:s,resourceType:"db-params"}),u=o(c),d=e==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:c,Description:`Parameter group for ${c}`,Family:d,Parameters:a,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static enableBackup(e,n=7){return e.Properties.BackupRetentionPeriod=n,e}static createTable(e){let{slug:n,environment:r,tableName:i,partitionKey:s,sortKey:a,billingMode:c="PAY_PER_REQUEST",readCapacity:u=5,writeCapacity:d=5,streamEnabled:m=!1,streamViewType:p="NEW_AND_OLD_IMAGES",encrypted:g=!0,kmsKeyId:y,pointInTimeRecovery:h=!0,ttlAttribute:f}=e,S=i||l({slug:n,environment:r,resourceType:"table"}),C=o(S),P=[{AttributeName:s.name,AttributeType:s.type}];if(a)P.push({AttributeName:a.name,AttributeType:a.type});let E=[{AttributeName:s.name,KeyType:"HASH"}];if(a)E.push({AttributeName:a.name,KeyType:"RANGE"});let v={Type:"AWS::DynamoDB::Table",Properties:{TableName:S,BillingMode:c,AttributeDefinitions:P,KeySchema:E,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:r}]}};if(c==="PROVISIONED")v.Properties.ProvisionedThroughput={ReadCapacityUnits:u,WriteCapacityUnits:d};if(m)v.Properties.StreamSpecification={StreamViewType:p};if(g)v.Properties.SSESpecification={SSEEnabled:!0,SSEType:y?"KMS":"AES256",KMSMasterKeyId:y};if(h)v.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(f)v.Properties.TimeToLiveSpecification={AttributeName:f,Enabled:!0};return{table:v,logicalId:C}}static addGlobalSecondaryIndex(e,n){let{indexName:r,partitionKey:i,sortKey:s,projectionType:a="ALL",nonKeyAttributes:c,readCapacity:u=5,writeCapacity:d=5}=n;if(!e.Properties.AttributeDefinitions.some((g)=>g.AttributeName===i.name))e.Properties.AttributeDefinitions.push({AttributeName:i.name,AttributeType:i.type});if(s&&!e.Properties.AttributeDefinitions.some((g)=>g.AttributeName===s.name))e.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});let m=[{AttributeName:i.name,KeyType:"HASH"}];if(s)m.push({AttributeName:s.name,KeyType:"RANGE"});let p={IndexName:r,KeySchema:m,Projection:{ProjectionType:a,NonKeyAttributes:a==="INCLUDE"?c:void 0},ProvisionedThroughput:void 0};if(e.Properties.BillingMode==="PROVISIONED")p.ProvisionedThroughput={ReadCapacityUnits:u,WriteCapacityUnits:d};if(!e.Properties.GlobalSecondaryIndexes)e.Properties.GlobalSecondaryIndexes=[];return e.Properties.GlobalSecondaryIndexes.push(p),e}static enableStreams(e,n="NEW_AND_OLD_IMAGES"){return e.Properties.StreamSpecification={StreamViewType:n},e}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 _i{static createRedis(e){let{slug:n,environment:r,nodeType:i="cache.t3.micro",engineVersion:s="7.1",port:a=6379,subnetIds:c,securityGroupIds:u,numCacheClusters:d=2,automaticFailover:m=!0,multiAz:p=!0,clusterMode:g=!1,numNodeGroups:y=1,replicasPerNodeGroup:h=1,atRestEncryption:f=!0,transitEncryption:S=!0,authToken:C,kmsKeyId:P,snapshotRetentionDays:E=7,snapshotWindow:v,maintenanceWindow:I}=e,D=l({slug:n,environment:r,resourceType:"redis"}),N=o(D),B,M;if(c&&c.length>0){let G=l({slug:n,environment:r,resourceType:"cache-subnet-group"});M=o(G),B={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:G,Description:`Subnet group for ${D}`,SubnetIds:c,Tags:[{Key:"Name",Value:G},{Key:"Environment",Value:r}]}}}let O={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:D,ReplicationGroupDescription:`Redis cluster for ${n} ${r}`,Engine:"redis",EngineVersion:s,CacheNodeType:i,Port:a,AutomaticFailoverEnabled:m,MultiAZEnabled:p,AtRestEncryptionEnabled:f,TransitEncryptionEnabled:S,SnapshotRetentionLimit:E,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:r}]}};if(g)O.Properties.NumNodeGroups=y,O.Properties.ReplicasPerNodeGroup=h;else O.Properties.NumCacheClusters=d;if(C)O.Properties.AuthToken=C;if(P)O.Properties.KmsKeyId=P;if(M)O.Properties.CacheSubnetGroupName=R.Ref(M);if(u&&u.length>0)O.Properties.SecurityGroupIds=u;if(v)O.Properties.SnapshotWindow=v;if(I)O.Properties.PreferredMaintenanceWindow=I;return{replicationGroup:O,subnetGroup:B,logicalId:N,subnetGroupId:M}}static createMemcached(e){let{slug:n,environment:r,nodeType:i="cache.t3.micro",engineVersion:s="1.6.22",port:a=11211,numCacheNodes:c=2,subnetIds:u,securityGroupIds:d,azMode:m="cross-az",preferredAzs:p,maintenanceWindow:g}=e,y=l({slug:n,environment:r,resourceType:"memcached"}),h=o(y),f,S;if(u&&u.length>0){let P=l({slug:n,environment:r,resourceType:"cache-subnet-group"});S=o(P),f={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:P,Description:`Subnet group for ${y}`,SubnetIds:u,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:r}]}}}let C={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:y,CacheNodeType:i,Engine:"memcached",EngineVersion:s,NumCacheNodes:c,Port:a,AZMode:m,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:r}]}};if(S)C.Properties.CacheSubnetGroupName=R.Ref(S);if(d&&d.length>0)C.Properties.VpcSecurityGroupIds=d;if(p&&p.length>0)C.Properties.PreferredAvailabilityZones=p;if(g)C.Properties.PreferredMaintenanceWindow=g;return{cluster:C,subnetGroup:f,logicalId:h,subnetGroupId:S}}static enableClusterMode(e,n=3,r=2){return delete e.Properties.NumCacheClusters,e.Properties.NumNodeGroups=n,e.Properties.ReplicasPerNodeGroup=r,e}static createRedisParameterGroup(e,n){let{slug:r,environment:i,parameters:s={}}=n,a=l({slug:r,environment:i,resourceType:"redis-params"}),c=o(a);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${e.split(".")[0]}.x`,Description:`Parameter group for ${a}`,Properties:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i}]}},logicalId:c}}static createMemcachedParameterGroup(e,n){let{slug:r,environment:i,parameters:s={}}=n,a=l({slug:r,environment:i,resourceType:"memcached-params"}),c=o(a);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${e.split(".")[0]}.${e.split(".")[1]}`,Description:`Parameter group for ${a}`,Properties:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:i}]}},logicalId:c}}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 we{static createUser(e){let{slug:n,environment:r,userName:i,groups:s,managedPolicyArns:a}=e,c=i||l({slug:n,environment:r,resourceType:"user"}),u=o(c),d={Type:"AWS::IAM::User",Properties:{UserName:c,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r}]}};if(s&&s.length>0)d.Properties.Groups=s;if(a&&a.length>0)d.Properties.ManagedPolicyArns=a;return{user:d,logicalId:u}}static createRole(e){let{slug:n,environment:r,roleName:i,servicePrincipal:s,awsPrincipal:a,managedPolicyArns:c}=e,u=i||l({slug:n,environment:r,resourceType:"role"}),d=o(u),m={};if(s)m.Service=s;if(a)m.AWS=a;let p={Type:"AWS::IAM::Role",Properties:{RoleName:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:m,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(c&&c.length>0)p.Properties.ManagedPolicyArns=c;return{role:p,logicalId:d}}static createGroup(e){let{slug:n,environment:r,groupName:i,managedPolicyArns:s}=e,a=i||l({slug:n,environment:r,resourceType:"group"}),c=o(a),u={Type:"AWS::IAM::Group",Properties:{GroupName:a}};if(s&&s.length>0)u.Properties.ManagedPolicyArns=s;return{group:u,logicalId:c}}static createPolicy(e){let{slug:n,environment:r,policyName:i,description:s,statements:a}=e,c=i||l({slug:n,environment:r,resourceType:"policy"}),u=o(c),d=a.map((p)=>({Sid:p.sid,Effect:p.effect||"Allow",Action:p.actions,Resource:p.resources,Condition:p.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:c,Description:s||`Managed policy for ${c}`,PolicyDocument:{Version:"2012-10-17",Statement:d}}},logicalId:u}}static attachPolicyToRole(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static attachPolicyToUser(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static attachPolicyToGroup(e,n){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(n))e.Properties.ManagedPolicyArns.push(n);return e}static addInlinePolicyToRole(e,n,r){if(!e.Properties.Policies)e.Properties.Policies=[];let i=r.map((s)=>({Effect:s.effect||"Allow",Action:s.actions,Resource:s.resources}));return e.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:i}}),e}static addInlinePolicyToUser(e,n,r){if(!e.Properties.Policies)e.Properties.Policies=[];let i=r.map((s)=>({Effect:s.effect||"Allow",Action:s.actions,Resource:s.resources}));return e.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:i}}),e}static createAccessKey(e,n){let{slug:r,environment:i,status:s="Active"}=n,a=l({slug:r,environment:i,resourceType:"access-key"}),c=o(a);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:R.Ref(e),Status:s}},logicalId:c}}static createInstanceProfile(e,n){let{slug:r,environment:i,profileName:s}=n,a=s||l({slug:r,environment:i,resourceType:"instance-profile"}),c=o(a);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:a,Roles:[R.Ref(e)]}},logicalId:c}}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(e){let{slug:n,environment:r,permissions:i,createAccessKey:s=!0}=e,a={},c=[];if(i.s3Buckets&&i.s3Buckets.length>0)c.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...i.s3Buckets,...i.s3Buckets.map((h)=>`${h}/*`)]});if(i.cloudFrontDistributions&&i.cloudFrontDistributions.length>0)c.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:i.cloudFrontDistributions});if(i.ecrRepositories&&i.ecrRepositories.length>0)c.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:i.ecrRepositories}),c.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(i.ecsServices&&i.ecsServices.length>0)c.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:i.ecsServices}),c.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),c.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(i.cloudFormationStacks&&i.cloudFormationStacks.length>0)c.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:i.cloudFormationStacks});if(i.lambdaFunctions&&i.lambdaFunctions.length>0)c.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:i.lambdaFunctions});if(i.secretsManagerSecrets&&i.secretsManagerSecrets.length>0)c.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:i.secretsManagerSecrets});let{policy:u,logicalId:d}=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${r})`,statements:c});a[d]=u;let{user:m,logicalId:p}=we.createUser({slug:n,environment:r,userName:l({slug:n,environment:r,resourceType:"cicd-user"}),managedPolicyArns:[R.Ref(d)]});a[p]=m;let g,y;if(s){let h=we.createAccessKey(p,{slug:n,environment:r});g=h.accessKey,y=h.logicalId,a[y]=g}return{user:m,accessKey:g,policy:u,userLogicalId:p,accessKeyLogicalId:y,policyLogicalId:d,resources:a}}static createCrossAccountRole(e){let{slug:n,environment:r,trustedAccountIds:i,externalId:s,permissions:a,maxSessionDuration:c=3600}=e,u={},{policy:d,logicalId:m}=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${r})`,statements:a});u[m]=d;let p=l({slug:n,environment:r,resourceType:"cross-account-role"}),g=o(p),y={};if(s)y.StringEquals={"sts:ExternalId":s};let h={Type:"AWS::IAM::Role",Properties:{RoleName:p,MaxSessionDuration:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:i.map((f)=>`arn:aws:iam::${f}:root`)},Action:"sts:AssumeRole",...Object.keys(y).length>0?{Condition:y}:{}}]},ManagedPolicyArns:[R.Ref(m)],Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r},{Key:"Purpose",Value:"Cross-Account Access"}]}};return u[g]=h,{role:h,policy:d,roleLogicalId:g,policyLogicalId:m,resources:u}}static createCliUser(e){let{slug:n,environment:r,permissions:i="readonly"}=e,s={},a=[],c=[];switch(i){case"readonly":c=[we.ManagedPolicies.ReadOnlyAccess];break;case"deploy":a=[{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":c=[we.ManagedPolicies.AdministratorAccess];break}let u,d;if(a.length>0){let h=we.createPolicy({slug:n,environment:r,policyName:l({slug:n,environment:r,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${r})`,statements:a});u=h.policy,d=h.logicalId,s[d]=u,c=[R.Ref(d)]}let{user:m,logicalId:p}=we.createUser({slug:n,environment:r,userName:l({slug:n,environment:r,resourceType:"cli-user"}),managedPolicyArns:c});s[p]=m;let{accessKey:g,logicalId:y}=we.createAccessKey(p,{slug:n,environment:r});return s[y]=g,{user:m,accessKey:g,policy:u,userLogicalId:p,accessKeyLogicalId:y,policyLogicalId:d,resources:s}}static CiCdPolicies={s3Deployment:(e)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:e},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:e.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(e)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:e}],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:(e)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:e}],lambdaDeployment:(e)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:e}],cloudFormationDeployment:(e)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:e}]}}class qo{static createRestApi(e){let{slug:n,environment:r,name:i,description:s,endpointType:a="REGIONAL",binaryMediaTypes:c,compressionSize:u}=e,d=i||l({slug:n,environment:r,resourceType:"rest-api"}),m=o(d),p={Type:"AWS::ApiGateway::RestApi",Properties:{Name:d,Description:s||`REST API for ${n} ${r}`,EndpointConfiguration:{Types:[a]},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r}]}};if(c&&c.length>0)p.Properties.BinaryMediaTypes=c;if(u!==void 0)p.Properties.MinimumCompressionSize=u;return{restApi:p,logicalId:m}}static createHttpApi(e){let{slug:n,environment:r,name:i,description:s,corsEnabled:a=!0,corsOrigins:c=["*"],corsMethods:u=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:d=["*"],corsMaxAge:m=86400,corsAllowCredentials:p=!1}=e,g=i||l({slug:n,environment:r,resourceType:"http-api"}),y=o(g),h={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:g,Description:s||`HTTP API for ${n} ${r}`,ProtocolType:"HTTP",Tags:{Name:g,Environment:r}}};if(a)h.Properties.CorsConfiguration={AllowOrigins:c,AllowMethods:u,AllowHeaders:d,MaxAge:m,AllowCredentials:p};return{httpApi:h,logicalId:y}}static createWebSocketApi(e){let{slug:n,environment:r,name:i,description:s}=e,a=i||l({slug:n,environment:r,resourceType:"ws-api"}),c=o(a);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:a,Description:s||`WebSocket API for ${n} ${r}`,ProtocolType:"WEBSOCKET",Tags:{Name:a,Environment:r}}},logicalId:c}}static createDeployment(e,n){let{slug:r,environment:i,description:s}=n,a=l({slug:r,environment:i,resourceType:"api-deployment"}),c=o(a);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:R.Ref(e),Description:s||`Deployment for ${a}`}},logicalId:c}}static createStage(e,n,r){let{slug:i,environment:s,stageName:a,description:c,cacheEnabled:u=!1,cacheSize:d="0.5",variables:m,throttling:p}=r,g=l({slug:i,environment:s,resourceType:"api-stage"}),y=o(g),h={Type:"AWS::ApiGateway::Stage",Properties:{StageName:a||s,RestApiId:R.Ref(e),DeploymentId:R.Ref(n),Description:c,CacheClusterEnabled:u,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u)h.Properties.CacheClusterSize=d;if(m)h.Properties.Variables=m;if(p)h.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:p.burstLimit,ThrottlingRateLimit:p.rateLimit}];return{stage:h,logicalId:y}}static createAuthorizer(e,n){let{slug:r,environment:i,name:s,type:a,functionArn:c,identitySource:u,userPoolArns:d,ttl:m=300}=n,p=s||l({slug:r,environment:i,resourceType:"api-authorizer"}),g=o(p),y={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:p,Type:a,RestApiId:R.Ref(e),AuthorizerResultTtlInSeconds:m}};if(a==="TOKEN"||a==="REQUEST"){if(!c)throw Error("Lambda authorizer requires functionArn");y.Properties.AuthorizerUri=c,y.Properties.IdentitySource=u||"method.request.header.Authorization"}if(a==="COGNITO_USER_POOLS"){if(!d||d.length===0)throw Error("Cognito authorizer requires userPoolArns");y.Properties.ProviderARNs=d,y.Properties.IdentitySource=u||"method.request.header.Authorization"}return{authorizer:y,logicalId:g}}static setCors(e,n={}){let{origins:r=["*"],methods:i=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:s=["*"],maxAge:a=86400,allowCredentials:c=!1}=n;return e.Properties.CorsConfiguration={AllowOrigins:r,AllowMethods:i,AllowHeaders:s,MaxAge:a,AllowCredentials:c},e}static addThrottling(e,n=5000,r=1e4){if(!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:r}),e}static enableCaching(e,n="0.5",r=300){if(e.Properties.CacheClusterEnabled=!0,e.Properties.CacheClusterSize=n,!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:r}),e}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 _e{static createTopic(e){let{slug:n,environment:r,topicName:i,displayName:s,encrypted:a=!1,kmsKeyId:c}=e,u=i||l({slug:n,environment:r,resourceType:"topic"}),d=o(u),m={Type:"AWS::SNS::Topic",Properties:{TopicName:u,DisplayName:s||u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:r}]}};if(a&&c)m.Properties.KmsMasterKeyId=c;return{topic:m,logicalId:d}}static subscribe(e,n){let{slug:r,environment:i,protocol:s,endpoint:a,filterPolicy:c,rawMessageDelivery:u=!1}=n,d=l({slug:r,environment:i,resourceType:"subscription"}),m=a.replace(/[^a-zA-Z0-9]/g,""),p=m.length>12?m.slice(-12):m,g=o(`${d}-${s}-${p}`),y={Type:"AWS::SNS::Subscription",Properties:{TopicArn:R.Ref(e),Protocol:s,Endpoint:a,RawMessageDelivery:u}};if(c)y.Properties.FilterPolicy=c;return{subscription:y,logicalId:g}}static subscribeEmail(e,n,r){return _e.subscribe(e,{...r,protocol:"email",endpoint:n})}static subscribeLambda(e,n,r){return _e.subscribe(e,{...r,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(e,n,r){return _e.subscribe(e,{...r,protocol:"sqs",endpoint:n})}static subscribeHttp(e,n,r){let i=n.startsWith("https://")?"https":"http";return _e.subscribe(e,{...r,protocol:i,endpoint:n})}static subscribeSms(e,n,r){return _e.subscribe(e,{...r,protocol:"sms",endpoint:n})}static setTopicPolicy(e,n){let{slug:r,environment:i,allowedPrincipals:s,allowedServices:a,actions:c="SNS:Publish"}=n,u=l({slug:r,environment:i,resourceType:"topic-policy"}),d=o(u),m={};if(s)m.AWS=s;if(a)m.Service=a;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[R.Ref(e)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:m,Action:c,Resource:R.Ref(e)}]}}},logicalId:d}}static allowCloudWatchAlarms(e,n){return _e.setTopicPolicy(e,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(e,n){return _e.setTopicPolicy(e,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(e,n){return _e.setTopicPolicy(e,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(e,n){if(!e.Properties)e.Properties={};return e.Properties.KmsMasterKeyId=n,e}static addInlineSubscription(e,n,r){if(!e.Properties)e.Properties={};if(!e.Properties.Subscription)e.Properties.Subscription=[];return e.Properties.Subscription.push({Protocol:n,Endpoint:r}),e}static FilterPolicies={eventType:(e)=>({eventType:e}),status:(e)=>({status:e}),numericRange:(e,n,r)=>({[e]:[{numeric:[">=",n,"<=",r]}]}),prefix:(e,n)=>({[e]:[{prefix:n}]}),and:(...e)=>Object.assign({},...e),exists:(e,n)=>({[e]:[{exists:n}]})};static UseCases={createAlertTopic:(e)=>_e.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-alerts`,displayName:e.displayName||"Alert Notifications"}),createEventFanout:(e)=>_e.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-events`,displayName:e.displayName||"Event Fanout"}),createNotificationTopic:(e)=>_e.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-notifications`,displayName:e.displayName||"User Notifications"})}}class au{static createStateMachine(e){let{slug:n,environment:r,stateMachineName:i,type:s="STANDARD",definition:a,roleArn:c,loggingConfiguration:u,tracingConfiguration:d}=e,m=i||l({slug:n,environment:r,resourceType:"state-machine"}),p=o(m),g,y,h;if(c)h=c;else{let S=l({slug:n,environment:r,resourceType:"state-machine-role"});y=o(S),g={Type:"AWS::IAM::Role",Properties:{RoleName:S,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:S},{Key:"Environment",Value:r}]}},h=R.GetAtt(y,"Arn")}let f={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:m,StateMachineType:s,DefinitionString:JSON.stringify(a),RoleArn:h,Tags:[{Key:"Name",Value:m},{Key:"Environment",Value:r}]}};if(u)f.Properties.LoggingConfiguration={Level:u.level,IncludeExecutionData:u.includeExecutionData,Destinations:u.destinations?.map((S)=>({CloudWatchLogsLogGroup:{LogGroupArn:S}}))};if(d)f.Properties.TracingConfiguration={Enabled:d.enabled};return{stateMachine:f,logicalId:p,role:g,roleLogicalId:y}}static createLambdaTask(e,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:e,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(e,n,r,i){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"}[e],Parameters:{TableName:n,...r},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSNSPublishTask(e,n,r){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:e,Message:n},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createSQSSendMessageTask(e,n,r){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:e,MessageBody:n},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createPassState(e){return{Type:"Pass",Result:e?.result,ResultPath:e?.resultPath,Parameters:e?.parameters,Next:e?.next,End:e?.end}}static createWaitState(e){return{Type:"Wait",Seconds:e.seconds,Timestamp:e.timestamp,SecondsPath:e.secondsPath,TimestampPath:e.timestampPath,Next:e.next,End:e.end}}static createChoiceState(e,n){return{Type:"Choice",Choices:e,Default:n}}static createParallelState(e,n){return{Type:"Parallel",Branches:e,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(e,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:e,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(e,n){return{Type:"Fail",Error:e,Cause:n}}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:(e,n,r,i)=>({ErrorEquals:e,IntervalSeconds:n,MaxAttempts:r,BackoffRate:i})};static CatchPolicies={all:(e,n)=>({ErrorEquals:["States.ALL"],Next:e,ResultPath:n||"$.error"}),specific:(e,n,r)=>({ErrorEquals:e,Next:n,ResultPath:r||"$.error"})};static Patterns={sequential:(e,n,r)=>{let i={};return r.forEach((s,a)=>{let c=a===r.length-1;i[s.name]={...s.state,Next:c?void 0:r[a+1].name,End:c}}),{Comment:"Sequential workflow",StartAt:r[0].name,States:i}},fanout:(e,n,r)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:r.map((i)=>i.definition),End:!0}}}),map:(e,n,r,i)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:r,MaxConcurrency:i,End:!0}}}),withErrorHandling:(e,n,r,i)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...r,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:i,Success:{Type:"Succeed"}}})}}class Oi{static createAlarm(e){let{slug:n,environment:r,alarmName:i,metricName:s,namespace:a,statistic:c="Average",period:u=300,evaluationPeriods:d=1,threshold:m,comparisonOperator:p,treatMissingData:g="notBreaching",actionsEnabled:y=!0,alarmActions:h,okActions:f,insufficientDataActions:S,dimensions:C,unit:P,datapointsToAlarm:E}=e,v=i||l({slug:n,environment:r,resourceType:"alarm"}),I=o(v),D={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:v,MetricName:s,Namespace:a,Statistic:c,Period:u,EvaluationPeriods:d,Threshold:m,ComparisonOperator:p,TreatMissingData:g,ActionsEnabled:y}};if(h&&h.length>0)D.Properties.AlarmActions=h;if(f&&f.length>0)D.Properties.OKActions=f;if(S&&S.length>0)D.Properties.InsufficientDataActions=S;if(C)D.Properties.Dimensions=Object.entries(C).map(([N,B])=>({Name:N,Value:B}));if(P)D.Properties.Unit=P;if(E!==void 0)D.Properties.DatapointsToAlarm=E;return{alarm:D,logicalId:I}}static createCompositeAlarm(e){let{slug:n,environment:r,alarmName:i,alarmRule:s,actionsEnabled:a=!0,alarmActions:c,okActions:u,insufficientDataActions:d}=e,m=i||l({slug:n,environment:r,resourceType:"composite-alarm"}),p=o(m),g={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:m,AlarmRule:s,ActionsEnabled:a}};if(c&&c.length>0)g.Properties.AlarmActions=c;if(u&&u.length>0)g.Properties.OKActions=u;if(d&&d.length>0)g.Properties.InsufficientDataActions=d;return{alarm:g,logicalId:p}}static createDashboard(e){let{slug:n,environment:r,dashboardName:i,widgets:s}=e,a=i||l({slug:n,environment:r,resourceType:"dashboard"}),c=o(a),u={widgets:s.map((m)=>({type:m.type,x:m.x,y:m.y,width:m.width,height:m.height,properties:m.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:a,DashboardBody:JSON.stringify(u)}},logicalId:c}}static createLogGroup(e){let{slug:n,environment:r,logGroupName:i,retentionInDays:s,kmsKeyId:a}=e,c=i||l({slug:n,environment:r,resourceType:"log-group"}),u=o(c),d={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:c}};if(s!==void 0)d.Properties.RetentionInDays=s;if(a)d.Properties.KmsKeyId=a;return{logGroup:d,logicalId:u}}static createLogStream(e,n){let{slug:r,environment:i,logStreamName:s}=n,a=s||l({slug:r,environment:i,resourceType:"log-stream"}),c=o(a);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:R.Ref(e),LogStreamName:a}},logicalId:c}}static createMetricFilter(e,n){let{slug:r,environment:i,filterName:s,filterPattern:a,metricTransformations:c}=n,u=s||l({slug:r,environment:i,resourceType:"metric-filter"}),d=o(u);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:R.Ref(e),FilterPattern:a,MetricTransformations:c.map((p)=>({MetricName:p.metricName,MetricNamespace:p.metricNamespace,MetricValue:p.metricValue,DefaultValue:p.defaultValue,Unit:p.unit}))}},logicalId:d}}static AlarmTypes={highCpu:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0}),highMemory:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0}),highDisk:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:s?[s]:void 0}),lambdaErrors:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:r},alarmActions:s?[s]:void 0}),lambdaThrottles:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:r},alarmActions:s?[s]:void 0}),apiGateway5xxErrors:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:r},alarmActions:s?[s]:void 0}),apiGateway4xxErrors:(e,n,r,i=50,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:r},alarmActions:s?[s]:void 0}),dynamoDBThrottles:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:r},alarmActions:s?[s]:void 0}),rdsCpu:(e,n,r,i=80,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:r},alarmActions:s?[s]:void 0}),rdsFreeStorage:(e,n,r,i=5368709120,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:r},alarmActions:s?[s]:void 0,unit:"Bytes"}),sqsQueueDepth:(e,n,r,i=100,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:r},alarmActions:s?[s]:void 0}),albUnhealthyTargets:(e,n,r,i,s=1,a)=>({slug:e,environment:n,alarmName:`${e}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:r,TargetGroup:i},alarmActions:a?[a]:void 0}),sesBounceRate:(e,n,r=5,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:r/100,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),sesComplaintRate:(e,n,r=0.1,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:r/100,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),smsDeliveryFailure:(e,n,r,i=10,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:r},alarmActions:s?[s]:void 0}),smsSpendLimit:(e,n,r=100,i)=>({slug:e,environment:n,alarmName:`${e}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",alarmActions:i?[i]:void 0}),connectMissedCalls:(e,n,r,i=5,s)=>({slug:e,environment:n,alarmName:`${e}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:r},alarmActions:s?[s]:void 0})};static DashboardWidgets={metric:(e,n,r,i,s,a)=>({type:"metric",x:e,y:n,width:r,height:i,properties:{metrics:s,title:a||"Metrics",region:"us-east-1",period:300}}),text:(e,n,r,i,s)=>({type:"text",x:e,y:n,width:r,height:i,properties:{markdown:s}}),log:(e,n,r,i,s,a)=>({type:"log",x:e,y:n,width:r,height:i,properties:{query:`SOURCE '${s.join("' | SOURCE '")}'
2275
2275
  | fields @timestamp, @message
2276
2276
  | sort @timestamp desc
2277
2277
  | limit 20`,region:"us-east-1",title:a||"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:(e,n)=>`{ $.${e} = "${n}" }`,httpStatus:(e)=>`[..., status_code = ${e}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(e){let{slug:n,environment:r,region:i="us-east-1",components:s={}}=e,a=[],c=0;if(a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:`# ${n.toUpperCase()} Dashboard (${r})`}}),c+=1,s.ec2InstanceIds&&s.ec2InstanceIds.length>0)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),c+=1,a.push({type:"metric",x:0,y:c,width:8,height:6,properties:{title:"CPU Utilization",region:i,metrics:s.ec2InstanceIds.map((u)=>["AWS/EC2","CPUUtilization","InstanceId",u]),period:300,stat:"Average"}}),a.push({type:"metric",x:8,y:c,width:8,height:6,properties:{title:"Network Traffic",region:i,metrics:[...s.ec2InstanceIds.flatMap((u)=>[["AWS/EC2","NetworkIn","InstanceId",u,{label:`${u} In`}],["AWS/EC2","NetworkOut","InstanceId",u,{label:`${u} Out`}]])],period:300,stat:"Sum"}}),a.push({type:"metric",x:16,y:c,width:8,height:6,properties:{title:"Status Checks",region:i,metrics:s.ec2InstanceIds.map((u)=>["AWS/EC2","StatusCheckFailed","InstanceId",u]),period:60,stat:"Maximum"}}),c+=6;if(s.lambdaFunctionNames&&s.lambdaFunctionNames.length>0)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),c+=1,a.push({type:"metric",x:0,y:c,width:8,height:6,properties:{title:"Invocations",region:i,metrics:s.lambdaFunctionNames.map((u)=>["AWS/Lambda","Invocations","FunctionName",u]),period:300,stat:"Sum"}}),a.push({type:"metric",x:8,y:c,width:8,height:6,properties:{title:"Duration",region:i,metrics:s.lambdaFunctionNames.map((u)=>["AWS/Lambda","Duration","FunctionName",u]),period:300,stat:"Average"}}),a.push({type:"metric",x:16,y:c,width:8,height:6,properties:{title:"Errors",region:i,metrics:s.lambdaFunctionNames.map((u)=>["AWS/Lambda","Errors","FunctionName",u]),period:300,stat:"Sum"}}),c+=6;if(s.ecsClusterName&&s.ecsServiceName)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## ECS Service"}}),c+=1,a.push({type:"metric",x:0,y:c,width:8,height:6,properties:{title:"CPU Utilization",region:i,metrics:[["AWS/ECS","CPUUtilization","ClusterName",s.ecsClusterName,"ServiceName",s.ecsServiceName]],period:300,stat:"Average"}}),a.push({type:"metric",x:8,y:c,width:8,height:6,properties:{title:"Memory Utilization",region:i,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",s.ecsClusterName,"ServiceName",s.ecsServiceName]],period:300,stat:"Average"}}),a.push({type:"metric",x:16,y:c,width:8,height:6,properties:{title:"Running Tasks",region:i,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",s.ecsClusterName,"ServiceName",s.ecsServiceName]],period:60,stat:"Average"}}),c+=6;if(s.albName)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),c+=1,a.push({type:"metric",x:0,y:c,width:8,height:6,properties:{title:"Request Count",region:i,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",s.albName]],period:60,stat:"Sum"}}),a.push({type:"metric",x:8,y:c,width:8,height:6,properties:{title:"Response Time",region:i,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",s.albName]],period:60,stat:"Average"}}),a.push({type:"metric",x:16,y:c,width:8,height:6,properties:{title:"HTTP Errors",region:i,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",s.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",s.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),c+=6;if(s.rdsInstanceId)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## RDS Database"}}),c+=1,a.push({type:"metric",x:0,y:c,width:8,height:6,properties:{title:"CPU Utilization",region:i,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",s.rdsInstanceId]],period:300,stat:"Average"}}),a.push({type:"metric",x:8,y:c,width:8,height:6,properties:{title:"Database Connections",region:i,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",s.rdsInstanceId]],period:60,stat:"Sum"}}),a.push({type:"metric",x:16,y:c,width:8,height:6,properties:{title:"Free Storage Space",region:i,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",s.rdsInstanceId]],period:300,stat:"Average"}}),c+=6;if(s.sqsQueueNames&&s.sqsQueueNames.length>0)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## SQS Queues"}}),c+=1,a.push({type:"metric",x:0,y:c,width:12,height:6,properties:{title:"Messages Visible",region:i,metrics:s.sqsQueueNames.map((u)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",u]),period:60,stat:"Sum"}}),a.push({type:"metric",x:12,y:c,width:12,height:6,properties:{title:"Message Age",region:i,metrics:s.sqsQueueNames.map((u)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",u]),period:60,stat:"Maximum"}}),c+=6;if(s.logGroupNames&&s.logGroupNames.length>0)a.push({type:"text",x:0,y:c,width:24,height:1,properties:{markdown:"## Application Logs"}}),c+=1,a.push({type:"log",x:0,y:c,width:24,height:6,properties:{query:`SOURCE '${s.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:i,title:"Recent Errors and Warnings"}}),c+=6;return Ni.createDashboard({slug:n,environment:r,widgets:a})}static DashboardTemplates={staticWebsite:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.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",e.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",e.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",e.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",e.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:e.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",e.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:e.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",e.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",e.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",e.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",e.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",e.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...e.lambdaFunctionNames.map((n,r)=>({type:"metric",x:r%3*8,y:7+Math.floor(r/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:e.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:e.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:e.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:e.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",e.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",e.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",e.albName]],period:60,stat:"Average"}},...e.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:e.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",e.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:e.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",e.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(e)=>{let{metricName:n,namespace:r,threshold:i,comparisonOperator:s="GreaterThanThreshold",evaluationPeriods:a=1,period:c=300,statistic:u="Average",treatMissingData:d="missing"}=e;return{MetricName:n,Namespace:r,Threshold:i,ComparisonOperator:s,EvaluationPeriods:a,Period:c,Statistic:u,TreatMissingData:d}},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:(e=80)=>({metricName:"CPUUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(e=80)=>({metricName:"MemoryUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(e=10)=>({metricName:"Errors",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(e=5000)=>({metricName:"Duration",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(e=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(e=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(e=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Ae{static createUserPool(e){let{slug:n,environment:r,userPoolName:i,aliasAttributes:s,autoVerifiedAttributes:a,passwordPolicy:c,mfaConfiguration:u,emailConfiguration:d,smsConfiguration:m,lambdaTriggers:p,userPoolAddOns:g,accountRecoverySetting:y}=e,h=i||l({slug:n,environment:r,resourceType:"user-pool"}),f=o(h),S={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:h,Policies:c?{PasswordPolicy:{MinimumLength:c.minimumLength,RequireLowercase:c.requireLowercase,RequireUppercase:c.requireUppercase,RequireNumbers:c.requireNumbers,RequireSymbols:c.requireSymbols,TemporaryPasswordValidityDays:c.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:u,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(s&&s.length>0)S.Properties.UsernameAttributes=s;if(a&&a.length>0)S.Properties.AutoVerifiedAttributes=a;if(d)S.Properties.EmailConfiguration={EmailSendingAccount:d.emailSendingAccount,From:d.from,ReplyToEmailAddress:d.replyToEmailAddress,SourceArn:d.sourceArn,ConfigurationSet:d.configurationSet};if(m)S.Properties.SmsConfiguration={ExternalId:m.externalId,SnsCallerArn:m.snsCallerArn};if(p)S.Properties.LambdaConfig={PreSignUp:p.preSignUp,PostConfirmation:p.postConfirmation,PreAuthentication:p.preAuthentication,PostAuthentication:p.postAuthentication,CustomMessage:p.customMessage,DefineAuthChallenge:p.defineAuthChallenge,CreateAuthChallenge:p.createAuthChallenge,VerifyAuthChallengeResponse:p.verifyAuthChallengeResponse,PreTokenGeneration:p.preTokenGeneration,UserMigration:p.userMigration};if(g)S.Properties.UserPoolAddOns={AdvancedSecurityMode:g.advancedSecurityMode};if(y)S.Properties.AccountRecoverySetting={RecoveryMechanisms:y.recoveryMechanisms};return{userPool:S,logicalId:f}}static createUserPoolClient(e,n){let{slug:r,environment:i,clientName:s,generateSecret:a=!1,refreshTokenValidity:c,accessTokenValidity:u,idTokenValidity:d,tokenValidityUnits:m,readAttributes:p,writeAttributes:g,explicitAuthFlows:y,preventUserExistenceErrors:h,enableTokenRevocation:f,callbackURLs:S,logoutURLs:C,allowedOAuthFlows:P,allowedOAuthScopes:E,allowedOAuthFlowsUserPoolClient:v,supportedIdentityProviders:I}=n,D=s||l({slug:r,environment:i,resourceType:"user-pool-client"}),x=o(D);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:D,UserPoolId:R.Ref(e),GenerateSecret:a,RefreshTokenValidity:c,AccessTokenValidity:u,IdTokenValidity:d,TokenValidityUnits:m,ReadAttributes:p,WriteAttributes:g,ExplicitAuthFlows:y,PreventUserExistenceErrors:h,EnableTokenRevocation:f,CallbackURLs:S,LogoutURLs:C,AllowedOAuthFlows:P,AllowedOAuthScopes:E,AllowedOAuthFlowsUserPoolClient:v,SupportedIdentityProviders:I}},logicalId:x}}static createUserPoolDomain(e,n){let{slug:r,environment:i,domain:s,customDomainConfig:a}=n,c=l({slug:r,environment:i,resourceType:"user-pool-domain"}),u=o(c);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:s,UserPoolId:R.Ref(e),CustomDomainConfig:a}},logicalId:u}}static createIdentityPool(e){let{slug:n,environment:r,identityPoolName:i,allowUnauthenticatedIdentities:s=!1,cognitoIdentityProviders:a,supportedLoginProviders:c,samlProviderARNs:u,openIdConnectProviderARNs:d}=e,m=i||l({slug:n,environment:r,resourceType:"identity-pool"}),p=o(m);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:m,AllowUnauthenticatedIdentities:s,CognitoIdentityProviders:a,SupportedLoginProviders:c,SamlProviderARNs:u,OpenIdConnectProviderARNs:d}},logicalId:p}}static createIdentityPoolRoleAttachment(e,n){let{slug:r,environment:i,authenticatedRole:s,unauthenticatedRole:a,roleMappings:c}=n,u=l({slug:r,environment:i,resourceType:"identity-pool-role-attachment"}),d=o(u),m={authenticated:s};if(a)m.unauthenticated=a;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:R.Ref(e),Roles:m,RoleMappings:c}},logicalId:d}}static createAuthenticatedRole(e){let{slug:n,environment:r,identityPoolLogicalId:i}=e,s=l({slug:n,environment:r,resourceType:"cognito-authenticated-role"}),a=o(s);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":R.Ref(i)},"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:s},{Key:"Environment",Value:r}]}},logicalId:a}}static createUnauthenticatedRole(e){let{slug:n,environment:r,identityPoolLogicalId:i}=e,s=l({slug:n,environment:r,resourceType:"cognito-unauthenticated-role"}),a=o(s);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":R.Ref(i)},"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:s},{Key:"Environment",Value:r}]}},logicalId:a}}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:(e,n,r)=>{let{userPool:i,logicalId:s}=Ae.createUserPool({slug:e,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Ae.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:a,logicalId:c}=Ae.createUserPoolClient(s,{slug:e,environment:n,explicitAuthFlows:[...Ae.AuthFlows.standard],callbackURLs:[r],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Ae.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:i,poolId:s,client:a,clientId:c}},mobileApp:(e,n)=>{let{userPool:r,logicalId:i}=Ae.createUserPool({slug:e,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Ae.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:s,logicalId:a}=Ae.createUserPoolClient(i,{slug:e,environment:n,explicitAuthFlows:[...Ae.AuthFlows.standard]}),{identityPool:c,logicalId:u}=Ae.createIdentityPool({slug:e,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:R.Ref(a),ProviderName:R.GetAtt(i,"ProviderName")}]}),{role:d,logicalId:m}=Ae.createAuthenticatedRole({slug:e,environment:n,identityPoolLogicalId:u}),{attachment:p,logicalId:g}=Ae.createIdentityPoolRoleAttachment(u,{slug:e,environment:n,authenticatedRole:R.GetAtt(m,"Arn")});return{userPool:r,poolId:i,client:s,clientId:a,identityPool:c,identityPoolId:u,authRole:d,authRoleId:m,attachment:p,attachmentId:g}}}}import{createHash as Fr}from"node:crypto";import{copyFileSync as Gr,existsSync as ht,readdirSync as Wr,readFileSync as ze,statSync as Vr,writeFileSync as Qe}from"node:fs";import{basename as Ur,dirname as un,extname as dn,join as $e}from"node:path";class Re{static createApplication(e){let{slug:n,environment:r,applicationName:i,computePlatform:s}=e,a=i||l({slug:n,environment:r,resourceType:"deploy-app"}),c=o(a);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:a,ComputePlatform:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:r}]}},logicalId:c}}static createDeploymentGroup(e,n){let{slug:r,environment:i,deploymentGroupName:s,serviceRoleArn:a,autoScalingGroups:c,ec2TagFilters:u,deploymentConfigName:d,autoRollbackConfiguration:m,alarmConfiguration:p,loadBalancerInfo:g,blueGreenDeploymentConfiguration:y}=n,h=s||l({slug:r,environment:i,resourceType:"deploy-group"}),f=o(h);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:R.Ref(e),DeploymentGroupName:h,ServiceRoleArn:a,AutoScalingGroups:c,Ec2TagFilters:u?.map((C)=>({Key:C.key,Value:C.value,Type:C.type})),DeploymentConfigName:d,AutoRollbackConfiguration:m?{Enabled:m.enabled,Events:m.events}:void 0,AlarmConfiguration:p?{Enabled:p.enabled,Alarms:p.alarms?.map((C)=>({Name:C.name})),IgnorePollAlarmFailure:p.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:g?{TargetGroupInfoList:g.targetGroupInfoList?.map((C)=>({Name:C.name})),ElbInfoList:g.elbInfoList?.map((C)=>({Name:C.name}))}:void 0,BlueGreenDeploymentConfiguration:y?{TerminateBlueInstancesOnDeploymentSuccess:y.terminateBlueInstancesOnDeploymentSuccess?{Action:y.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:y.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:y.deploymentReadyOption?{ActionOnTimeout:y.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:y.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:y.greenFleetProvisioningOption?{Action:y.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:f}}static createDeploymentConfig(e){let{slug:n,environment:r,deploymentConfigName:i,minimumHealthyHosts:s,trafficRoutingConfig:a}=e,c=i||l({slug:n,environment:r,resourceType:"deploy-config"}),u=o(c);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:c,MinimumHealthyHosts:s?{Type:s.type,Value:s.value}:void 0,TrafficRoutingConfig:a?{Type:a.type,TimeBasedCanary:a.timeBasedCanary?{CanaryPercentage:a.timeBasedCanary.canaryPercentage,CanaryInterval:a.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:a.timeBasedLinear?{LinearPercentage:a.timeBasedLinear.linearPercentage,LinearInterval:a.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:u}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(e,n)=>({type:e,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(e,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:e,canaryInterval:n}}),linear:(e,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:e,linearInterval:n}})};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:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:e},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:e},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:(e,n,r,i)=>{let{application:s,logicalId:a}=Re.createApplication({slug:e,environment:n,computePlatform:"Server"}),{deploymentGroup:c,logicalId:u}=Re.createDeploymentGroup(a,{slug:e,environment:n,serviceRoleArn:r,autoScalingGroups:i,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Re.RollbackConfigs.onFailure()});return{application:s,appId:a,deploymentGroup:c,groupId:u}},lambdaCanaryDeployment:(e,n,r,i=10,s=5)=>{let{application:a,logicalId:c}=Re.createApplication({slug:e,environment:n,computePlatform:"Lambda"}),{deploymentConfig:u,logicalId:d}=Re.createDeploymentConfig({slug:e,environment:n,trafficRoutingConfig:Re.TrafficRouting.canary(i,s)}),{deploymentGroup:m,logicalId:p}=Re.createDeploymentGroup(c,{slug:e,environment:n,serviceRoleArn:r,deploymentConfigName:R.Ref(d),autoRollbackConfiguration:Re.RollbackConfigs.onAlarmOrFailure()});return{application:a,appId:c,deploymentConfig:u,configId:d,deploymentGroup:m,groupId:p}},ecsBlueGreenDeployment:(e,n,r,i)=>{let{application:s,logicalId:a}=Re.createApplication({slug:e,environment:n,computePlatform:"ECS"}),{deploymentGroup:c,logicalId:u}=Re.createDeploymentGroup(a,{slug:e,environment:n,serviceRoleArn:r,loadBalancerInfo:{targetGroupInfoList:[{name:i}]},blueGreenDeploymentConfiguration:Re.BlueGreenConfigs.standard(),autoRollbackConfiguration:Re.RollbackConfigs.onFailure()});return{application:s,appId:a,deploymentGroup:c,groupId:u}}};static Strategies={rolling:(e=25)=>({type:"rolling",batchPercentage:e}),blueGreen:()=>({type:"blue-green"}),canary:(e=10,n=5)=>({type:"canary",canaryPercentage:e,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class ne{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(e,n="md5"){let r=ze(e);return Fr(n).update(r).digest("hex")}static computeShortHash(e){return ne.computeFileHash(e).slice(0,8)}static getContentType(e){let n=dn(e).toLowerCase();return ne.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(e,n){return![...ne.NoHashPatterns,...n||[]].some((i)=>i.test(e))}static generateHashedFilename(e,n){let r=dn(e),i=Ur(e,r),s=un(e);if(s===".")return`${i}.${n}${r}`;return $e(s,`${i}.${n}${r}`)}static collectFiles(e,n){let r=[],i=n||e;if(!ht(e))return r;let s=Wr(e,{withFileTypes:!0});for(let a of s){let c=$e(e,a.name);if(a.isDirectory())r.push(...ne.collectFiles(c,i));else if(a.isFile())r.push(c)}return r}static hashDirectory(e){let{sourceDir:n,outputDir:r,excludePatterns:i=[],hashAlgorithm:s="md5",copyUnhashed:a=!0}=e,c=ne.collectFiles(n),u=[],d={};for(let p of c){let g=p.replace(n,"").replace(/^[/\\]/,""),y=ne.shouldHashFile(g,i),h=Vr(p),f=y?ne.computeFileHash(p,s).slice(0,8):"",S=y?ne.generateHashedFilename(g,f):g,C={originalPath:g,hashedPath:S,hash:f,size:h.size,contentType:ne.getContentType(p)};if(u.push(C),d[g]=S,r){let P=$e(r,S),E=un(P);if(!ht(E)){let{mkdirSync:v}=Lr("node:fs");v(E,{recursive:!0})}if(y||a)Gr(p,P)}}let m={version:"1.0",timestamp:new Date().toISOString(),assets:u,hashMap:d};if(r){let p=$e(r,"asset-manifest.json");Qe(p,JSON.stringify(m,null,2))}return m}static getInvalidationPaths(e,n){let r=[];if(!e)return["/*"];let i=e.hashMap,s=n.hashMap;for(let[a,c]of Object.entries(s)){let u=i[a];if(!u||u!==c){if(r.push(`/${a}`),u&&u!==c)r.push(`/${u}`)}}for(let[a,c]of Object.entries(i))if(!s[a])r.push(`/${a}`),r.push(`/${c}`);if(r.length>100)return["/*"];return[...new Set(r)]}static updateHtmlReferences(e){let{htmlDir:n,manifest:r,basePath:i=""}=e,s=ne.collectFiles(n).filter((a)=>a.endsWith(".html")||a.endsWith(".htm"));for(let a of s){let c=ze(a,"utf-8");for(let[u,d]of Object.entries(r.hashMap)){if(u===d)continue;let m=[new RegExp(`(src|href)=["']${i}/?${ne.escapeRegExp(u)}["']`,"g"),new RegExp(`url\\(["']?${i}/?${ne.escapeRegExp(u)}["']?\\)`,"g")];for(let p of m)c=c.replace(p,(g)=>g.replace(u,d))}Qe(a,c)}}static updateCssReferences(e){let{cssDir:n,manifest:r,basePath:i=""}=e,s=ne.collectFiles(n).filter((a)=>a.endsWith(".css"));for(let a of s){let c=ze(a,"utf-8");for(let[u,d]of Object.entries(r.hashMap)){if(u===d)continue;let m=new RegExp(`url\\(["']?${i}/?${ne.escapeRegExp(u)}["']?\\)`,"g");c=c.replace(m,`url(${i}/${d})`)}Qe(a,c)}}static escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(e){let{sourceDir:n,keyPrefix:r="",excludePatterns:i=[],cacheControl:s={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=e;return ne.hashDirectory({sourceDir:n,excludePatterns:i}).assets.map((c)=>{let u=c.hash!=="",d=c.contentType==="text/html",m=s.unhashed||"public, max-age=3600";if(d)m=s.html||"public, max-age=0, must-revalidate";else if(u)m=s.hashed||"public, max-age=31536000, immutable";return{localPath:$e(n,c.originalPath),s3Key:r?`${r}/${c.hashedPath}`:c.hashedPath,contentType:c.contentType,cacheControl:m,hash:c.hash}})}static compareManifests(e,n){let r={added:[],removed:[],changed:[],unchanged:[]},i=new Set(Object.keys(e.hashMap)),s=new Set(Object.keys(n.hashMap));for(let a of s)if(!i.has(a))r.added.push(a);for(let a of i)if(!s.has(a))r.removed.push(a);for(let a of s)if(i.has(a))if(e.hashMap[a]!==n.hashMap[a])r.changed.push(a);else r.unchanged.push(a);return r}static loadManifest(e){if(!ht(e))return null;try{let n=ze(e,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(e,n){Qe(n,JSON.stringify(e,null,2))}}class ki{static createSecret(e){let{slug:n,environment:r,secretName:i,description:s,secretString:a,kmsKeyId:c,tags:u}=e,d=i||l({slug:n,environment:r,resourceType:"secret"}),m=o(d),p={Type:"AWS::SecretsManager::Secret",Properties:{Name:d,Description:s,SecretString:a,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},...u?Object.entries(u).map(([g,y])=>({Key:g,Value:y})):[]]}};if(c)p.Properties.KmsKeyId=c;return{secret:p,logicalId:m}}static createGeneratedSecret(e){let{slug:n,environment:r,secretName:i,description:s,excludeCharacters:a,excludeLowercase:c,excludeNumbers:u,excludePunctuation:d,excludeUppercase:m,passwordLength:p,requireEachIncludedType:g,kmsKeyId:y,tags:h}=e,f=i||l({slug:n,environment:r,resourceType:"secret"}),S=o(f),C={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:s,GenerateSecretString:{ExcludeCharacters:a,ExcludeLowercase:c,ExcludeNumbers:u,ExcludePunctuation:d,ExcludeUppercase:m,PasswordLength:p||32,RequireEachIncludedType:g!==!1},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:r},...h?Object.entries(h).map(([P,E])=>({Key:P,Value:E})):[]]}};if(y)C.Properties.KmsKeyId=y;return{secret:C,logicalId:S}}static createDatabaseSecret(e){let{slug:n,environment:r,secretName:i,username:s,dbname:a,engine:c,host:u,port:d,kmsKeyId:m}=e,p=i||l({slug:n,environment:r,resourceType:"db-secret"}),g=o(p),y={username:s};if(a)y.dbname=a;if(c)y.engine=c;if(u)y.host=u;if(d)y.port=d;let h={Type:"AWS::SecretsManager::Secret",Properties:{Name:p,Description:`Database credentials for ${s}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(y),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r},{Key:"Type",Value:"database"}]}};if(m)h.Properties.KmsKeyId=m;return{secret:h,logicalId:g}}static attachToDatabase(e){let{slug:n,environment:r,secretId:i,targetId:s,targetType:a}=e,c=l({slug:n,environment:r,resourceType:"secret-attachment"}),u=o(c);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:i,TargetId:s,TargetType:a}},logicalId:u}}static enableRotation(e){let{slug:n,environment:r,secretId:i,rotationLambdaArn:s,automaticallyAfterDays:a,rotationType:c,kmsKeyArn:u,vpcSecurityGroupIds:d,vpcSubnetIds:m}=e,p=l({slug:n,environment:r,resourceType:"secret-rotation"}),g=o(p),y={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:i,RotationRules:{AutomaticallyAfterDays:a||30}}};if(s)y.Properties.RotationLambdaARN=s;else if(c)y.Properties.HostedRotationLambda={RotationType:c,KmsKeyArn:u,VpcSecurityGroupIds:d,VpcSubnetIds:m};return{rotation:y,logicalId:g}}static SecretTypes={apiKey:(e,n,r)=>ki.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-${r}-api-key`,description:`API key for ${r}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(e,n,r)=>ki.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-${r}-oauth-secret`,description:`OAuth client secret for ${r}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(e,n)=>ki.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(e,n)=>ki.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-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 X{static createParameter(e){let{slug:n,environment:r,parameterName:i,value:s,type:a="String",description:c,tier:u="Standard",tags:d}=e,m=i||l({slug:n,environment:r,resourceType:"parameter"}),p=o(m);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${r}/${m}`,Type:a,Value:s,Description:c,Tier:u,Tags:{Name:m,Environment:r,...d}}},logicalId:p}}static createString(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i,type:"String",description:s})}static createSecureString(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i,type:"SecureString",description:s})}static createStringList(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i.join(","),type:"StringList",description:s})}static Parameters={databaseUrl:(e,n,r)=>X.createSecureString(e,n,"database-url",r,"Database connection URL"),apiEndpoint:(e,n,r)=>X.createString(e,n,"api-endpoint",r,"API endpoint URL"),appVersion:(e,n,r)=>X.createString(e,n,"app-version",r,"Application version"),featureFlags:(e,n,r)=>X.createStringList(e,n,"feature-flags",r,"Enabled feature flags"),apiKey:(e,n,r,i)=>X.createSecureString(e,n,`${r}-api-key`,i,`API key for ${r}`),oauthCredentials:(e,n,r,i)=>{let s=X.createString(e,n,"oauth-client-id",r,"OAuth client ID"),a=X.createSecureString(e,n,"oauth-client-secret",i,"OAuth client secret");return{clientId:s,clientSecret:a}},smtpCredentials:(e,n,r,i,s,a)=>{let c=X.createString(e,n,"smtp-username",r,"SMTP username"),u=X.createSecureString(e,n,"smtp-password",i,"SMTP password"),d=X.createString(e,n,"smtp-host",s,"SMTP host"),m=X.createString(e,n,"smtp-port",a.toString(),"SMTP port");return{username:c,password:u,host:d,port:m}},redisUrl:(e,n,r)=>X.createSecureString(e,n,"redis-url",r,"Redis connection URL"),s3Bucket:(e,n,r)=>X.createString(e,n,"s3-bucket",r,"S3 bucket name"),cloudFrontDistribution:(e,n,r)=>X.createString(e,n,"cloudfront-distribution-id",r,"CloudFront distribution ID")}}class qt{static createDomain(e){let{slug:n,environment:r,domainName:i,engineVersion:s="OpenSearch_2.11",instanceType:a="t3.small.search",instanceCount:c=1,volumeSize:u=10,volumeType:d="gp3",dedicatedMaster:m=!1,dedicatedMasterType:p,dedicatedMasterCount:g=3,multiAz:y=!1,availabilityZoneCount:h=2,vpc:f,encryption:S,enforceHttps:C=!0,tlsSecurityPolicy:P="Policy-Min-TLS-1-2-2019-07",advancedSecurity:E,autoSnapshotHour:v=0,autoTune:I=!0,tags:D={}}=e,x=i||l({slug:n,environment:r,resourceType:"search"}),F=o(x);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:x,EngineVersion:s,ClusterConfig:{InstanceType:a,InstanceCount:c,DedicatedMasterEnabled:m,...m&&{DedicatedMasterType:p||a,DedicatedMasterCount:g},ZoneAwarenessEnabled:y,...y&&{ZoneAwarenessConfig:{AvailabilityZoneCount:h}}},EBSOptions:{EBSEnabled:!0,VolumeType:d,VolumeSize:u},DomainEndpointOptions:{EnforceHTTPS:C,TLSSecurityPolicy:P},SnapshotOptions:{AutomatedSnapshotStartHour:v},...f&&{VPCOptions:{SubnetIds:f.subnetIds,SecurityGroupIds:f.securityGroupIds}},...S&&{EncryptionAtRestOptions:{Enabled:S.atRest??!0,...S.kmsKeyId&&{KmsKeyId:S.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:S.nodeToNode??!0}},...E&&{AdvancedSecurityOptions:{Enabled:E.enabled,InternalUserDatabaseEnabled:E.internalUserDatabase??!0,...E.masterUserName&&E.masterUserPassword&&{MasterUserOptions:{MasterUserName:E.masterUserName,MasterUserPassword:E.masterUserPassword}},...E.masterUserArn&&{MasterUserOptions:{MasterUserARN:E.masterUserArn}}}},...I&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:r},...Object.entries(D).map(([O,G])=>({Key:O,Value:G}))]}},logicalId:F}}static createAccessPolicy(e,n){let{ipAddresses:r,iamPrincipalArns:i,allowAll:s,vpcEndpoint:a}=n;if(s)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};let c=[];if(i&&i.length>0)c.push({Effect:"Allow",Principal:{AWS:i},Action:"es:*",Resource:e});if(r&&r.length>0)c.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e,Condition:{IpAddress:{"aws:SourceIp":r}}});if(a)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};return{Version:"2012-10-17",Statement:c}}static DomainPresets={development:(e,n)=>qt.createDomain({slug:e,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(e,n,r)=>qt.createDomain({slug:e,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:r,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(e,n)=>qt.createDomain({slug:e,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(e,n,r)=>qt.createDomain({slug:e,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:r,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 At{static createDomainRedirectBucket(e){let{slug:n,environment:r,sourceDomain:i,targetDomain:s,protocol:a="https"}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"redirect"}),u=o(c),d=o(`${c}-policy`),m={Type:"AWS::S3::Bucket",Properties:{BucketName:i,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:s,Protocol:a}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r},{Key:"Purpose",Value:"Domain Redirect"}]}},p={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(u),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(u,"Arn"),"/*"])]}]}}};return{bucket:m,bucketPolicy:p,logicalId:u,policyLogicalId:d}}static createPathRedirectFunction(e){let{slug:n,environment:r,rules:i}=e,s=l({slug:n,environment:r,resourceType:"cf-redirect"}),a=o(s),c=At.generateRedirectFunctionCode(i);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:s,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${r})`,Runtime:"cloudfront-js-2.0"},FunctionCode:c}},logicalId:a,functionCode:c}}static generateRedirectFunctionCode(e){return`function handler(event) {
2281
+ | limit 50`,region:i,title:"Recent Errors and Warnings"}}),c+=6;return Oi.createDashboard({slug:n,environment:r,widgets:a})}static DashboardTemplates={staticWebsite:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.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",e.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",e.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",e.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",e.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:e.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",e.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:e.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",e.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",e.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",e.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",e.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",e.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...e.lambdaFunctionNames.map((n,r)=>({type:"metric",x:r%3*8,y:7+Math.floor(r/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:e.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:e.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:e.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:e.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",e.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",e.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",e.albName]],period:60,stat:"Average"}},...e.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:e.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",e.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:e.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",e.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(e)=>{let{metricName:n,namespace:r,threshold:i,comparisonOperator:s="GreaterThanThreshold",evaluationPeriods:a=1,period:c=300,statistic:u="Average",treatMissingData:d="missing"}=e;return{MetricName:n,Namespace:r,Threshold:i,ComparisonOperator:s,EvaluationPeriods:a,Period:c,Statistic:u,TreatMissingData:d}},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:(e=80)=>({metricName:"CPUUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(e=80)=>({metricName:"MemoryUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(e=10)=>({metricName:"Errors",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(e=5000)=>({metricName:"Duration",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(e=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(e=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(e=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Ae{static createUserPool(e){let{slug:n,environment:r,userPoolName:i,aliasAttributes:s,autoVerifiedAttributes:a,passwordPolicy:c,mfaConfiguration:u,emailConfiguration:d,smsConfiguration:m,lambdaTriggers:p,userPoolAddOns:g,accountRecoverySetting:y}=e,h=i||l({slug:n,environment:r,resourceType:"user-pool"}),f=o(h),S={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:h,Policies:c?{PasswordPolicy:{MinimumLength:c.minimumLength,RequireLowercase:c.requireLowercase,RequireUppercase:c.requireUppercase,RequireNumbers:c.requireNumbers,RequireSymbols:c.requireSymbols,TemporaryPasswordValidityDays:c.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:u,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(s&&s.length>0)S.Properties.UsernameAttributes=s;if(a&&a.length>0)S.Properties.AutoVerifiedAttributes=a;if(d)S.Properties.EmailConfiguration={EmailSendingAccount:d.emailSendingAccount,From:d.from,ReplyToEmailAddress:d.replyToEmailAddress,SourceArn:d.sourceArn,ConfigurationSet:d.configurationSet};if(m)S.Properties.SmsConfiguration={ExternalId:m.externalId,SnsCallerArn:m.snsCallerArn};if(p)S.Properties.LambdaConfig={PreSignUp:p.preSignUp,PostConfirmation:p.postConfirmation,PreAuthentication:p.preAuthentication,PostAuthentication:p.postAuthentication,CustomMessage:p.customMessage,DefineAuthChallenge:p.defineAuthChallenge,CreateAuthChallenge:p.createAuthChallenge,VerifyAuthChallengeResponse:p.verifyAuthChallengeResponse,PreTokenGeneration:p.preTokenGeneration,UserMigration:p.userMigration};if(g)S.Properties.UserPoolAddOns={AdvancedSecurityMode:g.advancedSecurityMode};if(y)S.Properties.AccountRecoverySetting={RecoveryMechanisms:y.recoveryMechanisms};return{userPool:S,logicalId:f}}static createUserPoolClient(e,n){let{slug:r,environment:i,clientName:s,generateSecret:a=!1,refreshTokenValidity:c,accessTokenValidity:u,idTokenValidity:d,tokenValidityUnits:m,readAttributes:p,writeAttributes:g,explicitAuthFlows:y,preventUserExistenceErrors:h,enableTokenRevocation:f,callbackURLs:S,logoutURLs:C,allowedOAuthFlows:P,allowedOAuthScopes:E,allowedOAuthFlowsUserPoolClient:v,supportedIdentityProviders:I}=n,D=s||l({slug:r,environment:i,resourceType:"user-pool-client"}),N=o(D);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:D,UserPoolId:R.Ref(e),GenerateSecret:a,RefreshTokenValidity:c,AccessTokenValidity:u,IdTokenValidity:d,TokenValidityUnits:m,ReadAttributes:p,WriteAttributes:g,ExplicitAuthFlows:y,PreventUserExistenceErrors:h,EnableTokenRevocation:f,CallbackURLs:S,LogoutURLs:C,AllowedOAuthFlows:P,AllowedOAuthScopes:E,AllowedOAuthFlowsUserPoolClient:v,SupportedIdentityProviders:I}},logicalId:N}}static createUserPoolDomain(e,n){let{slug:r,environment:i,domain:s,customDomainConfig:a}=n,c=l({slug:r,environment:i,resourceType:"user-pool-domain"}),u=o(c);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:s,UserPoolId:R.Ref(e),CustomDomainConfig:a}},logicalId:u}}static createIdentityPool(e){let{slug:n,environment:r,identityPoolName:i,allowUnauthenticatedIdentities:s=!1,cognitoIdentityProviders:a,supportedLoginProviders:c,samlProviderARNs:u,openIdConnectProviderARNs:d}=e,m=i||l({slug:n,environment:r,resourceType:"identity-pool"}),p=o(m);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:m,AllowUnauthenticatedIdentities:s,CognitoIdentityProviders:a,SupportedLoginProviders:c,SamlProviderARNs:u,OpenIdConnectProviderARNs:d}},logicalId:p}}static createIdentityPoolRoleAttachment(e,n){let{slug:r,environment:i,authenticatedRole:s,unauthenticatedRole:a,roleMappings:c}=n,u=l({slug:r,environment:i,resourceType:"identity-pool-role-attachment"}),d=o(u),m={authenticated:s};if(a)m.unauthenticated=a;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:R.Ref(e),Roles:m,RoleMappings:c}},logicalId:d}}static createAuthenticatedRole(e){let{slug:n,environment:r,identityPoolLogicalId:i}=e,s=l({slug:n,environment:r,resourceType:"cognito-authenticated-role"}),a=o(s);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":R.Ref(i)},"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:s},{Key:"Environment",Value:r}]}},logicalId:a}}static createUnauthenticatedRole(e){let{slug:n,environment:r,identityPoolLogicalId:i}=e,s=l({slug:n,environment:r,resourceType:"cognito-unauthenticated-role"}),a=o(s);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":R.Ref(i)},"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:s},{Key:"Environment",Value:r}]}},logicalId:a}}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:(e,n,r)=>{let{userPool:i,logicalId:s}=Ae.createUserPool({slug:e,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Ae.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:a,logicalId:c}=Ae.createUserPoolClient(s,{slug:e,environment:n,explicitAuthFlows:[...Ae.AuthFlows.standard],callbackURLs:[r],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Ae.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:i,poolId:s,client:a,clientId:c}},mobileApp:(e,n)=>{let{userPool:r,logicalId:i}=Ae.createUserPool({slug:e,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Ae.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:s,logicalId:a}=Ae.createUserPoolClient(i,{slug:e,environment:n,explicitAuthFlows:[...Ae.AuthFlows.standard]}),{identityPool:c,logicalId:u}=Ae.createIdentityPool({slug:e,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:R.Ref(a),ProviderName:R.GetAtt(i,"ProviderName")}]}),{role:d,logicalId:m}=Ae.createAuthenticatedRole({slug:e,environment:n,identityPoolLogicalId:u}),{attachment:p,logicalId:g}=Ae.createIdentityPoolRoleAttachment(u,{slug:e,environment:n,authenticatedRole:R.GetAtt(m,"Arn")});return{userPool:r,poolId:i,client:s,clientId:a,identityPool:c,identityPoolId:u,authRole:d,authRoleId:m,attachment:p,attachmentId:g}}}}import{createHash as Fr}from"node:crypto";import{copyFileSync as Gr,existsSync as ht,readdirSync as _r,readFileSync as ze,statSync as Wr,writeFileSync as Qe}from"node:fs";import{basename as Vr,dirname as un,extname as dn,join as Oe}from"node:path";class Re{static createApplication(e){let{slug:n,environment:r,applicationName:i,computePlatform:s}=e,a=i||l({slug:n,environment:r,resourceType:"deploy-app"}),c=o(a);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:a,ComputePlatform:s,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:r}]}},logicalId:c}}static createDeploymentGroup(e,n){let{slug:r,environment:i,deploymentGroupName:s,serviceRoleArn:a,autoScalingGroups:c,ec2TagFilters:u,deploymentConfigName:d,autoRollbackConfiguration:m,alarmConfiguration:p,loadBalancerInfo:g,blueGreenDeploymentConfiguration:y}=n,h=s||l({slug:r,environment:i,resourceType:"deploy-group"}),f=o(h);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:R.Ref(e),DeploymentGroupName:h,ServiceRoleArn:a,AutoScalingGroups:c,Ec2TagFilters:u?.map((C)=>({Key:C.key,Value:C.value,Type:C.type})),DeploymentConfigName:d,AutoRollbackConfiguration:m?{Enabled:m.enabled,Events:m.events}:void 0,AlarmConfiguration:p?{Enabled:p.enabled,Alarms:p.alarms?.map((C)=>({Name:C.name})),IgnorePollAlarmFailure:p.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:g?{TargetGroupInfoList:g.targetGroupInfoList?.map((C)=>({Name:C.name})),ElbInfoList:g.elbInfoList?.map((C)=>({Name:C.name}))}:void 0,BlueGreenDeploymentConfiguration:y?{TerminateBlueInstancesOnDeploymentSuccess:y.terminateBlueInstancesOnDeploymentSuccess?{Action:y.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:y.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:y.deploymentReadyOption?{ActionOnTimeout:y.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:y.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:y.greenFleetProvisioningOption?{Action:y.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:f}}static createDeploymentConfig(e){let{slug:n,environment:r,deploymentConfigName:i,minimumHealthyHosts:s,trafficRoutingConfig:a}=e,c=i||l({slug:n,environment:r,resourceType:"deploy-config"}),u=o(c);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:c,MinimumHealthyHosts:s?{Type:s.type,Value:s.value}:void 0,TrafficRoutingConfig:a?{Type:a.type,TimeBasedCanary:a.timeBasedCanary?{CanaryPercentage:a.timeBasedCanary.canaryPercentage,CanaryInterval:a.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:a.timeBasedLinear?{LinearPercentage:a.timeBasedLinear.linearPercentage,LinearInterval:a.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:u}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(e,n)=>({type:e,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(e,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:e,canaryInterval:n}}),linear:(e,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:e,linearInterval:n}})};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:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:e},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:e},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:(e,n,r,i)=>{let{application:s,logicalId:a}=Re.createApplication({slug:e,environment:n,computePlatform:"Server"}),{deploymentGroup:c,logicalId:u}=Re.createDeploymentGroup(a,{slug:e,environment:n,serviceRoleArn:r,autoScalingGroups:i,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Re.RollbackConfigs.onFailure()});return{application:s,appId:a,deploymentGroup:c,groupId:u}},lambdaCanaryDeployment:(e,n,r,i=10,s=5)=>{let{application:a,logicalId:c}=Re.createApplication({slug:e,environment:n,computePlatform:"Lambda"}),{deploymentConfig:u,logicalId:d}=Re.createDeploymentConfig({slug:e,environment:n,trafficRoutingConfig:Re.TrafficRouting.canary(i,s)}),{deploymentGroup:m,logicalId:p}=Re.createDeploymentGroup(c,{slug:e,environment:n,serviceRoleArn:r,deploymentConfigName:R.Ref(d),autoRollbackConfiguration:Re.RollbackConfigs.onAlarmOrFailure()});return{application:a,appId:c,deploymentConfig:u,configId:d,deploymentGroup:m,groupId:p}},ecsBlueGreenDeployment:(e,n,r,i)=>{let{application:s,logicalId:a}=Re.createApplication({slug:e,environment:n,computePlatform:"ECS"}),{deploymentGroup:c,logicalId:u}=Re.createDeploymentGroup(a,{slug:e,environment:n,serviceRoleArn:r,loadBalancerInfo:{targetGroupInfoList:[{name:i}]},blueGreenDeploymentConfiguration:Re.BlueGreenConfigs.standard(),autoRollbackConfiguration:Re.RollbackConfigs.onFailure()});return{application:s,appId:a,deploymentGroup:c,groupId:u}}};static Strategies={rolling:(e=25)=>({type:"rolling",batchPercentage:e}),blueGreen:()=>({type:"blue-green"}),canary:(e=10,n=5)=>({type:"canary",canaryPercentage:e,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class ne{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(e,n="md5"){let r=ze(e);return Fr(n).update(r).digest("hex")}static computeShortHash(e){return ne.computeFileHash(e).slice(0,8)}static getContentType(e){let n=dn(e).toLowerCase();return ne.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(e,n){return![...ne.NoHashPatterns,...n||[]].some((i)=>i.test(e))}static generateHashedFilename(e,n){let r=dn(e),i=Vr(e,r),s=un(e);if(s===".")return`${i}.${n}${r}`;return Oe(s,`${i}.${n}${r}`)}static collectFiles(e,n){let r=[],i=n||e;if(!ht(e))return r;let s=_r(e,{withFileTypes:!0});for(let a of s){let c=Oe(e,a.name);if(a.isDirectory())r.push(...ne.collectFiles(c,i));else if(a.isFile())r.push(c)}return r}static hashDirectory(e){let{sourceDir:n,outputDir:r,excludePatterns:i=[],hashAlgorithm:s="md5",copyUnhashed:a=!0}=e,c=ne.collectFiles(n),u=[],d={};for(let p of c){let g=p.replace(n,"").replace(/^[/\\]/,""),y=ne.shouldHashFile(g,i),h=Wr(p),f=y?ne.computeFileHash(p,s).slice(0,8):"",S=y?ne.generateHashedFilename(g,f):g,C={originalPath:g,hashedPath:S,hash:f,size:h.size,contentType:ne.getContentType(p)};if(u.push(C),d[g]=S,r){let P=Oe(r,S),E=un(P);if(!ht(E)){let{mkdirSync:v}=Br("node:fs");v(E,{recursive:!0})}if(y||a)Gr(p,P)}}let m={version:"1.0",timestamp:new Date().toISOString(),assets:u,hashMap:d};if(r){let p=Oe(r,"asset-manifest.json");Qe(p,JSON.stringify(m,null,2))}return m}static getInvalidationPaths(e,n){let r=[];if(!e)return["/*"];let i=e.hashMap,s=n.hashMap;for(let[a,c]of Object.entries(s)){let u=i[a];if(!u||u!==c){if(r.push(`/${a}`),u&&u!==c)r.push(`/${u}`)}}for(let[a,c]of Object.entries(i))if(!s[a])r.push(`/${a}`),r.push(`/${c}`);if(r.length>100)return["/*"];return[...new Set(r)]}static updateHtmlReferences(e){let{htmlDir:n,manifest:r,basePath:i=""}=e,s=ne.collectFiles(n).filter((a)=>a.endsWith(".html")||a.endsWith(".htm"));for(let a of s){let c=ze(a,"utf-8");for(let[u,d]of Object.entries(r.hashMap)){if(u===d)continue;let m=[new RegExp(`(src|href)=["']${i}/?${ne.escapeRegExp(u)}["']`,"g"),new RegExp(`url\\(["']?${i}/?${ne.escapeRegExp(u)}["']?\\)`,"g")];for(let p of m)c=c.replace(p,(g)=>g.replace(u,d))}Qe(a,c)}}static updateCssReferences(e){let{cssDir:n,manifest:r,basePath:i=""}=e,s=ne.collectFiles(n).filter((a)=>a.endsWith(".css"));for(let a of s){let c=ze(a,"utf-8");for(let[u,d]of Object.entries(r.hashMap)){if(u===d)continue;let m=new RegExp(`url\\(["']?${i}/?${ne.escapeRegExp(u)}["']?\\)`,"g");c=c.replace(m,`url(${i}/${d})`)}Qe(a,c)}}static escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(e){let{sourceDir:n,keyPrefix:r="",excludePatterns:i=[],cacheControl:s={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=e;return ne.hashDirectory({sourceDir:n,excludePatterns:i}).assets.map((c)=>{let u=c.hash!=="",d=c.contentType==="text/html",m=s.unhashed||"public, max-age=3600";if(d)m=s.html||"public, max-age=0, must-revalidate";else if(u)m=s.hashed||"public, max-age=31536000, immutable";return{localPath:Oe(n,c.originalPath),s3Key:r?`${r}/${c.hashedPath}`:c.hashedPath,contentType:c.contentType,cacheControl:m,hash:c.hash}})}static compareManifests(e,n){let r={added:[],removed:[],changed:[],unchanged:[]},i=new Set(Object.keys(e.hashMap)),s=new Set(Object.keys(n.hashMap));for(let a of s)if(!i.has(a))r.added.push(a);for(let a of i)if(!s.has(a))r.removed.push(a);for(let a of s)if(i.has(a))if(e.hashMap[a]!==n.hashMap[a])r.changed.push(a);else r.unchanged.push(a);return r}static loadManifest(e){if(!ht(e))return null;try{let n=ze(e,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(e,n){Qe(n,JSON.stringify(e,null,2))}}class $i{static createSecret(e){let{slug:n,environment:r,secretName:i,description:s,secretString:a,kmsKeyId:c,tags:u}=e,d=i||l({slug:n,environment:r,resourceType:"secret"}),m=o(d),p={Type:"AWS::SecretsManager::Secret",Properties:{Name:d,Description:s,SecretString:a,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:r},...u?Object.entries(u).map(([g,y])=>({Key:g,Value:y})):[]]}};if(c)p.Properties.KmsKeyId=c;return{secret:p,logicalId:m}}static createGeneratedSecret(e){let{slug:n,environment:r,secretName:i,description:s,excludeCharacters:a,excludeLowercase:c,excludeNumbers:u,excludePunctuation:d,excludeUppercase:m,passwordLength:p,requireEachIncludedType:g,kmsKeyId:y,tags:h}=e,f=i||l({slug:n,environment:r,resourceType:"secret"}),S=o(f),C={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:s,GenerateSecretString:{ExcludeCharacters:a,ExcludeLowercase:c,ExcludeNumbers:u,ExcludePunctuation:d,ExcludeUppercase:m,PasswordLength:p||32,RequireEachIncludedType:g!==!1},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:r},...h?Object.entries(h).map(([P,E])=>({Key:P,Value:E})):[]]}};if(y)C.Properties.KmsKeyId=y;return{secret:C,logicalId:S}}static createDatabaseSecret(e){let{slug:n,environment:r,secretName:i,username:s,dbname:a,engine:c,host:u,port:d,kmsKeyId:m}=e,p=i||l({slug:n,environment:r,resourceType:"db-secret"}),g=o(p),y={username:s};if(a)y.dbname=a;if(c)y.engine=c;if(u)y.host=u;if(d)y.port=d;let h={Type:"AWS::SecretsManager::Secret",Properties:{Name:p,Description:`Database credentials for ${s}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(y),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:r},{Key:"Type",Value:"database"}]}};if(m)h.Properties.KmsKeyId=m;return{secret:h,logicalId:g}}static attachToDatabase(e){let{slug:n,environment:r,secretId:i,targetId:s,targetType:a}=e,c=l({slug:n,environment:r,resourceType:"secret-attachment"}),u=o(c);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:i,TargetId:s,TargetType:a}},logicalId:u}}static enableRotation(e){let{slug:n,environment:r,secretId:i,rotationLambdaArn:s,automaticallyAfterDays:a,rotationType:c,kmsKeyArn:u,vpcSecurityGroupIds:d,vpcSubnetIds:m}=e,p=l({slug:n,environment:r,resourceType:"secret-rotation"}),g=o(p),y={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:i,RotationRules:{AutomaticallyAfterDays:a||30}}};if(s)y.Properties.RotationLambdaARN=s;else if(c)y.Properties.HostedRotationLambda={RotationType:c,KmsKeyArn:u,VpcSecurityGroupIds:d,VpcSubnetIds:m};return{rotation:y,logicalId:g}}static SecretTypes={apiKey:(e,n,r)=>$i.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-${r}-api-key`,description:`API key for ${r}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(e,n,r)=>$i.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-${r}-oauth-secret`,description:`OAuth client secret for ${r}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(e,n)=>$i.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(e,n)=>$i.createGeneratedSecret({slug:e,environment:n,secretName:`${e}-${n}-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 X{static createParameter(e){let{slug:n,environment:r,parameterName:i,value:s,type:a="String",description:c,tier:u="Standard",tags:d}=e,m=i||l({slug:n,environment:r,resourceType:"parameter"}),p=o(m);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${r}/${m}`,Type:a,Value:s,Description:c,Tier:u,Tags:{Name:m,Environment:r,...d}}},logicalId:p}}static createString(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i,type:"String",description:s})}static createSecureString(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i,type:"SecureString",description:s})}static createStringList(e,n,r,i,s){return X.createParameter({slug:e,environment:n,parameterName:r,value:i.join(","),type:"StringList",description:s})}static Parameters={databaseUrl:(e,n,r)=>X.createSecureString(e,n,"database-url",r,"Database connection URL"),apiEndpoint:(e,n,r)=>X.createString(e,n,"api-endpoint",r,"API endpoint URL"),appVersion:(e,n,r)=>X.createString(e,n,"app-version",r,"Application version"),featureFlags:(e,n,r)=>X.createStringList(e,n,"feature-flags",r,"Enabled feature flags"),apiKey:(e,n,r,i)=>X.createSecureString(e,n,`${r}-api-key`,i,`API key for ${r}`),oauthCredentials:(e,n,r,i)=>{let s=X.createString(e,n,"oauth-client-id",r,"OAuth client ID"),a=X.createSecureString(e,n,"oauth-client-secret",i,"OAuth client secret");return{clientId:s,clientSecret:a}},smtpCredentials:(e,n,r,i,s,a)=>{let c=X.createString(e,n,"smtp-username",r,"SMTP username"),u=X.createSecureString(e,n,"smtp-password",i,"SMTP password"),d=X.createString(e,n,"smtp-host",s,"SMTP host"),m=X.createString(e,n,"smtp-port",a.toString(),"SMTP port");return{username:c,password:u,host:d,port:m}},redisUrl:(e,n,r)=>X.createSecureString(e,n,"redis-url",r,"Redis connection URL"),s3Bucket:(e,n,r)=>X.createString(e,n,"s3-bucket",r,"S3 bucket name"),cloudFrontDistribution:(e,n,r)=>X.createString(e,n,"cloudfront-distribution-id",r,"CloudFront distribution ID")}}class qt{static createDomain(e){let{slug:n,environment:r,domainName:i,engineVersion:s="OpenSearch_2.11",instanceType:a="t3.small.search",instanceCount:c=1,volumeSize:u=10,volumeType:d="gp3",dedicatedMaster:m=!1,dedicatedMasterType:p,dedicatedMasterCount:g=3,multiAz:y=!1,availabilityZoneCount:h=2,vpc:f,encryption:S,enforceHttps:C=!0,tlsSecurityPolicy:P="Policy-Min-TLS-1-2-2019-07",advancedSecurity:E,autoSnapshotHour:v=0,autoTune:I=!0,tags:D={}}=e,N=i||l({slug:n,environment:r,resourceType:"search"}),B=o(N);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:N,EngineVersion:s,ClusterConfig:{InstanceType:a,InstanceCount:c,DedicatedMasterEnabled:m,...m&&{DedicatedMasterType:p||a,DedicatedMasterCount:g},ZoneAwarenessEnabled:y,...y&&{ZoneAwarenessConfig:{AvailabilityZoneCount:h}}},EBSOptions:{EBSEnabled:!0,VolumeType:d,VolumeSize:u},DomainEndpointOptions:{EnforceHTTPS:C,TLSSecurityPolicy:P},SnapshotOptions:{AutomatedSnapshotStartHour:v},...f&&{VPCOptions:{SubnetIds:f.subnetIds,SecurityGroupIds:f.securityGroupIds}},...S&&{EncryptionAtRestOptions:{Enabled:S.atRest??!0,...S.kmsKeyId&&{KmsKeyId:S.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:S.nodeToNode??!0}},...E&&{AdvancedSecurityOptions:{Enabled:E.enabled,InternalUserDatabaseEnabled:E.internalUserDatabase??!0,...E.masterUserName&&E.masterUserPassword&&{MasterUserOptions:{MasterUserName:E.masterUserName,MasterUserPassword:E.masterUserPassword}},...E.masterUserArn&&{MasterUserOptions:{MasterUserARN:E.masterUserArn}}}},...I&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:N},{Key:"Environment",Value:r},...Object.entries(D).map(([O,G])=>({Key:O,Value:G}))]}},logicalId:B}}static createAccessPolicy(e,n){let{ipAddresses:r,iamPrincipalArns:i,allowAll:s,vpcEndpoint:a}=n;if(s)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};let c=[];if(i&&i.length>0)c.push({Effect:"Allow",Principal:{AWS:i},Action:"es:*",Resource:e});if(r&&r.length>0)c.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e,Condition:{IpAddress:{"aws:SourceIp":r}}});if(a)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};return{Version:"2012-10-17",Statement:c}}static DomainPresets={development:(e,n)=>qt.createDomain({slug:e,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(e,n,r)=>qt.createDomain({slug:e,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:r,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(e,n)=>qt.createDomain({slug:e,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(e,n,r)=>qt.createDomain({slug:e,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:r,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 At{static createDomainRedirectBucket(e){let{slug:n,environment:r,sourceDomain:i,targetDomain:s,protocol:a="https"}=e,c=l({slug:n,environment:r,resourceType:"s3",suffix:"redirect"}),u=o(c),d=o(`${c}-policy`),m={Type:"AWS::S3::Bucket",Properties:{BucketName:i,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:s,Protocol:a}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:r},{Key:"Purpose",Value:"Domain Redirect"}]}},p={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:R.Ref(u),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[R.Join("",[R.GetAtt(u,"Arn"),"/*"])]}]}}};return{bucket:m,bucketPolicy:p,logicalId:u,policyLogicalId:d}}static createPathRedirectFunction(e){let{slug:n,environment:r,rules:i}=e,s=l({slug:n,environment:r,resourceType:"cf-redirect"}),a=o(s),c=At.generateRedirectFunctionCode(i);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:s,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${r})`,Runtime:"cloudfront-js-2.0"},FunctionCode:c}},logicalId:a,functionCode:c}}static generateRedirectFunctionCode(e){return`function handler(event) {
2282
2282
  const request = event.request;
2283
2283
  const uri = request.uri;
2284
2284
  const querystring = request.querystring;
@@ -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 t={ref:(e)=>({Ref:e}),getAtt:(e,n)=>({"Fn::GetAtt":[e,n]}),join:(e,n)=>({"Fn::Join":[e,n]}),sub:(e,n)=>n?{"Fn::Sub":[e,n]}:{"Fn::Sub":e},select:(e,n)=>({"Fn::Select":[e,n]}),split:(e,n)=>({"Fn::Split":[e,n]}),getAZs:(e="")=>({"Fn::GetAZs":e}),importValue:(e)=>({"Fn::ImportValue":e}),findInMap:(e,n,r)=>({"Fn::FindInMap":[e,n,r]}),base64:(e)=>({"Fn::Base64":e}),cidr:(e,n,r)=>({"Fn::Cidr":[e,n,r]}),equals:(e,n)=>({"Fn::Equals":[e,n]}),if:(e,n,r)=>({"Fn::If":[e,n,r]}),not:(e)=>({"Fn::Not":[e]}),and:(...e)=>({"Fn::And":e}),or:(...e)=>({"Fn::Or":e})},yn={s3Bucket:(e)=>t.sub(`arn:aws:s3:::${e}`),s3Object:(e,n="*")=>t.sub(`arn:aws:s3:::${e}/${n}`),lambda:(e,n,r)=>t.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${e}`,n&&r?{"AWS::Region":n,"AWS::AccountId":r}:void 0),dynamodb:(e)=>t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${e}`),sqs:(e)=>t.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${e}`),sns:(e)=>t.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${e}`),kinesis:(e)=>t.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${e}`),iam:(e,n)=>t.sub(`arn:aws:iam::\${AWS::AccountId}:${e}/${n}`),secretsManager:(e)=>t.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${e}`),cloudwatch:(e)=>t.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${e}`)},vm={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 mn(e,n){if(n.type==="http")Hr(e,n);else if(n.type==="rest")jr(e,n);else if(n.type==="websocket")Kr(e,n)}function Hr(e,n){let r={Name:t.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)r.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(e.addResource("HttpApi","AWS::ApiGatewayV2::Api",r),e.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:t.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:t.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),e.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:t.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)qr(e,"HttpApi",n.authorizer);if(n.customDomain)ft(e,"HttpApi",n.customDomain,"HTTP");e.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:t.ref("HttpApi"),Export:{Name:t.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:t.getAtt("HttpApi","ApiEndpoint"),Export:{Name:t.sub("${AWS::StackName}-http-api-endpoint")}}})}function jr(e,n){e.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:t.sub("${AWS::StackName}-rest-api"),Description:t.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),e.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:t.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),e.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"]}),e.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:t.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let r={RestApiId:t.ref("RestApi"),DeploymentId:t.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)r.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,r.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(e.addResource("RestApiStage","AWS::ApiGateway::Stage",r,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)ft(e,"RestApi",n.customDomain,"REST");e.addOutputs({RestApiId:{Description:"REST API ID",Value:t.ref("RestApi"),Export:{Name:t.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:t.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:t.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Kr(e,n){if(e.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:t.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)Je(e,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)Je(e,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)Je(e,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((r)=>{Je(e,r.routeKey,r.functionName)})}if(e.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:t.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)ft(e,"WebSocketApi",n.customDomain,"WEBSOCKET");e.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:t.ref("WebSocketApi"),Export:{Name:t.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:t.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:t.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function Je(e,n,r){let i=e.toLogicalId(`websocket-route-${n}`),s=e.toLogicalId(`websocket-integration-${n}`),a=e.toLogicalId(`${r}-function`);e.addResource(s,"AWS::ApiGatewayV2::Integration",{ApiId:t.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:t.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${a}.Arn}/invocations`)},{dependsOn:["WebSocketApi",a]}),e.addResource(i,"AWS::ApiGatewayV2::Route",{ApiId:t.ref("WebSocketApi"),RouteKey:n,Target:t.join("/",["integrations",t.ref(s)])},{dependsOn:["WebSocketApi",s]}),e.addResource(`${i}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(a),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:t.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[a,"WebSocketApi"]})}function ft(e,n,r,i){let s={DomainName:r.domain};if(i==="REST")s.CertificateArn=r.certificateArn,s.EndpointConfiguration={Types:["REGIONAL"]},e.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",s),e.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:t.ref("ApiCustomDomain"),RestApiId:t.ref(n),Stage:t.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else s.DomainNameConfigurations=[{CertificateArn:r.certificateArn,EndpointType:"REGIONAL"}],e.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",s),e.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:t.ref(n),DomainName:t.ref("ApiCustomDomain"),Stage:i==="HTTP"?t.ref("HttpApiStage"):t.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(r.dnsProvider!=="external")e.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:t.sub(`${zr(r.domain)}.`),Name:r.domain,Type:"A",AliasTarget:{HostedZoneId:t.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:t.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});e.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:r.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:t.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:t.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function qr(e,n,r){if(!r)return;if(r.type==="jwt")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:t.ref(n),AuthorizerType:"JWT",IdentitySource:[r.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:r.issuer,Audience:r.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(r.type==="lambda")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:t.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:r.authorizerUri,IdentitySource:[r.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function zr(e){let n=e.split(".");if(n.length>=2)return n.slice(-2).join(".");return e}function pn(e,n){if(n.redis)Qr(e,n.redis);if(n.memcached)Jr(e,n.memcached);if(n.elasticache)Yr(e,n.elasticache)}function Qr(e,n){if(!n)return;if(e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)e.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)e.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:t.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),SecurityGroupIds:[t.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?t.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:t.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:t.sub("${AWS::StackName}-redis-port")}}});else e.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?t.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:t.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:t.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-redis-port")}}})}function Jr(e,n){if(!n)return;if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),e.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:t.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:t.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-memcached-port")}}})}function Yr(e,n){if(!n)return;let r=n.engine==="redis";if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:r?6379:11211,ToPort:r?6379:11211,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function An(e,n){if(!n.enabled)return;e.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:t.sub("${AWS::StackName} CloudFront OAI")}});let r=[],i=[];if(!n.origins||n.origins.length===0)r.push({Id:"S3Origin",DomainName:t.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:t.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((c,u)=>{let d={Id:c.id,DomainName:c.domainName};if(c.originPath)d.OriginPath=c.originPath;if(c.domainName.includes("s3"))d.S3OriginConfig={OriginAccessIdentity:t.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else d.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(r.push(d),u>0||c.pathPattern)i.push({PathPattern:c.pathPattern||`/${c.id}/*`,TargetOriginId:c.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let s={TargetOriginId:r[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)s.LambdaFunctionAssociations=n.edgeFunctions.map((c)=>({EventType:c.eventType,LambdaFunctionARN:c.functionArn}));let a={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:r,DefaultCacheBehavior:s,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(i.length>0)a.CacheBehaviors=i;if(n.customDomain)a.Aliases=[n.customDomain.domain],a.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else a.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)a.CustomErrorResponses=Object.entries(n.errorPages).map(([c,u])=>({ErrorCode:Number.parseInt(c),ResponseCode:200,ResponsePagePath:u,ErrorCachingMinTTL:300}));if(a.DefaultRootObject="index.html",a.Comment=t.sub("${AWS::StackName} CloudFront Distribution"),e.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:a},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)e.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:t.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:t.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:t.join("",[t.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)e.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:t.sub(`${Zr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:t.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(e.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:t.ref("CloudFrontDistribution"),Export:{Name:t.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:t.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:t.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)e.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:t.sub(`https://${n.customDomain.domain}`)}})}function Zr(e){let n=e.split(".");if(n.length>=2)return n.slice(-2).join(".");return e}function Pn(e,n){if(n.server)Xr(e,n.server);if(n.fargate)Rn(e,"app",n.fargate);if(n.services)n.services.forEach((r)=>{if(r.type==="fargate")Rn(e,r.name,{taskDefinition:r.taskDefinition,service:r.service})})}function Xr(e,n){if(!n)return;e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:t.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:t.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),e.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:t.sub("${AWS::StackName}-ec2-role")}]}),e.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[t.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let r=n.userData||`#!/bin/bash
2433
+ };`}var t={ref:(e)=>({Ref:e}),getAtt:(e,n)=>({"Fn::GetAtt":[e,n]}),join:(e,n)=>({"Fn::Join":[e,n]}),sub:(e,n)=>n?{"Fn::Sub":[e,n]}:{"Fn::Sub":e},select:(e,n)=>({"Fn::Select":[e,n]}),split:(e,n)=>({"Fn::Split":[e,n]}),getAZs:(e="")=>({"Fn::GetAZs":e}),importValue:(e)=>({"Fn::ImportValue":e}),findInMap:(e,n,r)=>({"Fn::FindInMap":[e,n,r]}),base64:(e)=>({"Fn::Base64":e}),cidr:(e,n,r)=>({"Fn::Cidr":[e,n,r]}),equals:(e,n)=>({"Fn::Equals":[e,n]}),if:(e,n,r)=>({"Fn::If":[e,n,r]}),not:(e)=>({"Fn::Not":[e]}),and:(...e)=>({"Fn::And":e}),or:(...e)=>({"Fn::Or":e})},vn={s3Bucket:(e)=>t.sub(`arn:aws:s3:::${e}`),s3Object:(e,n="*")=>t.sub(`arn:aws:s3:::${e}/${n}`),lambda:(e,n,r)=>t.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${e}`,n&&r?{"AWS::Region":n,"AWS::AccountId":r}:void 0),dynamodb:(e)=>t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${e}`),sqs:(e)=>t.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${e}`),sns:(e)=>t.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${e}`),kinesis:(e)=>t.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${e}`),iam:(e,n)=>t.sub(`arn:aws:iam::\${AWS::AccountId}:${e}/${n}`),secretsManager:(e)=>t.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${e}`),cloudwatch:(e)=>t.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${e}`)},wm={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 mn(e,n){if(n.type==="http")Hr(e,n);else if(n.type==="rest")jr(e,n);else if(n.type==="websocket")Kr(e,n)}function Hr(e,n){let r={Name:t.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)r.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(e.addResource("HttpApi","AWS::ApiGatewayV2::Api",r),e.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:t.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:t.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),e.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:t.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)qr(e,"HttpApi",n.authorizer);if(n.customDomain)ft(e,"HttpApi",n.customDomain,"HTTP");e.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:t.ref("HttpApi"),Export:{Name:t.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:t.getAtt("HttpApi","ApiEndpoint"),Export:{Name:t.sub("${AWS::StackName}-http-api-endpoint")}}})}function jr(e,n){e.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:t.sub("${AWS::StackName}-rest-api"),Description:t.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),e.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:t.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),e.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"]}),e.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:t.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let r={RestApiId:t.ref("RestApi"),DeploymentId:t.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)r.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,r.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(e.addResource("RestApiStage","AWS::ApiGateway::Stage",r,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)ft(e,"RestApi",n.customDomain,"REST");e.addOutputs({RestApiId:{Description:"REST API ID",Value:t.ref("RestApi"),Export:{Name:t.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:t.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:t.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Kr(e,n){if(e.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:t.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)Je(e,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)Je(e,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)Je(e,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((r)=>{Je(e,r.routeKey,r.functionName)})}if(e.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:t.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)ft(e,"WebSocketApi",n.customDomain,"WEBSOCKET");e.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:t.ref("WebSocketApi"),Export:{Name:t.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:t.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:t.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function Je(e,n,r){let i=e.toLogicalId(`websocket-route-${n}`),s=e.toLogicalId(`websocket-integration-${n}`),a=e.toLogicalId(`${r}-function`);e.addResource(s,"AWS::ApiGatewayV2::Integration",{ApiId:t.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:t.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${a}.Arn}/invocations`)},{dependsOn:["WebSocketApi",a]}),e.addResource(i,"AWS::ApiGatewayV2::Route",{ApiId:t.ref("WebSocketApi"),RouteKey:n,Target:t.join("/",["integrations",t.ref(s)])},{dependsOn:["WebSocketApi",s]}),e.addResource(`${i}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(a),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:t.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[a,"WebSocketApi"]})}function ft(e,n,r,i){let s={DomainName:r.domain};if(i==="REST")s.CertificateArn=r.certificateArn,s.EndpointConfiguration={Types:["REGIONAL"]},e.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",s),e.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:t.ref("ApiCustomDomain"),RestApiId:t.ref(n),Stage:t.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else s.DomainNameConfigurations=[{CertificateArn:r.certificateArn,EndpointType:"REGIONAL"}],e.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",s),e.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:t.ref(n),DomainName:t.ref("ApiCustomDomain"),Stage:i==="HTTP"?t.ref("HttpApiStage"):t.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(r.dnsProvider!=="external")e.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:t.sub(`${zr(r.domain)}.`),Name:r.domain,Type:"A",AliasTarget:{HostedZoneId:t.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:t.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});e.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:r.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:t.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:t.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function qr(e,n,r){if(!r)return;if(r.type==="jwt")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:t.ref(n),AuthorizerType:"JWT",IdentitySource:[r.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:r.issuer,Audience:r.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(r.type==="lambda")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:t.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:r.authorizerUri,IdentitySource:[r.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function zr(e){let n=e.split(".");if(n.length>=2)return n.slice(-2).join(".");return e}function pn(e,n){if(n.redis)Qr(e,n.redis);if(n.memcached)Jr(e,n.memcached);if(n.elasticache)Yr(e,n.elasticache)}function Qr(e,n){if(!n)return;if(e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)e.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)e.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:t.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),SecurityGroupIds:[t.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?t.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:t.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:t.sub("${AWS::StackName}-redis-port")}}});else e.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?t.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:t.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:t.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-redis-port")}}})}function Jr(e,n){if(!n)return;if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),e.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:t.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:t.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-memcached-port")}}})}function Yr(e,n){if(!n)return;let r=n.engine==="redis";if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:r?6379:11211,ToPort:r?6379:11211,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:t.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[t.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function gn(e,n){if(!n.enabled)return;e.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:t.sub("${AWS::StackName} CloudFront OAI")}});let r=[],i=[];if(!n.origins||n.origins.length===0)r.push({Id:"S3Origin",DomainName:t.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:t.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((c,u)=>{let d={Id:c.id,DomainName:c.domainName};if(c.originPath)d.OriginPath=c.originPath;if(c.domainName.includes("s3"))d.S3OriginConfig={OriginAccessIdentity:t.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else d.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(r.push(d),u>0||c.pathPattern)i.push({PathPattern:c.pathPattern||`/${c.id}/*`,TargetOriginId:c.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let s={TargetOriginId:r[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)s.LambdaFunctionAssociations=n.edgeFunctions.map((c)=>({EventType:c.eventType,LambdaFunctionARN:c.functionArn}));let a={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:r,DefaultCacheBehavior:s,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(i.length>0)a.CacheBehaviors=i;if(n.customDomain)a.Aliases=[n.customDomain.domain],a.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else a.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)a.CustomErrorResponses=Object.entries(n.errorPages).map(([c,u])=>({ErrorCode:Number.parseInt(c),ResponseCode:200,ResponsePagePath:u,ErrorCachingMinTTL:300}));if(a.DefaultRootObject="index.html",a.Comment=t.sub("${AWS::StackName} CloudFront Distribution"),e.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:a},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)e.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:t.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:t.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:t.join("",[t.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)e.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:t.sub(`${Zr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:t.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(e.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:t.ref("CloudFrontDistribution"),Export:{Name:t.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:t.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:t.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)e.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:t.sub(`https://${n.customDomain.domain}`)}})}function Zr(e){let n=e.split(".");if(n.length>=2)return n.slice(-2).join(".");return e}function fn(e,n){if(n.server)Xr(e,n.server);if(n.fargate)hn(e,"app",n.fargate);if(n.services)n.services.forEach((r)=>{if(r.type==="fargate")hn(e,r.name,{taskDefinition:r.taskDefinition,service:r.service})})}function Xr(e,n){if(!n)return;e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:t.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:t.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),e.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:t.sub("${AWS::StackName}-ec2-role")}]}),e.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[t.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let r=n.userData||`#!/bin/bash
2434
2434
  set -e
2435
2435
  # Update system
2436
2436
  yum update -y || apt-get update -y
@@ -2445,20 +2445,20 @@ 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(e.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:t.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:n.ami||t.findInMap("RegionMap",t.ref("AWS::Region"),"AMI"),InstanceType:n.instanceType,IamInstanceProfile:{Arn:t.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[t.ref("AppSecurityGroup")],UserData:t.base64(t.sub(r)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),n.loadBalancer){ei(e,n.loadBalancer);let i={LaunchTemplate:{LaunchTemplateId:t.ref("LaunchTemplate"),Version:t.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:n.autoScaling?.min.toString()||"1",MaxSize:n.autoScaling?.max.toString()||"3",DesiredCapacity:n.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],TargetGroupARNs:[t.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(e.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",i,{dependsOn:["LaunchTemplate","TargetGroup"]}),n.autoScaling)e.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:t.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),e.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:t.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),e.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(n.autoScaling.targetCPU||70).toString(),AlarmActions:[t.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:t.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),e.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:((n.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[t.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:t.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function ei(e,n){if(!n)return;e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:t.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:t.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:t.sub("${AWS::StackName}-alb"),Type:n.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[t.ref("PublicSubnet1"),t.ref("PublicSubnet2")],SecurityGroups:[t.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),e.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:t.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:t.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:n.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:n.healthCheck?.interval||30,HealthCheckTimeoutSeconds:n.healthCheck?.timeout||5,HealthyThresholdCount:n.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:t.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),e.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:t.getAtt("LoadBalancer","DNSName"),Export:{Name:t.sub("${AWS::StackName}-alb-dns")}}})}function Rn(e,n,r){let i=e.toLogicalId(n),s=r.taskDefinition.containerDefinitions?.[0],a=s?.name||s?.Name||n,c=s?.portMappings?.[0]?.containerPort||s?.PortMappings?.[0]?.ContainerPort||3000,u=(r.taskDefinition.containerDefinitions||[]).flatMap((y)=>(y.secrets||y.Secrets||[]).map((h)=>h.valueFrom||h.ValueFrom)).filter(Boolean);if(!e.hasResource("ECSCluster"))e.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:t.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cluster")}]});if(e.addResource(`${i}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"],...u.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:u},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),e.addResource(`${i}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:t.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!e.hasResource("ALBSecurityGroup"))e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...r.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:c,ToPort:c,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!e.hasResource("AppSecurityGroup"))e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:c,ToPort:c,SourceSecurityGroupId:t.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let d=(r.taskDefinition.containerDefinitions||[{name:n,image:t.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${n}:latest`),portMappings:[{containerPort:3000}]}]).map((y)=>({Name:y.Name||y.name,Image:y.Image||y.image,Essential:y.Essential??y.essential??!0,PortMappings:(y.PortMappings||y.portMappings||[]).map((h)=>({ContainerPort:h.ContainerPort??h.containerPort,Protocol:h.Protocol||h.protocol||"tcp"})),Environment:Array.isArray(y.Environment||y.environment)?(y.Environment||y.environment).map((h)=>({Name:h.Name||h.name,Value:h.Value??h.value})):Object.entries(y.Environment||y.environment||{}).map(([h,f])=>({Name:h,Value:f})),Secrets:(y.Secrets||y.secrets||[]).map((h)=>({Name:h.Name||h.name,ValueFrom:h.ValueFrom||h.valueFrom})),HealthCheck:y.HealthCheck||y.healthCheck,Command:y.Command||y.command,EntryPoint:y.EntryPoint||y.entryPoint,LogConfiguration:y.LogConfiguration||y.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":t.ref(`${i}LogGroup`),"awslogs-region":t.ref("AWS::Region"),"awslogs-stream-prefix":n}}}));e.addResource(`${i}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:t.sub(`\${AWS::StackName}-${n}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:r.taskDefinition.cpu,Memory:r.taskDefinition.memory,ExecutionRoleArn:t.getAtt(`${i}TaskExecutionRole`,"Arn"),TaskRoleArn:t.getAtt(`${i}TaskRole`,"Arn"),ContainerDefinitions:d},{dependsOn:[`${i}TaskExecutionRole`,`${i}TaskRole`,`${i}LogGroup`]}),e.addResource(`${i}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/ecs/\${AWS::StackName}/${n}`),RetentionInDays:14});let m=r.service.healthCheck||{};e.addResource(`${i}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:t.ref("VPC"),Port:c,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:m.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:m.interval||30,HealthCheckTimeoutSeconds:m.timeout||5,HealthyThresholdCount:m.healthyThreshold||2,UnhealthyThresholdCount:m.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),e.addResource(`${i}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[t.ref("PublicSubnet1"),t.ref("PublicSubnet2")],SecurityGroups:[t.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(r.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let p=r.loadBalancer?.customDomain?.certificateArn,g=r.loadBalancer?.originVerifyHeader;if(e.addResource(`${i}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref(`${i}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:p?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:g?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[`${i}LoadBalancer`,`${i}TargetGroup`]}),p)e.addResource(`${i}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref(`${i}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:p}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:g?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[`${i}LoadBalancer`,`${i}TargetGroup`]});if(g){let y=p?`${i}HttpsListener`:`${i}HttpListener`;e.addResource(`${i}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:t.ref(y),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:g.name,Values:[g.value]}}],Actions:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[y,`${i}TargetGroup`]})}if(e.addResource(`${i}Service`,"AWS::ECS::Service",{ServiceName:t.sub(`\${AWS::StackName}-${n}`),Cluster:t.ref("ECSCluster"),TaskDefinition:t.ref(`${i}TaskDefinition`),DesiredCount:r.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:a,ContainerPort:c,TargetGroupArn:t.ref(`${i}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],SecurityGroups:[t.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${i}TaskDefinition`,g?`${i}OriginVerifyRule`:p?`${i}HttpsListener`:`${i}HttpListener`]}),r.service.autoScaling){let y=r.service.autoScaling;e.addResource(`${i}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:y.min,MaxCapacity:y.max,ResourceId:t.join("/",["service",t.ref("ECSCluster"),t.getAtt(`${i}Service`,"Name")]),RoleARN:t.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${i}Service`}),e.addResource(`${i}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:t.ref(`${i}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:y.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${i}ScalableTarget`})}e.addOutputs({[`${i}ClusterName`]:{Description:"ECS cluster name",Value:t.ref("ECSCluster")},[`${i}ServiceName`]:{Description:"ECS service name",Value:t.getAtt(`${i}Service`,"Name")},[`${i}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:t.getAtt(`${i}LoadBalancer`,"DNSName")},[`${i}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:t.getAtt(`${i}LoadBalancer`,"CanonicalHostedZoneID")},[`${i}TargetGroupArn`]:{Description:"ECS target group ARN",Value:t.ref(`${i}TargetGroup`)}})}function In(e,n){if(n.postgres)En(e,"postgres",n.postgres);if(n.mysql)En(e,"mysql",n.mysql);if(n.dynamodb?.tables)n.dynamodb.tables.forEach((r)=>{ti(e,r)})}function En(e,n,r){if(!r)return;let i=n==="postgres"?"postgres":"mysql",s=e.toLogicalId(`${i}-db`);e.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n==="postgres"?5432:3306,ToPort:n==="postgres"?5432:3306,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let a=n==="postgres"?`postgres${r.version.split(".")[0]}`:`mysql${r.version.split(".")[0]}.${r.version.split(".")[1]||"0"}`;if(r.parameters&&Object.keys(r.parameters).length>0)e.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${i}`,Family:a,Parameters:r.parameters,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-params")}]});e.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let c={Engine:i,EngineVersion:r.version,DBInstanceClass:r.instanceClass,AllocatedStorage:r.allocatedStorage.toString(),MaxAllocatedStorage:r.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:r.multiAZ!==!1,DBSubnetGroupName:t.ref("DBSubnetGroup"),VPCSecurityGroups:[t.ref("DBSecurityGroup")],MasterUsername:t.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:t.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:r.backupRetentionDays||7,PreferredBackupWindow:r.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:r.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:r.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:r.performanceInsightsRetention||7,DeletionProtection:r.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:n==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${i}-db`)}]};if(r.parameters&&Object.keys(r.parameters).length>0)c.DBParameterGroupName=t.ref("DBParameterGroup");e.addResource(s,"AWS::RDS::DBInstance",c,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:t.ref("DBSecret"),TargetId:t.ref(s),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[s,"DBSecret"]}),e.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:t.getAtt(s,"Endpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:t.getAtt(s,"Endpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:t.ref("DBSecret"),Export:{Name:t.sub("${AWS::StackName}-db-secret-arn")}}})}function ti(e,n){let r=e.toLogicalId(`${n.name}-table`),i={TableName:t.sub(`\${AWS::StackName}-${n.name}`),BillingMode:n.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:n.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]};if(n.sortKey)i.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"}),i.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.billingMode==="PROVISIONED")i.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};if(n.streamEnabled)i.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(n.pointInTimeRecovery)i.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(n.ttl?.enabled)i.TimeToLiveSpecification={Enabled:!0,AttributeName:n.ttl.attributeName};if(n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0)i.GlobalSecondaryIndexes=n.globalSecondaryIndexes.map((s)=>{let a=new Set(i.AttributeDefinitions.map((u)=>u.AttributeName));if(!a.has(s.partitionKey))i.AttributeDefinitions.push({AttributeName:s.partitionKey,AttributeType:"S"});if(s.sortKey&&!a.has(s.sortKey))i.AttributeDefinitions.push({AttributeName:s.sortKey,AttributeType:"S"});let c={IndexName:s.name,KeySchema:[{AttributeName:s.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:s.projectionType||"ALL"}};if(s.sortKey)c.KeySchema.push({AttributeName:s.sortKey,KeyType:"RANGE"});if(s.projectionType==="INCLUDE"&&s.nonKeyAttributes)c.Projection.NonKeyAttributes=s.nonKeyAttributes;if(n.billingMode==="PROVISIONED")c.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};return c});if(e.addResource(r,"AWS::DynamoDB::Table",i,{deletionPolicy:"Retain"}),e.addOutputs({[`${r}Name`]:{Description:`${n.name} table name`,Value:t.ref(r),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-table`)}},[`${r}Arn`]:{Description:`${n.name} table ARN`,Value:t.getAtt(r,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-table-arn`)}}}),n.streamEnabled)e.addOutputs({[`${r}StreamArn`]:{Description:`${n.name} stream ARN`,Value:t.getAtt(r,"StreamArn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-stream-arn`)}}})}function wn(e,n){for(let[r,i]of Object.entries(n))i.forEach((s)=>{ni(e,s,r)})}function ni(e,n,r){let i=e.toLogicalId(`${r}-${n.name}-function`),s=`${i}Role`;e.addResource(s,"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:[...ii(n.events||[])]}}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}-role`)}]});let a={FunctionName:t.sub(`\${AWS::StackName}-${n.name}`),Runtime:n.runtime,Handler:n.handler,Role:t.getAtt(s,"Arn"),MemorySize:n.memory,Timeout:n.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2448
+ `;if(e.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:t.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:n.ami||t.findInMap("RegionMap",t.ref("AWS::Region"),"AMI"),InstanceType:n.instanceType,IamInstanceProfile:{Arn:t.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[t.ref("AppSecurityGroup")],UserData:t.base64(t.sub(r)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),n.loadBalancer){ei(e,n.loadBalancer);let i={LaunchTemplate:{LaunchTemplateId:t.ref("LaunchTemplate"),Version:t.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:n.autoScaling?.min.toString()||"1",MaxSize:n.autoScaling?.max.toString()||"3",DesiredCapacity:n.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],TargetGroupARNs:[t.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(e.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",i,{dependsOn:["LaunchTemplate","TargetGroup"]}),n.autoScaling)e.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:t.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),e.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:t.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),e.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(n.autoScaling.targetCPU||70).toString(),AlarmActions:[t.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:t.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),e.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:((n.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[t.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:t.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function ei(e,n){if(!n)return;e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:t.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:t.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:t.sub("${AWS::StackName}-alb"),Type:n.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[t.ref("PublicSubnet1"),t.ref("PublicSubnet2")],SecurityGroups:[t.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),e.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:t.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:t.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:n.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:n.healthCheck?.interval||30,HealthCheckTimeoutSeconds:n.healthCheck?.timeout||5,HealthyThresholdCount:n.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:t.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),e.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:t.getAtt("LoadBalancer","DNSName"),Export:{Name:t.sub("${AWS::StackName}-alb-dns")}}})}function hn(e,n,r){let i=e.toLogicalId(n),s=r.taskDefinition.containerDefinitions?.[0],a=s?.name||s?.Name||n,c=s?.portMappings?.[0]?.containerPort||s?.PortMappings?.[0]?.ContainerPort||3000,u=(r.taskDefinition.containerDefinitions||[]).flatMap((y)=>(y.secrets||y.Secrets||[]).map((h)=>h.valueFrom||h.ValueFrom)).filter(Boolean);if(!e.hasResource("ECSCluster"))e.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:t.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-cluster")}]});if(e.addResource(`${i}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"],...u.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:u},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),e.addResource(`${i}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:t.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!e.hasResource("ALBSecurityGroup"))e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...r.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:c,ToPort:c,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!e.hasResource("AppSecurityGroup"))e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:c,ToPort:c,SourceSecurityGroupId:t.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let d=(r.taskDefinition.containerDefinitions||[{name:n,image:t.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${n}:latest`),portMappings:[{containerPort:3000}]}]).map((y)=>({Name:y.Name||y.name,Image:y.Image||y.image,Essential:y.Essential??y.essential??!0,PortMappings:(y.PortMappings||y.portMappings||[]).map((h)=>({ContainerPort:h.ContainerPort??h.containerPort,Protocol:h.Protocol||h.protocol||"tcp"})),Environment:Array.isArray(y.Environment||y.environment)?(y.Environment||y.environment).map((h)=>({Name:h.Name||h.name,Value:h.Value??h.value})):Object.entries(y.Environment||y.environment||{}).map(([h,f])=>({Name:h,Value:f})),Secrets:(y.Secrets||y.secrets||[]).map((h)=>({Name:h.Name||h.name,ValueFrom:h.ValueFrom||h.valueFrom})),HealthCheck:y.HealthCheck||y.healthCheck,Command:y.Command||y.command,EntryPoint:y.EntryPoint||y.entryPoint,LogConfiguration:y.LogConfiguration||y.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":t.ref(`${i}LogGroup`),"awslogs-region":t.ref("AWS::Region"),"awslogs-stream-prefix":n}}}));e.addResource(`${i}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:t.sub(`\${AWS::StackName}-${n}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:r.taskDefinition.cpu,Memory:r.taskDefinition.memory,ExecutionRoleArn:t.getAtt(`${i}TaskExecutionRole`,"Arn"),TaskRoleArn:t.getAtt(`${i}TaskRole`,"Arn"),ContainerDefinitions:d},{dependsOn:[`${i}TaskExecutionRole`,`${i}TaskRole`,`${i}LogGroup`]}),e.addResource(`${i}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/ecs/\${AWS::StackName}/${n}`),RetentionInDays:14});let m=r.service.healthCheck||{};e.addResource(`${i}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:t.ref("VPC"),Port:c,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:m.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:m.interval||30,HealthCheckTimeoutSeconds:m.timeout||5,HealthyThresholdCount:m.healthyThreshold||2,UnhealthyThresholdCount:m.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),e.addResource(`${i}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[t.ref("PublicSubnet1"),t.ref("PublicSubnet2")],SecurityGroups:[t.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(r.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let p=r.loadBalancer?.customDomain?.certificateArn,g=r.loadBalancer?.originVerifyHeader;if(e.addResource(`${i}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref(`${i}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:p?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:g?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[`${i}LoadBalancer`,`${i}TargetGroup`]}),p)e.addResource(`${i}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:t.ref(`${i}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:p}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:g?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[`${i}LoadBalancer`,`${i}TargetGroup`]});if(g){let y=p?`${i}HttpsListener`:`${i}HttpListener`;e.addResource(`${i}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:t.ref(y),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:g.name,Values:[g.value]}}],Actions:[{Type:"forward",TargetGroupArn:t.ref(`${i}TargetGroup`)}]},{dependsOn:[y,`${i}TargetGroup`]})}if(e.addResource(`${i}Service`,"AWS::ECS::Service",{ServiceName:t.sub(`\${AWS::StackName}-${n}`),Cluster:t.ref("ECSCluster"),TaskDefinition:t.ref(`${i}TaskDefinition`),DesiredCount:r.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:a,ContainerPort:c,TargetGroupArn:t.ref(`${i}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],SecurityGroups:[t.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${i}TaskDefinition`,g?`${i}OriginVerifyRule`:p?`${i}HttpsListener`:`${i}HttpListener`]}),r.service.autoScaling){let y=r.service.autoScaling;e.addResource(`${i}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:y.min,MaxCapacity:y.max,ResourceId:t.join("/",["service",t.ref("ECSCluster"),t.getAtt(`${i}Service`,"Name")]),RoleARN:t.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${i}Service`}),e.addResource(`${i}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:t.ref(`${i}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:y.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${i}ScalableTarget`})}e.addOutputs({[`${i}ClusterName`]:{Description:"ECS cluster name",Value:t.ref("ECSCluster")},[`${i}ServiceName`]:{Description:"ECS service name",Value:t.getAtt(`${i}Service`,"Name")},[`${i}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:t.getAtt(`${i}LoadBalancer`,"DNSName")},[`${i}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:t.getAtt(`${i}LoadBalancer`,"CanonicalHostedZoneID")},[`${i}TargetGroupArn`]:{Description:"ECS target group ARN",Value:t.ref(`${i}TargetGroup`)}})}function Pn(e,n){if(n.postgres)Rn(e,"postgres",n.postgres);if(n.mysql)Rn(e,"mysql",n.mysql);if(n.dynamodb?.tables)n.dynamodb.tables.forEach((r)=>{ti(e,r)})}function Rn(e,n,r){if(!r)return;let i=n==="postgres"?"postgres":"mysql",s=e.toLogicalId(`${i}-db`);e.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n==="postgres"?5432:3306,ToPort:n==="postgres"?5432:3306,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let a=n==="postgres"?`postgres${r.version.split(".")[0]}`:`mysql${r.version.split(".")[0]}.${r.version.split(".")[1]||"0"}`;if(r.parameters&&Object.keys(r.parameters).length>0)e.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${i}`,Family:a,Parameters:r.parameters,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-params")}]});e.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let c={Engine:i,EngineVersion:r.version,DBInstanceClass:r.instanceClass,AllocatedStorage:r.allocatedStorage.toString(),MaxAllocatedStorage:r.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:r.multiAZ!==!1,DBSubnetGroupName:t.ref("DBSubnetGroup"),VPCSecurityGroups:[t.ref("DBSecurityGroup")],MasterUsername:t.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:t.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:r.backupRetentionDays||7,PreferredBackupWindow:r.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:r.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:r.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:r.performanceInsightsRetention||7,DeletionProtection:r.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:n==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${i}-db`)}]};if(r.parameters&&Object.keys(r.parameters).length>0)c.DBParameterGroupName=t.ref("DBParameterGroup");e.addResource(s,"AWS::RDS::DBInstance",c,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:t.ref("DBSecret"),TargetId:t.ref(s),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[s,"DBSecret"]}),e.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:t.getAtt(s,"Endpoint.Address"),Export:{Name:t.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:t.getAtt(s,"Endpoint.Port"),Export:{Name:t.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:t.ref("DBSecret"),Export:{Name:t.sub("${AWS::StackName}-db-secret-arn")}}})}function ti(e,n){let r=e.toLogicalId(`${n.name}-table`),i={TableName:t.sub(`\${AWS::StackName}-${n.name}`),BillingMode:n.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:n.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]};if(n.sortKey)i.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"}),i.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.billingMode==="PROVISIONED")i.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};if(n.streamEnabled)i.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(n.pointInTimeRecovery)i.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(n.ttl?.enabled)i.TimeToLiveSpecification={Enabled:!0,AttributeName:n.ttl.attributeName};if(n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0)i.GlobalSecondaryIndexes=n.globalSecondaryIndexes.map((s)=>{let a=new Set(i.AttributeDefinitions.map((u)=>u.AttributeName));if(!a.has(s.partitionKey))i.AttributeDefinitions.push({AttributeName:s.partitionKey,AttributeType:"S"});if(s.sortKey&&!a.has(s.sortKey))i.AttributeDefinitions.push({AttributeName:s.sortKey,AttributeType:"S"});let c={IndexName:s.name,KeySchema:[{AttributeName:s.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:s.projectionType||"ALL"}};if(s.sortKey)c.KeySchema.push({AttributeName:s.sortKey,KeyType:"RANGE"});if(s.projectionType==="INCLUDE"&&s.nonKeyAttributes)c.Projection.NonKeyAttributes=s.nonKeyAttributes;if(n.billingMode==="PROVISIONED")c.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};return c});if(e.addResource(r,"AWS::DynamoDB::Table",i,{deletionPolicy:"Retain"}),e.addOutputs({[`${r}Name`]:{Description:`${n.name} table name`,Value:t.ref(r),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-table`)}},[`${r}Arn`]:{Description:`${n.name} table ARN`,Value:t.getAtt(r,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-table-arn`)}}}),n.streamEnabled)e.addOutputs({[`${r}StreamArn`]:{Description:`${n.name} stream ARN`,Value:t.getAtt(r,"StreamArn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-stream-arn`)}}})}function In(e,n){for(let[r,i]of Object.entries(n))i.forEach((s)=>{ni(e,s,r)})}function ni(e,n,r){let i=e.toLogicalId(`${r}-${n.name}-function`),s=`${i}Role`;e.addResource(s,"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:[...ii(n.events||[])]}}],Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}-role`)}]});let a={FunctionName:t.sub(`\${AWS::StackName}-${n.name}`),Runtime:n.runtime,Handler:n.handler,Role:t.getAtt(s,"Arn"),MemorySize:n.memory,Timeout:n.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:n.environment?{Variables:n.environment}:void 0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]};if(r!=="edge")a.VpcConfig={SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],SecurityGroupIds:[t.ref("AppSecurityGroup")]};if(e.addResource(i,"AWS::Lambda::Function",a,{dependsOn:s}),e.addResource(`${i}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/aws/lambda/\${AWS::StackName}-${n.name}`),RetentionInDays:14}),n.events)n.events.forEach((c,u)=>{ri(e,i,c,u)});e.addOutputs({[`${i}Arn`]:{Description:`${n.name} function ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-function-arn`)}}})}function ri(e,n,r,i){let s=`${n}EventSource${i}`;switch(r.type){case"http":break;case"s3":if(r.bucket){let a=e.toLogicalId(`${r.bucket}-bucket`);e.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(n),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:yn.s3Bucket(t.ref(a))},{dependsOn:[n,a]})}break;case"sqs":if(r.queueName){let a=e.toLogicalId(`${r.queueName}-queue`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"Arn"),FunctionName:t.ref(n),BatchSize:r.batchSize||10},{dependsOn:[n,a]})}break;case"kinesis":if(r.streamName){let a=e.toLogicalId(`${r.streamName}-stream`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"Arn"),FunctionName:t.ref(n),BatchSize:r.batchSize||100,StartingPosition:r.startingPosition||"LATEST",ParallelizationFactor:r.parallelizationFactor||1},{dependsOn:[n,a]})}break;case"dynamodb-stream":if(r.tableName){let a=e.toLogicalId(`${r.tableName}-table`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"StreamArn"),FunctionName:t.ref(n),BatchSize:r.batchSize||100,StartingPosition:r.startingPosition||"LATEST"},{dependsOn:[n,a]})}break;case"schedule":if(r.expression)e.addResource(`${s}Rule`,"AWS::Events::Rule",{ScheduleExpression:r.expression,State:"ENABLED",Targets:[{Arn:t.getAtt(n,"Arn"),Id:`${n}Target`}]},{dependsOn:n}),e.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(n),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.getAtt(`${s}Rule`,"Arn")},{dependsOn:[n,`${s}Rule`]});break}}function ii(e){let n=[];if(!e)return n;if(e.forEach((r)=>{switch(r.type){case"s3":n.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:r.bucket?`arn:aws:s3:::${r.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":n.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:r.queueName?yn.sqs(r.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":n.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:r.streamName?yn.kinesis(r.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":n.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:r.tableName?t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${r.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),n.length===0)n.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return n}function Dn(e,n){if(n.topics)n.topics.forEach((r)=>{si(e,r)})}function si(e,n){let r=e.toLogicalId(`${n.name}-topic`);if(e.addResource(r,"AWS::SNS::Topic",{TopicName:t.sub(`\${AWS::StackName}-${n.name}`),DisplayName:n.displayName||n.name,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]}),e.addResource(`${r}Policy`,"AWS::SNS::TopicPolicy",{Topics:[t.ref(r)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:t.ref(r)},{Effect:"Allow",Principal:{AWS:t.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:t.ref(r)}]}},{dependsOn:r}),n.subscriptions)n.subscriptions.forEach((i,s)=>{let a=`${r}Subscription${s+1}`,c={Protocol:i.protocol,TopicArn:t.ref(r),Endpoint:i.endpoint};if(i.filterPolicy)c.FilterPolicy=i.filterPolicy;if(i.protocol==="sqs"){let u=e.toLogicalId(`${i.endpoint}-queue`);c.Endpoint=t.getAtt(u,"Arn")}if(i.protocol==="lambda"){let u=e.toLogicalId(i.endpoint);c.Endpoint=t.getAtt(u,"Arn"),e.addResource(`${a}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(u),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:t.ref(r)},{dependsOn:[u,r]})}e.addResource(a,"AWS::SNS::Subscription",c,{dependsOn:r})});e.addOutputs({[`${r}Arn`]:{Description:`${n.name} topic ARN`,Value:t.ref(r),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-topic-arn`)}}})}function Nn(e,n){if(n.alarms&&n.alarms.length>0)e.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:t.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alarms")}]}),n.alarms.forEach((r,i)=>{ai(e,r,i)});if(n.dashboard)oi(e,n.dashboard);if(n.logs?.groups)n.logs.groups.forEach((r)=>{ci(e,r,n.logs?.retention)})}function ai(e,n,r){let i=e.toLogicalId(`alarm-${n.name||n.metric}-${r}`),s={AlarmName:n.name||t.sub(`\${AWS::StackName}-${n.metric}`),AlarmDescription:`Alarm for ${n.metric}`,MetricName:n.metric,Namespace:n.namespace||bt(n.metric,n.service),Statistic:n.statistic||"Average",Period:n.period||300,EvaluationPeriods:n.evaluationPeriods||1,Threshold:n.threshold,ComparisonOperator:n.comparisonOperator||"GreaterThanThreshold",TreatMissingData:n.treatMissingData||"notBreaching",AlarmActions:[t.ref("AlarmTopic")],OKActions:[t.ref("AlarmTopic")]};if(n.dimensions)s.Dimensions=Object.entries(n.dimensions).map(([a,c])=>({Name:a,Value:c}));else if(n.service)s.Dimensions=li(n.service);e.addResource(i,"AWS::CloudWatch::Alarm",s,{dependsOn:"AlarmTopic"})}function oi(e,n){if(!n)return;let r=[],i=0,s=0;n.widgets?.forEach((a)=>{let c=a.width||12,u=a.height||6;if(a.type==="metric"&&a.metrics){let d=a.metrics.map((m)=>{if(typeof m==="string")return[bt(m),m];else return[bt(m.metric,m.service),m.metric]});r.push({type:"metric",x:i,y:s,width:c,height:u,properties:{metrics:d,period:300,stat:"Average",region:t.ref("AWS::Region"),title:a.metrics.length>1?"Multiple Metrics":typeof a.metrics[0]==="string"?a.metrics[0]:a.metrics[0].metric}})}else if(a.type==="log"&&a.logGroup)r.push({type:"log",x:i,y:s,width:c,height:u,properties:{query:`SOURCE '${a.logGroup}'
2451
+ };`},Environment:n.environment?{Variables:n.environment}:void 0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]};if(r!=="edge")a.VpcConfig={SubnetIds:[t.ref("PrivateSubnet1"),t.ref("PrivateSubnet2")],SecurityGroupIds:[t.ref("AppSecurityGroup")]};if(e.addResource(i,"AWS::Lambda::Function",a,{dependsOn:s}),e.addResource(`${i}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/aws/lambda/\${AWS::StackName}-${n.name}`),RetentionInDays:14}),n.events)n.events.forEach((c,u)=>{ri(e,i,c,u)});e.addOutputs({[`${i}Arn`]:{Description:`${n.name} function ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-function-arn`)}}})}function ri(e,n,r,i){let s=`${n}EventSource${i}`;switch(r.type){case"http":break;case"s3":if(r.bucket){let a=e.toLogicalId(`${r.bucket}-bucket`);e.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(n),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:vn.s3Bucket(t.ref(a))},{dependsOn:[n,a]})}break;case"sqs":if(r.queueName){let a=e.toLogicalId(`${r.queueName}-queue`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"Arn"),FunctionName:t.ref(n),BatchSize:r.batchSize||10},{dependsOn:[n,a]})}break;case"kinesis":if(r.streamName){let a=e.toLogicalId(`${r.streamName}-stream`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"Arn"),FunctionName:t.ref(n),BatchSize:r.batchSize||100,StartingPosition:r.startingPosition||"LATEST",ParallelizationFactor:r.parallelizationFactor||1},{dependsOn:[n,a]})}break;case"dynamodb-stream":if(r.tableName){let a=e.toLogicalId(`${r.tableName}-table`);e.addResource(s,"AWS::Lambda::EventSourceMapping",{EventSourceArn:t.getAtt(a,"StreamArn"),FunctionName:t.ref(n),BatchSize:r.batchSize||100,StartingPosition:r.startingPosition||"LATEST"},{dependsOn:[n,a]})}break;case"schedule":if(r.expression)e.addResource(`${s}Rule`,"AWS::Events::Rule",{ScheduleExpression:r.expression,State:"ENABLED",Targets:[{Arn:t.getAtt(n,"Arn"),Id:`${n}Target`}]},{dependsOn:n}),e.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(n),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.getAtt(`${s}Rule`,"Arn")},{dependsOn:[n,`${s}Rule`]});break}}function ii(e){let n=[];if(!e)return n;if(e.forEach((r)=>{switch(r.type){case"s3":n.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:r.bucket?`arn:aws:s3:::${r.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":n.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:r.queueName?vn.sqs(r.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":n.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:r.streamName?vn.kinesis(r.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":n.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:r.tableName?t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${r.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),n.length===0)n.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return n}function Dn(e,n){if(n.topics)n.topics.forEach((r)=>{si(e,r)})}function si(e,n){let r=e.toLogicalId(`${n.name}-topic`);if(e.addResource(r,"AWS::SNS::Topic",{TopicName:t.sub(`\${AWS::StackName}-${n.name}`),DisplayName:n.displayName||n.name,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n.name}`)}]}),e.addResource(`${r}Policy`,"AWS::SNS::TopicPolicy",{Topics:[t.ref(r)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:t.ref(r)},{Effect:"Allow",Principal:{AWS:t.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:t.ref(r)}]}},{dependsOn:r}),n.subscriptions)n.subscriptions.forEach((i,s)=>{let a=`${r}Subscription${s+1}`,c={Protocol:i.protocol,TopicArn:t.ref(r),Endpoint:i.endpoint};if(i.filterPolicy)c.FilterPolicy=i.filterPolicy;if(i.protocol==="sqs"){let u=e.toLogicalId(`${i.endpoint}-queue`);c.Endpoint=t.getAtt(u,"Arn")}if(i.protocol==="lambda"){let u=e.toLogicalId(i.endpoint);c.Endpoint=t.getAtt(u,"Arn"),e.addResource(`${a}Permission`,"AWS::Lambda::Permission",{FunctionName:t.ref(u),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:t.ref(r)},{dependsOn:[u,r]})}e.addResource(a,"AWS::SNS::Subscription",c,{dependsOn:r})});e.addOutputs({[`${r}Arn`]:{Description:`${n.name} topic ARN`,Value:t.ref(r),Export:{Name:t.sub(`\${AWS::StackName}-${n.name}-topic-arn`)}}})}function Nn(e,n){if(n.alarms&&n.alarms.length>0)e.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:t.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-alarms")}]}),n.alarms.forEach((r,i)=>{ai(e,r,i)});if(n.dashboard)oi(e,n.dashboard);if(n.logs?.groups)n.logs.groups.forEach((r)=>{ci(e,r,n.logs?.retention)})}function ai(e,n,r){let i=e.toLogicalId(`alarm-${n.name||n.metric}-${r}`),s={AlarmName:n.name||t.sub(`\${AWS::StackName}-${n.metric}`),AlarmDescription:`Alarm for ${n.metric}`,MetricName:n.metric,Namespace:n.namespace||bt(n.metric,n.service),Statistic:n.statistic||"Average",Period:n.period||300,EvaluationPeriods:n.evaluationPeriods||1,Threshold:n.threshold,ComparisonOperator:n.comparisonOperator||"GreaterThanThreshold",TreatMissingData:n.treatMissingData||"notBreaching",AlarmActions:[t.ref("AlarmTopic")],OKActions:[t.ref("AlarmTopic")]};if(n.dimensions)s.Dimensions=Object.entries(n.dimensions).map(([a,c])=>({Name:a,Value:c}));else if(n.service)s.Dimensions=li(n.service);e.addResource(i,"AWS::CloudWatch::Alarm",s,{dependsOn:"AlarmTopic"})}function oi(e,n){if(!n)return;let r=[],i=0,s=0;n.widgets?.forEach((a)=>{let c=a.width||12,u=a.height||6;if(a.type==="metric"&&a.metrics){let d=a.metrics.map((m)=>{if(typeof m==="string")return[bt(m),m];else return[bt(m.metric,m.service),m.metric]});r.push({type:"metric",x:i,y:s,width:c,height:u,properties:{metrics:d,period:300,stat:"Average",region:t.ref("AWS::Region"),title:a.metrics.length>1?"Multiple Metrics":typeof a.metrics[0]==="string"?a.metrics[0]:a.metrics[0].metric}})}else if(a.type==="log"&&a.logGroup)r.push({type:"log",x:i,y:s,width:c,height:u,properties:{query:`SOURCE '${a.logGroup}'
2452
2452
  | fields @timestamp, @message
2453
2453
  | sort @timestamp desc
2454
- | limit 20`,region:t.ref("AWS::Region"),title:`Logs: ${a.logGroup}`}});else if(a.type==="text"&&a.text)r.push({type:"text",x:i,y:s,width:c,height:u,properties:{markdown:a.text}});if(i+=c,i>=24)i=0,s+=u}),e.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:t.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:r})}),e.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:t.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function ci(e,n,r){let i=e.toLogicalId(`${n}-log-group`);e.addResource(i,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:r||14,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]})}function bt(e,n){if(n)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"}[n.toLowerCase()]||"AWS/CloudWatch";let r=e.toLowerCase();if(r.includes("cpu")||r.includes("memory")||r.includes("network"))return"AWS/EC2";if(r.includes("lambda")||r.includes("invocation")||r.includes("duration"))return"AWS/Lambda";if(r.includes("request")||r.includes("latency")||r.includes("target"))return"AWS/ApplicationELB";if(r.includes("database")||r.includes("connection"))return"AWS/RDS";if(r.includes("read")||r.includes("write")||r.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function li(e){return{ec2:[{Name:"InstanceId",Value:t.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:t.ref("ECSCluster")},{Name:"ServiceName",Value:t.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:t.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:t.ref("Database")}],dynamodb:[{Name:"TableName",Value:t.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:t.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:t.ref("HttpApi")}]}[e.toLowerCase()]||[]}function xn(e,n){if(!n.vpc)return;let{cidr:r="10.0.0.0/16",availabilityZones:i=2,natGateways:s=1,enableDnsHostnames:a=!0,enableDnsSupport:c=!0}=n.vpc;e.addResource("VPC","AWS::EC2::VPC",{CidrBlock:r,EnableDnsHostnames:a,EnableDnsSupport:c,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-vpc")}]}),e.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-igw")}]}),e.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:t.ref("VPC"),InternetGatewayId:t.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let u=[];for(let g=0;g<i;g++){let y=`PublicSubnet${g+1}`;u.push(y),e.addResource(y,"AWS::EC2::Subnet",{VpcId:t.ref("VPC"),CidrBlock:t.select(g,t.cidr(t.getAtt("VPC","CidrBlock"),i*2,8)),AvailabilityZone:t.select(g,t.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-public-${g+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let d=[];for(let g=0;g<i;g++){let y=`PrivateSubnet${g+1}`;d.push(y),e.addResource(y,"AWS::EC2::Subnet",{VpcId:t.ref("VPC"),CidrBlock:t.select(g+i,t.cidr(t.getAtt("VPC","CidrBlock"),i*2,8)),AvailabilityZone:t.select(g,t.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-private-${g+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let m=[];for(let g=0;g<s;g++){let y=`NatEIP${g+1}`;m.push(y),e.addResource(y,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-nat-eip-${g+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let p=[];for(let g=0;g<s;g++){let y=`NatGateway${g+1}`;p.push(y);let h=g%i;e.addResource(y,"AWS::EC2::NatGateway",{AllocationId:t.getAtt(m[g],"AllocationId"),SubnetId:t.ref(u[h]),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-nat-${g+1}`)}]},{dependsOn:[m[g],u[h]]})}e.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),e.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:t.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:t.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),u.forEach((g,y)=>{e.addResource(`PublicSubnetRouteTableAssociation${y+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:t.ref(g),RouteTableId:t.ref("PublicRouteTable")},{dependsOn:[g,"PublicRouteTable"]})}),d.forEach((g,y)=>{let h=`PrivateRouteTable${y+1}`,f=y%s;e.addResource(h,"AWS::EC2::RouteTable",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-private-rt-${y+1}`)}]},{dependsOn:"VPC"}),e.addResource(`PrivateRoute${y+1}`,"AWS::EC2::Route",{RouteTableId:t.ref(h),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:t.ref(p[f])},{dependsOn:[h,p[f]]}),e.addResource(`PrivateSubnetRouteTableAssociation${y+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:t.ref(g),RouteTableId:t.ref(h)},{dependsOn:[g,h]})}),e.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:t.ref("VPC"),ServiceName:t.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[t.ref("PublicRouteTable"),...Array.from({length:i},(g,y)=>t.ref(`PrivateRouteTable${y+1}`))]},{dependsOn:"VPC"}),e.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),e.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:t.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:t.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addOutputs({VPCId:{Description:"VPC ID",Value:t.ref("VPC"),Export:{Name:t.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:t.join(",",u.map((g)=>t.ref(g))),Export:{Name:t.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:t.join(",",d.map((g)=>t.ref(g))),Export:{Name:t.sub("${AWS::StackName}-PrivateSubnets")}}})}function kn(e,n){for(let[r,i]of Object.entries(n))ui(e,r,i)}function ui(e,n,r){let i=e.toLogicalId(`${n}-queue`),s=r.fifo||!1,a;if(r.deadLetterQueue){let u=`${i}DLQ`;e.addResource(u,"AWS::SQS::Queue",{QueueName:s?t.sub(`\${AWS::StackName}-${n}-dlq.fifo`):t.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:s,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a=t.getAtt(u,"Arn")}let c={QueueName:s?t.sub(`\${AWS::StackName}-${n}.fifo`):t.sub(`\${AWS::StackName}-${n}`),FifoQueue:s,VisibilityTimeout:r.visibilityTimeout||30,MessageRetentionPeriod:r.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:r.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(s&&r.contentBasedDeduplication)c.ContentBasedDeduplication=!0;if(r.deadLetterQueue&&a)c.RedrivePolicy={deadLetterTargetArn:a,maxReceiveCount:r.maxReceiveCount||3};if(e.addResource(i,"AWS::SQS::Queue",c,{dependsOn:r.deadLetterQueue?`${i}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),e.addResource(`${i}Policy`,"AWS::SQS::QueuePolicy",{Queues:[t.ref(i)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:t.getAtt(i,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":t.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:i}),e.addOutputs({[`${i}Url`]:{Description:`${n} queue URL`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${i}Arn`]:{Description:`${n} queue ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),r.deadLetterQueue)e.addOutputs({[`${i}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:t.ref(`${i}DLQ`),Export:{Name:t.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function Mn(e,n){if(n.certificate)di(e,n.certificate);if(n.waf?.enabled)mi(e,n.waf);if(n.securityGroups)for(let[r,i]of Object.entries(n.securityGroups))pi(e,r,i)}function di(e,n){if(!n)return;let r=[n.domain];if(n.subdomains)r.push(...n.subdomains);e.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:r.map((i)=>({DomainName:i,HostedZoneId:t.ref("HostedZone")})),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-certificate")}]}),e.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:t.ref("Certificate"),Export:{Name:t.sub("${AWS::StackName}-certificate-arn")}}})}function mi(e,n){if(!n)return;let r=[],i=n.rules||["rateLimit","sqlInjection","xss"];if(i.includes("rateLimit"))r.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let s=r.length+1;if(i.includes("sqlInjection"))r.push({Name:"AWSManagedRulesSQLi",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(i.includes("xss"))r.push({Name:"AWSManagedRulesXSS",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(i.includes("knownBadInputs"))r.push({Name:"AWSManagedRulesKnownBadInputs",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(i.includes("coreRuleSet"))r.push({Name:"AWSManagedRulesCoreRuleSet",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(i.includes("linuxRuleSet"))r.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(i.includes("apiProtection"))r.push({Name:"AWSManagedRulesAPIProtection",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(i.includes("geoBlock"))r.push({Name:"GeoBlockRule",Priority:s++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(i.includes("connectionLimit"))r.push({Name:"ConnectionLimitRule",Priority:s++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(e.addResource("WebACL","AWS::WAFv2::WebACL",{Name:t.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:r,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:t.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-waf")}]}),e.hasResource("LoadBalancer"))e.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:t.ref("LoadBalancer"),WebACLArn:t.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});e.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:t.ref("WebACL"),Export:{Name:t.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:t.getAtt("WebACL","Arn"),Export:{Name:t.sub("${AWS::StackName}-waf-arn")}}})}function pi(e,n,r){if(!r)return;let i=e.toLogicalId(`${n}-security-group`),s=r.ingress?.map((c)=>({IpProtocol:c.protocol,FromPort:c.port,ToPort:c.port,CidrIp:c.cidr,SourceSecurityGroupId:c.source?t.ref(c.source):void 0}))||[],a=r.egress?.map((c)=>({IpProtocol:c.protocol,FromPort:c.port,ToPort:c.port,CidrIp:c.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];e.addResource(i,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:t.ref("VPC"),SecurityGroupIngress:s,SecurityGroupEgress:a,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),e.addOutputs({[`${i}Id`]:{Description:`${n} security group ID`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function Ln(e,n){for(let[r,i]of Object.entries(n)){if(i.type==="efs"){yi(e,r,i);continue}gi(e,r,i)}}function gi(e,n,r){let i=e.toLogicalId(`${n}-bucket`),s={BucketName:t.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(r.versioning)s.VersioningConfiguration={Status:"Enabled"};if(r.encryption)s.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!r.public)s.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(r.website)s.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(r.cors&&r.cors.length>0)s.CorsConfiguration={CorsRules:r.cors.map((a)=>({AllowedOrigins:a.allowedOrigins,AllowedMethods:a.allowedMethods,AllowedHeaders:a.allowedHeaders||["*"],MaxAge:a.maxAge||3600}))};if(r.lifecycleRules&&r.lifecycleRules.length>0)s.LifecycleConfiguration={Rules:r.lifecycleRules.map((a)=>({Id:a.id,Status:a.enabled?"Enabled":"Disabled",ExpirationInDays:a.expirationDays,Transitions:a.transitions?.map((c)=>({TransitionInDays:c.days,StorageClass:c.storageClass}))}))};if(r.intelligentTiering)s.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(e.addResource(i,"AWS::S3::Bucket",s,{deletionPolicy:r.versioning?"Retain":"Delete"}),r.public)e.addResource(`${i}Policy`,"AWS::S3::BucketPolicy",{Bucket:t.ref(i),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:t.join("",[yn.s3Bucket(t.ref(i)),"/*"])}]}},{dependsOn:i});if(e.addOutputs({[`${i}Name`]:{Description:`${n} bucket name`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${i}Arn`]:{Description:`${n} bucket ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),r.website)e.addOutputs({[`${i}WebsiteURL`]:{Description:`${n} website URL`,Value:t.getAtt(i,"WebsiteURL")}})}function yi(e,n,r){let i=e.toLogicalId(`${n}-efs`),s={Encrypted:r.encryption!==!1,PerformanceMode:r.performanceMode||"generalPurpose",ThroughputMode:r.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(r.lifecyclePolicy){if(s.LifecyclePolicies=[],r.lifecyclePolicy.transitionToIA)s.LifecyclePolicies.push({TransitionToIA:`AFTER_${r.lifecyclePolicy.transitionToIA}_DAYS`});if(r.lifecyclePolicy.transitionToPrimaryStorageClass)s.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}e.addResource(i,"AWS::EFS::FileSystem",s,{deletionPolicy:"Retain"});let a=2;for(let c=0;c<a;c++)e.addResource(`${i}MountTarget${c+1}`,"AWS::EFS::MountTarget",{FileSystemId:t.ref(i),SubnetId:t.ref(`PrivateSubnet${c+1}`),SecurityGroups:[t.ref("EFSSecurityGroup")]},{dependsOn:[i,`PrivateSubnet${c+1}`]});e.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),e.addOutputs({[`${i}Id`]:{Description:`${n} EFS file system ID`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-efs`)}}})}class nl{template;config;resourceDependencies;constructor(e){this.config=e,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${e.project.name} (${e.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:t.equals(t.ref("Environment"),"production"),HasDomain:t.not([t.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:e}=this.config;if(!e)return;if(e.network)this.addNetworkResources(e.network);if(e.storage)this.addStorageResources(e.storage);if(e.compute)this.addComputeResources(e.compute);if(e.databases)this.addDatabaseResources(e.databases);if(e.cache)this.addCacheResources(e.cache);if(e.cdn)this.addCDNResources(e.cdn);if(e.apiGateway)this.addApiGatewayResources(e.apiGateway);if(e.functions)this.addFunctionResources(e.functions);if(e.queues)this.addQueueResources(e.queues);if(e.messaging)this.addMessagingResources(e.messaging);if(e.monitoring)this.addMonitoringResources(e.monitoring);if(e.security)this.addSecurityResources(e.security)}initializeOutputs(){let e=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:t.ref("AWS::StackName"),Export:{Name:t.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:t.ref("AWS::Region"),Export:{Name:t.sub("${AWS::StackName}-Region")}},...e},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(e,n,r,i){let s={Type:n,Properties:r};if(i?.dependsOn)s.DependsOn=i.dependsOn,this.trackDependency(e,i.dependsOn);if(i?.condition)s.Condition=i.condition;if(i?.deletionPolicy)s.DeletionPolicy=i.deletionPolicy;if(i?.updateReplacePolicy)s.UpdateReplacePolicy=i.updateReplacePolicy;this.template.Resources[e]=s}addOutputs(e){this.template.Outputs={...this.template.Outputs,...e}}getOutputs(){return this.template.Outputs||{}}hasResource(e){return e in this.template.Resources}getResource(e){return this.template.Resources[e]}trackDependency(e,n){if(!this.resourceDependencies.has(e))this.resourceDependencies.set(e,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(e).add(i))}resolveDependencies(){let e=new Set,n=new Set,r=(i)=>{if(n.has(i))throw Error(`Circular dependency detected involving resource: ${i}`);if(e.has(i))return!0;e.add(i),n.add(i);let s=this.resourceDependencies.get(i);if(s)for(let a of s)r(a);return n.delete(i),!0};for(let i of this.resourceDependencies.keys())r(i)}toLogicalId(e){return e.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(e){xn(this,e)}addStorageResources(e){Ln(this,e)}addComputeResources(e){Pn(this,e)}addDatabaseResources(e){In(this,e)}addFunctionResources(e){wn(this,e)}addCacheResources(e){pn(this,e)}addQueueResources(e){kn(this,e)}addMessagingResources(e){Dn(this,e)}addCDNResources(e){An(this,e)}addApiGatewayResources(e){mn(this,e)}addMonitoringResources(e){Nn(this,e)}addSecurityResources(e){Mn(this,e)}}function ya(e){return new nl(e).build()}function Cm(e){let{name:n,slug:r,domain:i,subdomain:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s&&i?`${s}.${i}`:i}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:i?{domain:s&&i?`${s}.${i}`:i,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 Tm(e){let{name:n,slug:r,domain:i,instanceType:s="t3.small",minInstances:a=2,maxInstances:c=10}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",keyPair:`${r}-key`,autoScaling:{min:a,max:c,desired:a,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:i?{domain:i,subdomains:[`*.${i}`],validationMethod:"DNS"}:void 0}}}}function Em(e){let{name:n,slug:r,domain:i,taskCpu:s="256",taskMemory:a="512",desiredCount:c=2}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:s,memory:a,containerDefinitions:[{name:"app",image:`${r}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:c,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:c,max:c*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${r}-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:`${r}-queue`}]}},security:{certificate:i?{domain:i,subdomains:[`*.${i}`],validationMethod:"DNS"}:void 0}}}}function wm(e){let{name:n,slug:r,entry:i,domain:s,runtime:a="nodejs20.x",memory:c=1024,build:u,deploy:d,assets:m,queues:p=!0,scheduler:g="on",region:y="us-east-1"}=e;return{project:{name:n,slug:r,region:y},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"node",runtime:a,entry:i,memory:c,build:u,deploy:d,assets:m,queues:p,scheduler:g,domain:s}}}}}function ba(e){let n=e.database!==!1,r=e.cache!==!1,i=e.queue!==!1;return{project:{name:e.name,slug:e.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:e.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:e.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:t.ref("AWS::Region")},...n?[{name:"DB_HOST",value:t.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:t.getAtt("PostgresDb","Endpoint.Port")}]:[],...r?[{name:"REDIS_HOST",value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...i?[{name:"QUEUE_URL",value:t.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:t.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:t.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:e.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:e.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...e.certificateArn?{customDomain:{domain:e.domain,certificateArn:e.certificateArn}}:{},...e.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:e.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...r?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...i?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Am(e){let{name:n,slug:r,domain:i,apiSubdomain:s="api"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},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:i,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:`${r}-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:`${s}.${i}`,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:i,subdomains:[`*.${i}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Rm(e){let{name:n,slug:r,domain:i}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:i?{domain:i,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:{[`${r}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${r}-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:i?{domain:i,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 Im(e){let{name:n,slug:r,domain:i,instanceType:s="t3.small"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",keyPair:`${r}-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:i,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:i,subdomains:[`www.${i}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Pm(e){let{name:n,slug:r,domain:i,apiDomain:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},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:i,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},...s?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:s?{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[i],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:i,subdomains:s?[s]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function Dm(e){let{name:n,slug:r,domain:i,services:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:s.map((a)=>({name:a.name,type:"fargate",taskDefinition:{cpu:a.cpu||"256",memory:a.memory||"512",containerDefinitions:[{name:a.name,image:`${r}-${a.name}:latest`,portMappings:[{containerPort:a.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${a.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:a.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${r}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:i,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:s.map((a)=>({path:`/${a.name}/{proxy+}`,integration:{type:"vpc-link",service:a.name}}))},databases:{dynamodb:{tables:Object.fromEntries(s.map((a)=>[`${r}-${a.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:`${r}-events`,subscriptions:s.map((a)=>({protocol:"sqs",endpoint:`${r}-${a.name}-queue`,filterPolicy:{service:[a.name]}}))}}},monitoring:{dashboard:{name:`${r}-microservices`,widgets:s.map((a)=>({type:"metric",metrics:[{service:a.name,metric:"CPUUtilization"},{service:a.name,metric:"MemoryUtilization"},{service:a.name,metric:"RequestCount"}]}))},alarms:s.flatMap((a)=>[{name:`${a.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:a.name},{name:`${a.name}-errors`,metric:"Errors",threshold:10,service:a.name}])},security:{certificate:{domain:i,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function Nm(e){let{name:n,slug:r,domain:i}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{apiGateway:{type:"websocket",customDomain:i?{domain:i,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:`${r}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${r}-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"}]},[`${r}-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"}]},[`${r}-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:`${r}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:i?{domain:i,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function km(e){let{name:n,slug:r,retentionDays:i=7}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${r}-stream`,shardCount:2,retentionPeriod:i*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:`${r}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${r}-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:`${r}_analytics`,workgroup:`${r}-workgroup`,outputBucket:`${r}-query-results`,tables:[{name:"raw_events",location:`s3://${r}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${r}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${r}-crawler`,databaseName:`${r}_analytics`,s3Targets:[`s3://${r}-raw/`,`s3://${r}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${r}-etl-job`,scriptLocation:`s3://${r}-scripts/etl.py`,role:`${r}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${r}-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:`${r}-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:`${r}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function xm(e){let{name:n,slug:r,domain:i,modelS3Path:s=`s3://${r}-models/`,instanceType:a="ml.t3.medium"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},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:`${r}-inference`,modelS3Path:s,instanceType:a,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${r}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:i?{domain:i,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:`${r}-inference`,MODEL_BUCKET:`${r}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${r}-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:{[`${r}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${r}-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:`${r}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:i?{domain:i,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function _m(e){let{name:n,slug:r,domain:i,instanceType:s="t3.medium",minInstances:a=2,maxInstances:c=10,databaseEngine:u="mysql",sessionStore:d="redis"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",autoScaling:{min:a,max:c,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:t.ref("AWS::Region"),title:`Logs: ${a.logGroup}`}});else if(a.type==="text"&&a.text)r.push({type:"text",x:i,y:s,width:c,height:u,properties:{markdown:a.text}});if(i+=c,i>=24)i=0,s+=u}),e.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:t.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:r})}),e.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:t.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function ci(e,n,r){let i=e.toLogicalId(`${n}-log-group`);e.addResource(i,"AWS::Logs::LogGroup",{LogGroupName:t.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:r||14,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]})}function bt(e,n){if(n)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"}[n.toLowerCase()]||"AWS/CloudWatch";let r=e.toLowerCase();if(r.includes("cpu")||r.includes("memory")||r.includes("network"))return"AWS/EC2";if(r.includes("lambda")||r.includes("invocation")||r.includes("duration"))return"AWS/Lambda";if(r.includes("request")||r.includes("latency")||r.includes("target"))return"AWS/ApplicationELB";if(r.includes("database")||r.includes("connection"))return"AWS/RDS";if(r.includes("read")||r.includes("write")||r.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function li(e){return{ec2:[{Name:"InstanceId",Value:t.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:t.ref("ECSCluster")},{Name:"ServiceName",Value:t.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:t.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:t.ref("Database")}],dynamodb:[{Name:"TableName",Value:t.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:t.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:t.ref("HttpApi")}]}[e.toLowerCase()]||[]}function xn(e,n){if(!n.vpc)return;let{cidr:r="10.0.0.0/16",availabilityZones:i=2,natGateways:s=1,enableDnsHostnames:a=!0,enableDnsSupport:c=!0}=n.vpc;e.addResource("VPC","AWS::EC2::VPC",{CidrBlock:r,EnableDnsHostnames:a,EnableDnsSupport:c,Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-vpc")}]}),e.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-igw")}]}),e.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:t.ref("VPC"),InternetGatewayId:t.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let u=[];for(let g=0;g<i;g++){let y=`PublicSubnet${g+1}`;u.push(y),e.addResource(y,"AWS::EC2::Subnet",{VpcId:t.ref("VPC"),CidrBlock:t.select(g,t.cidr(t.getAtt("VPC","CidrBlock"),i*2,8)),AvailabilityZone:t.select(g,t.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-public-${g+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let d=[];for(let g=0;g<i;g++){let y=`PrivateSubnet${g+1}`;d.push(y),e.addResource(y,"AWS::EC2::Subnet",{VpcId:t.ref("VPC"),CidrBlock:t.select(g+i,t.cidr(t.getAtt("VPC","CidrBlock"),i*2,8)),AvailabilityZone:t.select(g,t.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-private-${g+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let m=[];for(let g=0;g<s;g++){let y=`NatEIP${g+1}`;m.push(y),e.addResource(y,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-nat-eip-${g+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let p=[];for(let g=0;g<s;g++){let y=`NatGateway${g+1}`;p.push(y);let h=g%i;e.addResource(y,"AWS::EC2::NatGateway",{AllocationId:t.getAtt(m[g],"AllocationId"),SubnetId:t.ref(u[h]),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-nat-${g+1}`)}]},{dependsOn:[m[g],u[h]]})}e.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),e.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:t.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:t.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),u.forEach((g,y)=>{e.addResource(`PublicSubnetRouteTableAssociation${y+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:t.ref(g),RouteTableId:t.ref("PublicRouteTable")},{dependsOn:[g,"PublicRouteTable"]})}),d.forEach((g,y)=>{let h=`PrivateRouteTable${y+1}`,f=y%s;e.addResource(h,"AWS::EC2::RouteTable",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-private-rt-${y+1}`)}]},{dependsOn:"VPC"}),e.addResource(`PrivateRoute${y+1}`,"AWS::EC2::Route",{RouteTableId:t.ref(h),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:t.ref(p[f])},{dependsOn:[h,p[f]]}),e.addResource(`PrivateSubnetRouteTableAssociation${y+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:t.ref(g),RouteTableId:t.ref(h)},{dependsOn:[g,h]})}),e.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:t.ref("VPC"),ServiceName:t.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[t.ref("PublicRouteTable"),...Array.from({length:i},(g,y)=>t.ref(`PrivateRouteTable${y+1}`))]},{dependsOn:"VPC"}),e.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:t.ref("VPC"),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),e.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:t.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:t.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addOutputs({VPCId:{Description:"VPC ID",Value:t.ref("VPC"),Export:{Name:t.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:t.join(",",u.map((g)=>t.ref(g))),Export:{Name:t.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:t.join(",",d.map((g)=>t.ref(g))),Export:{Name:t.sub("${AWS::StackName}-PrivateSubnets")}}})}function kn(e,n){for(let[r,i]of Object.entries(n))ui(e,r,i)}function ui(e,n,r){let i=e.toLogicalId(`${n}-queue`),s=r.fifo||!1,a;if(r.deadLetterQueue){let u=`${i}DLQ`;e.addResource(u,"AWS::SQS::Queue",{QueueName:s?t.sub(`\${AWS::StackName}-${n}-dlq.fifo`):t.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:s,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a=t.getAtt(u,"Arn")}let c={QueueName:s?t.sub(`\${AWS::StackName}-${n}.fifo`):t.sub(`\${AWS::StackName}-${n}`),FifoQueue:s,VisibilityTimeout:r.visibilityTimeout||30,MessageRetentionPeriod:r.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:r.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(s&&r.contentBasedDeduplication)c.ContentBasedDeduplication=!0;if(r.deadLetterQueue&&a)c.RedrivePolicy={deadLetterTargetArn:a,maxReceiveCount:r.maxReceiveCount||3};if(e.addResource(i,"AWS::SQS::Queue",c,{dependsOn:r.deadLetterQueue?`${i}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),e.addResource(`${i}Policy`,"AWS::SQS::QueuePolicy",{Queues:[t.ref(i)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:t.getAtt(i,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":t.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:i}),e.addOutputs({[`${i}Url`]:{Description:`${n} queue URL`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${i}Arn`]:{Description:`${n} queue ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),r.deadLetterQueue)e.addOutputs({[`${i}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:t.ref(`${i}DLQ`),Export:{Name:t.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function Mn(e,n){if(n.certificate)di(e,n.certificate);if(n.waf?.enabled)mi(e,n.waf);if(n.securityGroups)for(let[r,i]of Object.entries(n.securityGroups))pi(e,r,i)}function di(e,n){if(!n)return;let r=[n.domain];if(n.subdomains)r.push(...n.subdomains);e.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:r.map((i)=>({DomainName:i,HostedZoneId:t.ref("HostedZone")})),Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-certificate")}]}),e.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:t.ref("Certificate"),Export:{Name:t.sub("${AWS::StackName}-certificate-arn")}}})}function mi(e,n){if(!n)return;let r=[],i=n.rules||["rateLimit","sqlInjection","xss"];if(i.includes("rateLimit"))r.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let s=r.length+1;if(i.includes("sqlInjection"))r.push({Name:"AWSManagedRulesSQLi",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(i.includes("xss"))r.push({Name:"AWSManagedRulesXSS",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(i.includes("knownBadInputs"))r.push({Name:"AWSManagedRulesKnownBadInputs",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(i.includes("coreRuleSet"))r.push({Name:"AWSManagedRulesCoreRuleSet",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(i.includes("linuxRuleSet"))r.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(i.includes("apiProtection"))r.push({Name:"AWSManagedRulesAPIProtection",Priority:s++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(i.includes("geoBlock"))r.push({Name:"GeoBlockRule",Priority:s++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(i.includes("connectionLimit"))r.push({Name:"ConnectionLimitRule",Priority:s++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(e.addResource("WebACL","AWS::WAFv2::WebACL",{Name:t.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:r,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:t.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-waf")}]}),e.hasResource("LoadBalancer"))e.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:t.ref("LoadBalancer"),WebACLArn:t.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});e.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:t.ref("WebACL"),Export:{Name:t.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:t.getAtt("WebACL","Arn"),Export:{Name:t.sub("${AWS::StackName}-waf-arn")}}})}function pi(e,n,r){if(!r)return;let i=e.toLogicalId(`${n}-security-group`),s=r.ingress?.map((c)=>({IpProtocol:c.protocol,FromPort:c.port,ToPort:c.port,CidrIp:c.cidr,SourceSecurityGroupId:c.source?t.ref(c.source):void 0}))||[],a=r.egress?.map((c)=>({IpProtocol:c.protocol,FromPort:c.port,ToPort:c.port,CidrIp:c.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];e.addResource(i,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:t.ref("VPC"),SecurityGroupIngress:s,SecurityGroupEgress:a,Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),e.addOutputs({[`${i}Id`]:{Description:`${n} security group ID`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function Ln(e,n){for(let[r,i]of Object.entries(n)){if(i.type==="efs"){yi(e,r,i);continue}gi(e,r,i)}}function gi(e,n,r){let i=e.toLogicalId(`${n}-bucket`),s={BucketName:t.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(r.versioning)s.VersioningConfiguration={Status:"Enabled"};if(r.encryption)s.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!r.public)s.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(r.website)s.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(r.cors&&r.cors.length>0)s.CorsConfiguration={CorsRules:r.cors.map((a)=>({AllowedOrigins:a.allowedOrigins,AllowedMethods:a.allowedMethods,AllowedHeaders:a.allowedHeaders||["*"],MaxAge:a.maxAge||3600}))};if(r.lifecycleRules&&r.lifecycleRules.length>0)s.LifecycleConfiguration={Rules:r.lifecycleRules.map((a)=>({Id:a.id,Status:a.enabled?"Enabled":"Disabled",ExpirationInDays:a.expirationDays,Transitions:a.transitions?.map((c)=>({TransitionInDays:c.days,StorageClass:c.storageClass}))}))};if(r.intelligentTiering)s.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(e.addResource(i,"AWS::S3::Bucket",s,{deletionPolicy:r.versioning?"Retain":"Delete"}),r.public)e.addResource(`${i}Policy`,"AWS::S3::BucketPolicy",{Bucket:t.ref(i),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:t.join("",[vn.s3Bucket(t.ref(i)),"/*"])}]}},{dependsOn:i});if(e.addOutputs({[`${i}Name`]:{Description:`${n} bucket name`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${i}Arn`]:{Description:`${n} bucket ARN`,Value:t.getAtt(i,"Arn"),Export:{Name:t.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),r.website)e.addOutputs({[`${i}WebsiteURL`]:{Description:`${n} website URL`,Value:t.getAtt(i,"WebsiteURL")}})}function yi(e,n,r){let i=e.toLogicalId(`${n}-efs`),s={Encrypted:r.encryption!==!1,PerformanceMode:r.performanceMode||"generalPurpose",ThroughputMode:r.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:t.sub(`\${AWS::StackName}-${n}`)}]};if(r.lifecyclePolicy){if(s.LifecyclePolicies=[],r.lifecyclePolicy.transitionToIA)s.LifecyclePolicies.push({TransitionToIA:`AFTER_${r.lifecyclePolicy.transitionToIA}_DAYS`});if(r.lifecyclePolicy.transitionToPrimaryStorageClass)s.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}e.addResource(i,"AWS::EFS::FileSystem",s,{deletionPolicy:"Retain"});let a=2;for(let c=0;c<a;c++)e.addResource(`${i}MountTarget${c+1}`,"AWS::EFS::MountTarget",{FileSystemId:t.ref(i),SubnetId:t.ref(`PrivateSubnet${c+1}`),SecurityGroups:[t.ref("EFSSecurityGroup")]},{dependsOn:[i,`PrivateSubnet${c+1}`]});e.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:t.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:t.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:t.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),e.addOutputs({[`${i}Id`]:{Description:`${n} EFS file system ID`,Value:t.ref(i),Export:{Name:t.sub(`\${AWS::StackName}-${n}-efs`)}}})}class al{template;config;resourceDependencies;constructor(e){this.config=e,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${e.project.name} (${e.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:t.equals(t.ref("Environment"),"production"),HasDomain:t.not([t.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:e}=this.config;if(!e)return;if(e.network)this.addNetworkResources(e.network);if(e.storage)this.addStorageResources(e.storage);if(e.compute)this.addComputeResources(e.compute);if(e.databases)this.addDatabaseResources(e.databases);if(e.cache)this.addCacheResources(e.cache);if(e.cdn)this.addCDNResources(e.cdn);if(e.apiGateway)this.addApiGatewayResources(e.apiGateway);if(e.functions)this.addFunctionResources(e.functions);if(e.queues)this.addQueueResources(e.queues);if(e.messaging)this.addMessagingResources(e.messaging);if(e.monitoring)this.addMonitoringResources(e.monitoring);if(e.security)this.addSecurityResources(e.security)}initializeOutputs(){let e=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:t.ref("AWS::StackName"),Export:{Name:t.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:t.ref("AWS::Region"),Export:{Name:t.sub("${AWS::StackName}-Region")}},...e},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(e,n,r,i){let s={Type:n,Properties:r};if(i?.dependsOn)s.DependsOn=i.dependsOn,this.trackDependency(e,i.dependsOn);if(i?.condition)s.Condition=i.condition;if(i?.deletionPolicy)s.DeletionPolicy=i.deletionPolicy;if(i?.updateReplacePolicy)s.UpdateReplacePolicy=i.updateReplacePolicy;this.template.Resources[e]=s}addOutputs(e){this.template.Outputs={...this.template.Outputs,...e}}getOutputs(){return this.template.Outputs||{}}hasResource(e){return e in this.template.Resources}getResource(e){return this.template.Resources[e]}trackDependency(e,n){if(!this.resourceDependencies.has(e))this.resourceDependencies.set(e,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(e).add(i))}resolveDependencies(){let e=new Set,n=new Set,r=(i)=>{if(n.has(i))throw Error(`Circular dependency detected involving resource: ${i}`);if(e.has(i))return!0;e.add(i),n.add(i);let s=this.resourceDependencies.get(i);if(s)for(let a of s)r(a);return n.delete(i),!0};for(let i of this.resourceDependencies.keys())r(i)}toLogicalId(e){return e.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(e){xn(this,e)}addStorageResources(e){Ln(this,e)}addComputeResources(e){fn(this,e)}addDatabaseResources(e){Pn(this,e)}addFunctionResources(e){In(this,e)}addCacheResources(e){pn(this,e)}addQueueResources(e){kn(this,e)}addMessagingResources(e){Dn(this,e)}addCDNResources(e){gn(this,e)}addApiGatewayResources(e){mn(this,e)}addMonitoringResources(e){Nn(this,e)}addSecurityResources(e){Mn(this,e)}}function Ca(e){return new al(e).build()}function Am(e){let{name:n,slug:r,domain:i,subdomain:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s&&i?`${s}.${i}`:i}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:i?{domain:s&&i?`${s}.${i}`:i,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 Rm(e){let{name:n,slug:r,domain:i,instanceType:s="t3.small",minInstances:a=2,maxInstances:c=10}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",keyPair:`${r}-key`,autoScaling:{min:a,max:c,desired:a,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:i?{domain:i,subdomains:[`*.${i}`],validationMethod:"DNS"}:void 0}}}}function Im(e){let{name:n,slug:r,domain:i,taskCpu:s="256",taskMemory:a="512",desiredCount:c=2}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:s,memory:a,containerDefinitions:[{name:"app",image:`${r}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:c,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:c,max:c*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${r}-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:`${r}-queue`}]}},security:{certificate:i?{domain:i,subdomains:[`*.${i}`],validationMethod:"DNS"}:void 0}}}}function Pm(e){let{name:n,slug:r,entry:i,domain:s,runtime:a="nodejs20.x",memory:c=1024,build:u,deploy:d,assets:m,queues:p=!0,scheduler:g="on",region:y="us-east-1"}=e;return{project:{name:n,slug:r,region:y},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"node",runtime:a,entry:i,memory:c,build:u,deploy:d,assets:m,queues:p,scheduler:g,domain:s}}}}}function Ta(e){let n=e.database!==!1,r=e.cache!==!1,i=e.queue!==!1;return{project:{name:e.name,slug:e.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:e.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:e.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:t.ref("AWS::Region")},...n?[{name:"DB_HOST",value:t.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:t.getAtt("PostgresDb","Endpoint.Port")}]:[],...r?[{name:"REDIS_HOST",value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:t.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...i?[{name:"QUEUE_URL",value:t.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:t.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:t.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:e.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:e.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...e.certificateArn?{customDomain:{domain:e.domain,certificateArn:e.certificateArn}}:{},...e.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:e.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...r?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...i?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Dm(e){let{name:n,slug:r,domain:i,apiSubdomain:s="api"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},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:i,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:`${r}-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:`${s}.${i}`,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:i,subdomains:[`*.${i}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function km(e){let{name:n,slug:r,domain:i}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:i?{domain:i,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:{[`${r}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${r}-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:i?{domain:i,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 Nm(e){let{name:n,slug:r,domain:i,instanceType:s="t3.small"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",keyPair:`${r}-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:i,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:i,subdomains:[`www.${i}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function xm(e){let{name:n,slug:r,domain:i,apiDomain:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},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:i,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},...s?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:s?{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[i],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:i,subdomains:s?[s]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function _m(e){let{name:n,slug:r,domain:i,services:s}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:s.map((a)=>({name:a.name,type:"fargate",taskDefinition:{cpu:a.cpu||"256",memory:a.memory||"512",containerDefinitions:[{name:a.name,image:`${r}-${a.name}:latest`,portMappings:[{containerPort:a.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${a.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:a.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${r}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:i,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:s.map((a)=>({path:`/${a.name}/{proxy+}`,integration:{type:"vpc-link",service:a.name}}))},databases:{dynamodb:{tables:Object.fromEntries(s.map((a)=>[`${r}-${a.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:`${r}-events`,subscriptions:s.map((a)=>({protocol:"sqs",endpoint:`${r}-${a.name}-queue`,filterPolicy:{service:[a.name]}}))}}},monitoring:{dashboard:{name:`${r}-microservices`,widgets:s.map((a)=>({type:"metric",metrics:[{service:a.name,metric:"CPUUtilization"},{service:a.name,metric:"MemoryUtilization"},{service:a.name,metric:"RequestCount"}]}))},alarms:s.flatMap((a)=>[{name:`${a.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:a.name},{name:`${a.name}-errors`,metric:"Errors",threshold:10,service:a.name}])},security:{certificate:{domain:i,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function Om(e){let{name:n,slug:r,domain:i}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},infrastructure:{apiGateway:{type:"websocket",customDomain:i?{domain:i,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:`${r}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${r}-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"}]},[`${r}-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"}]},[`${r}-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:`${r}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:i?{domain:i,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function $m(e){let{name:n,slug:r,retentionDays:i=7}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${r}-stream`,shardCount:2,retentionPeriod:i*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:`${r}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${r}-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:`${r}_analytics`,workgroup:`${r}-workgroup`,outputBucket:`${r}-query-results`,tables:[{name:"raw_events",location:`s3://${r}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${r}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${r}-crawler`,databaseName:`${r}_analytics`,s3Targets:[`s3://${r}-raw/`,`s3://${r}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${r}-etl-job`,scriptLocation:`s3://${r}-scripts/etl.py`,role:`${r}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${r}-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:`${r}-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:`${r}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function Lm(e){let{name:n,slug:r,domain:i,modelS3Path:s=`s3://${r}-models/`,instanceType:a="ml.t3.medium"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:i}},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:`${r}-inference`,modelS3Path:s,instanceType:a,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${r}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:i?{domain:i,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:`${r}-inference`,MODEL_BUCKET:`${r}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${r}-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:{[`${r}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${r}-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:`${r}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:i?{domain:i,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function Mm(e){let{name:n,slug:r,domain:i,instanceType:s="t3.medium",minInstances:a=2,maxInstances:c=10,databaseEngine:u="mysql",sessionStore:d="redis"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:i}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:s,ami:"ubuntu-22.04",autoScaling:{min:a,max:c,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:[i||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${r}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:i?{domain:i,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:u==="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:d==="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:`${r}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${r}-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:`${r}-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:[`${r}-app`,`${r}-nginx`,`${r}-workers`]}},security:{certificate:i?{domain:i,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:u==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...d==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function Om(e){let{name:n,slug:r,domain:i,repository:s,phpVersion:a="8.3",size:c="small",database:u=r.replace(/-/g,"_"),databasePassword:d,sslEmail:m,deployStrategy:p="push",provider:g="hetzner"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",cloud:{provider:g},environments:{production:{type:"production",domain:i}},infrastructure:{compute:{mode:"server",size:c,runtime:"php",webServer:"nginx",php:{versions:[a],default:a},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:u,username:u,password:d}},sites:{main:{root:".",type:"laravel",domain:i,phpVersion:a,repository:{...s,strategy:p},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:m}}}}}function $m(e){let{name:n,slug:r,domain:i,layers:s,phpVersion:a="8.3",architecture:c="x86_64",memory:u=1024,build:d,deploy:m=["migrate --force"],cache:p="dynamodb",scheduler:g="on",region:y="us-east-1"}=e;return{project:{name:n,slug:r,region:y},mode:"serverless",environments:{production:{type:"production",domain:i,app:{kind:"php",runtime:"provided.al2023",phpVersion:a,architecture:c,layers:s,memory:u,build:d,deploy:m,assets:"public",queues:!0,scheduler:g,cache:{driver:p},domain:i}}}}}function Lm(e){return{root:e.root??"packages/ui/dist",deploy:"server",type:"static",domain:e.domain,build:e.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:e.username??"admin",password:e.password}}}var iu=Zs,ou="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function hi(e){let n=e.split(".").filter(Boolean);return n.length<=2?e:n.slice(-2).join(".")}function fi(e){let n=2166136261;for(let r=0;r<e.length;r++)n^=e.charCodeAt(r),n=Math.imul(n,16777619);return n>>>0}var su=20000,au=12000;function cu(e){return su+fi(e)%au}function On(e,n){let r=hi(e);if(r===e)return`dashboard.${r}`;for(let i of n)if(i===r)return`dashboard.${r}`;return`dashboard.${e}`}function $n(e,n){let r=[],i=e.infrastructure?.dns?.domain;if(i&&!e.cloud?.attachTo)r.push(i);if(n&&e.environments?.[n]?.domain)r.push(e.environments[n].domain);for(let s of Object.values(e.sites??{})){let a=s;if(!a||a.redirect)continue;let c=a.domain;if(typeof c==="string")r.push(c);else if(Array.isArray(c))r.push(...c.filter((u)=>typeof u==="string"))}return r.filter((s)=>s&&!s.startsWith("dashboard."))}function lu(e,n,r){if(r)return r;let i=$n(e,n),s=i[0];if(!s)return null;return On(s,i)}function du(e,n,r){if(r)return[r];let i=$n(e,n),s=[];for(let a of i){let c=On(a,i);if(!s.includes(c))s.push(c)}return s}function Wt(e){return Object.entries(e.sites??{}).some(([n,r])=>{if(!r)return!1;let i=r.root??"";return _r(n)||i==="ui/dist"||i.endsWith("/ui/dist")||i.endsWith("/dist/ui")})}var il="dashboard-";function ol(e){return il+e.replace(/^dashboard\./,"").replace(/\./g,"-")}function _r(e){return e==="dashboard"||e.startsWith(il)}function xi(e,n,r){if(Wt(e))return[];if(e.cloud?.attachTo)return[];let i=r.password?{auth:{username:r.username||"admin",password:r.password,realm:r.realm}}:{},s=r.build===!1||r.build===void 0?{}:{build:r.build};if(r.live!==!1){let c=lu(e,n,r.domain);if(!c)return[];let u=r.port??cu(c),d=e.infrastructure?.appDatabase??e.infrastructure?.compute?.database,m={root:r.uiRoot,deploy:"server",domain:c,preStart:["bun install --production --no-save"],start:`bun ${ou} --box --host 127.0.0.1 --port ${u}`,port:u,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...d?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:d.password}:{}},zeroDowntime:!1,sharedPaths:[iu],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:ol(c),site:m}]}return du(e,n,r.domain).map((c)=>({name:ol(c),site:{root:r.uiRoot,deploy:"server",type:"static",domain:c,ssl:{provider:"letsencrypt"},...s,...i}}))}function Mm(e,n,r){return xi(e,n,r)[0]??null}function St(e,n){let r={...e};for(let i in n){let s=n[i],a=r[i];if(s===void 0)continue;if(Array.isArray(s)&&Array.isArray(a))r[i]=[...a,...s];else if(typeof s==="object"&&s!==null&&!Array.isArray(s)&&typeof a==="object"&&a!==null&&!Array.isArray(a))r[i]=St(a,s);else r[i]=s}return r}function sl(e,n){return St(e,n)}function Um(...e){return e.reduce((n,r)=>St(n,r),{})}function Fm(e,n){return(r)=>{let i=e(r);if(typeof n==="function")return sl(i,n(i,r));return sl(i,n)}}function bn(e){return{infrastructure:e}}function Bm(e){return bn({monitoring:e})}function jm(e){return bn({security:e})}function Vm(e){return bn({databases:e})}function zm(e){return bn({cache:e})}function Hm(e){return bn({cdn:e})}function Gm(e){return bn({queues:e})}import{existsSync as Bn,readFileSync as Ct}from"node:fs";import{homedir as Fn}from"node:os";import{join as Gn}from"node:path";function uu(){let e=process.env.AWS_ACCESS_KEY_ID,n=process.env.AWS_SECRET_ACCESS_KEY;if(!e||!n)return null;return{accessKeyId:e,secretAccessKey:n,sessionToken:process.env.AWS_SESSION_TOKEN}}function pu(e){let n=e?.profile||process.env.AWS_PROFILE||"default",r=e?.credentialsFile||Gn(Fn(),".aws","credentials");if(!Bn(r))return null;try{let i=Ct(r,"utf-8");return bi(i,n)}catch{return null}}function bi(e,n){let r=e.split(`
2459
- `),i=null,s,a,c;for(let u of r){let d=u.trim();if(!d||d.startsWith("#")||d.startsWith(";"))continue;let m=d.match(/^\[([^\]]+)\]$/);if(m){if(i===n&&s&&a)return{accessKeyId:s,secretAccessKey:a,sessionToken:c};i=m[1],s=void 0,a=void 0,c=void 0;continue}if(i===n){let[p,...g]=d.split("="),y=g.join("=").trim();switch(p.trim().toLowerCase()){case"aws_access_key_id":s=y;break;case"aws_secret_access_key":a=y;break;case"aws_session_token":c=y;break}}}if(i===n&&s&&a)return{accessKeyId:s,secretAccessKey:a,sessionToken:c};return null}async function mu(e){let n=e?.timeout??1000,r="http://169.254.169.254";try{let i=await _e("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!i.ok)return null;let s=await i.text(),a=await _e("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":s}},n);if(!a.ok)return null;let c=(await a.text()).trim(),u=await _e(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${c}`,{headers:{"X-aws-ec2-metadata-token":s}},n);if(!u.ok)return null;let d=await u.json();return{accessKeyId:d.AccessKeyId,secretAccessKey:d.SecretAccessKey,sessionToken:d.Token,expiration:new Date(d.Expiration)}}catch{return null}}async function gu(e){let n=e?.timeout??1000,r=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,i=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,s=null;if(r)s=`http://169.254.170.2${r}`;else if(i)s=i;if(!s)return null;try{let a={},c=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(c)a.Authorization=c;let u=await _e(s,{headers:a},n);if(!u.ok)return null;let d=await u.json();return{accessKeyId:d.AccessKeyId,secretAccessKey:d.SecretAccessKey,sessionToken:d.Token,expiration:new Date(d.Expiration)}}catch{return null}}async function fu(e){let n=e?.timeout??5000,r=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,i=process.env.AWS_ROLE_ARN,s=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!r||!i)return null;try{let a=Ct(r,"utf-8").trim(),c=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",u=c.startsWith("us-gov")?`https://sts.${c}.amazonaws.com`:c==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${c}.amazonaws.com`,d=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:i,RoleSessionName:s,WebIdentityToken:a}),m=await _e(`${u}/?${d.toString()}`,{method:"POST"},n);if(!m.ok)return null;let p=await m.text(),g=Ge(p,"AccessKeyId"),y=Ge(p,"SecretAccessKey"),h=Ge(p,"SessionToken"),f=Ge(p,"Expiration");if(!g||!y)return null;return{accessKeyId:g,secretAccessKey:y,sessionToken:h??void 0,expiration:f?new Date(f):void 0}}catch{return null}}async function _i(e){let n=uu();if(n)return n;let r=pu(e);if(r)return r;let i=await fu(e);if(i)return i;let s=await gu(e);if(s)return s;let a=await mu(e);if(a)return a;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 qm(e){let n=null,r=null;return async()=>{if(n){if(!n.expiration)return n;let i=300000;if(n.expiration.getTime()-Date.now()>i)return n}if(r)return r;return r=_i(e).then((i)=>(n=i,r=null,i)).catch((i)=>{throw r=null,i}),r}}async function _e(e,n,r){let i=new AbortController,s=setTimeout(()=>i.abort(),r);try{let a=await fetch(e,{...n,signal:i.signal});return clearTimeout(s),a}catch(a){throw clearTimeout(s),a}}function Ge(e,n){let r=new RegExp(`<${n}>([^<]+)</${n}>`),i=e.match(r);return i?i[1]:null}async function Sn(e){return _i({profile:e})}function hu(e){let n=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(n)return n;let r=Gn(Fn(),".aws","config");if(Bn(r))try{let i=Ct(r,"utf-8"),s=e||process.env.AWS_PROFILE||"default",a=s==="default"?"[default]":`[profile ${s}]`,c=i.split(`
2460
- `),u=!1;for(let d of c){let m=d.trim();if(m.startsWith("[")){u=m===a;continue}if(u&&m.startsWith("region")){let[,p]=m.split("=");if(p)return p.trim()}}}catch{}return"us-east-1"}async function al(e){let n=e||await _i(),r=hu(),{signRequest:i}=await import("./chunk-ya71t2ed.js"),s=r.startsWith("us-gov")?`https://sts.${r}.amazonaws.com`:r==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${r}.amazonaws.com`,a="Action=GetCallerIdentity&Version=2011-06-15",c=i({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:r}),u=await fetch(c.url,{method:c.method,headers:c.headers,body:c.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let d=await u.text(),m=Ge(d,"Account");if(!m)throw Error("Failed to parse account ID from response");return m}class yu{profile;credentials=null;region;constructor(e="us-east-1",n="default"){this.profile=n;this.region=e}async init(){if(this.credentials=await Sn(this.profile),this.credentials.region)this.region=this.credentials.region}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async request(e,n){let r=await this.ensureCredentials(),i={Action:e,Version:"2010-05-15",...vt(n)},s=new URLSearchParams(i).toString(),c=await(await Pt({method:"POST",url:`https://cloudformation.${this.region}.amazonaws.com/`,service:"cloudformation",region:this.region,headers:{"Content-Type":"application/x-www-form-urlencoded"},body:s,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken})).text();return Si(c)}async createStack(e){let n={StackName:e.stackName};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;else throw Error("Either templateBody or templateURL must be provided");if(e.parameters)for(let[s,[a,c]]of Object.entries(e.parameters).entries())n[`Parameters.member.${s+1}.ParameterKey`]=a,n[`Parameters.member.${s+1}.ParameterValue`]=c;if(e.capabilities)for(let[s,a]of e.capabilities.entries())n[`Capabilities.member.${s+1}`]=a;if(e.tags)for(let[s,[a,c]]of Object.entries(e.tags).entries())n[`Tags.member.${s+1}.Key`]=a,n[`Tags.member.${s+1}.Value`]=c;if(e.timeoutInMinutes)n.TimeoutInMinutes=e.timeoutInMinutes;if(e.onFailure)n.OnFailure=e.onFailure;let r=await this.request("CreateStack",n);return(r?.CreateStackResult||r?.CreateStackResponse?.CreateStackResult||r)?.StackId}async updateStack(e){let n={StackName:e.stackName};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;if(e.parameters)for(let[s,[a,c]]of Object.entries(e.parameters).entries())n[`Parameters.member.${s+1}.ParameterKey`]=a,n[`Parameters.member.${s+1}.ParameterValue`]=c;if(e.capabilities)for(let[s,a]of e.capabilities.entries())n[`Capabilities.member.${s+1}`]=a;if(e.tags)for(let[s,[a,c]]of Object.entries(e.tags).entries())n[`Tags.member.${s+1}.Key`]=a,n[`Tags.member.${s+1}.Value`]=c;let r=await this.request("UpdateStack",n);return(r?.UpdateStackResult||r?.UpdateStackResponse?.UpdateStackResult||r)?.StackId}async deleteStack(e){await this.request("DeleteStack",{StackName:e})}async describeStack(e){let n=await this.request("DescribeStacks",{StackName:e}),i=(n?.DescribeStacksResult||n?.DescribeStacksResponse?.DescribeStacksResult||n)?.Stacks?.member,s=Array.isArray(i)?i[0]:i;if(!s)throw Error(`Stack ${e} not found`);return Ai(s)}async listStacks(e){let n={};if(e)for(let[i,s]of e.entries())n[`StackStatusFilter.member.${i+1}`]=s;let r=await this.request("ListStacks",n);return Ci(r)}async describeStackEvents(e){let n=await this.request("DescribeStackEvents",{StackName:e});return vi(n)}async waitForStack(e,n,r){let a=0,c=null;while(a<360){a++;let u=await this.describeStack(e);if(r)try{let d=await this.describeStackEvents(e),m=[];if(c){for(let p of d){if(p.EventId===c)break;m.push(p)}m.reverse()}else if(d.length>0)m=[d[0]];for(let p of m)r(p);if(d.length>0)c=d[0].EventId}catch{}if(u.StackStatus&&n.includes(u.StackStatus))return u;if(u.StackStatus?.includes("FAILED")||u.StackStatus?.includes("ROLLBACK"))throw Error(`Stack reached failed state: ${u.StackStatus}
2461
- Reason: ${u.StackStatusReason||"Unknown"}`);await new Promise((d)=>setTimeout(d,5000))}throw Error(`Timeout waiting for stack ${e} to complete`)}async waitForStackWithProgress(e,n,r){let s={"stack-create-complete":["CREATE_COMPLETE"],"stack-update-complete":["UPDATE_COMPLETE"],"stack-delete-complete":["DELETE_COMPLETE"]}[n];if(!s)throw Error(`Unknown waiter: ${n}`);return this.waitForStack(e,s,r)}async createChangeSet(e){let n={StackName:e.stackName,ChangeSetName:e.changeSetName,ChangeSetType:"UPDATE"};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;if(e.parameters)for(let[i,[s,a]]of Object.entries(e.parameters).entries())n[`Parameters.member.${i+1}.ParameterKey`]=s,n[`Parameters.member.${i+1}.ParameterValue`]=a;if(e.capabilities)for(let[i,s]of e.capabilities.entries())n[`Capabilities.member.${i+1}`]=s;return(await this.request("CreateChangeSet",n)).ChangeSetId}async executeChangeSet(e,n){await this.request("ExecuteChangeSet",{ChangeSetName:e,StackName:n})}async describeStacks(e){let n=typeof e==="string"?e:e.stackName;try{return{Stacks:[await this.describeStack(n)]}}catch{return{Stacks:[]}}}async getStackOutputs(e){let n=await this.request("DescribeStacks",{StackName:e}),i=(n?.DescribeStacksResult||n?.DescribeStacksResponse?.DescribeStacksResult||n)?.Stacks?.member,s=Array.isArray(i)?i[0]:i;if(!s)return{};let a={},c=s.Outputs?.member;if(c){let u=Array.isArray(c)?c:[c];for(let d of u)if(d.OutputKey&&d.OutputValue)a[d.OutputKey]=d.OutputValue}return a}}function vt(e,n=""){let r={};for(let[i,s]of Object.entries(e)){let a=n?`${n}.${i}`:i;if(Array.isArray(s))s.forEach((c,u)=>{if(typeof c==="object")Object.assign(r,vt(c,`${a}.${u+1}`));else r[`${a}.${u+1}`]=String(c)});else if(typeof s==="object"&&s!==null)Object.assign(r,vt(s,a));else if(s!==void 0&&s!==null)r[a]=String(s)}return r}function Si(e){e=e.replace(/<\?xml[^?]*\?>\s*/,"").trim();function n(s,a,c){let u=1,d=c,m=`<${a}`,p=`</${a}>`;while(d<s.length&&u>0){let g=s.indexOf(m,d),y=s.indexOf(p,d);if(y===-1)return-1;if(g!==-1&&g<y){let h=s[g+m.length];if(h===">"||h===" "||h==="/"){let f=s.indexOf(">",g);if(f!==-1&&s[f-1]==="/")d=f+1;else u++,d=f+1}else d=g+m.length}else{if(u--,u===0)return y;d=y+p.length}}return-1}function r(s,a){while(a<s.length&&/\s/.test(s[a]))a++;if(a>=s.length||s[a]!=="<"){let S=s.indexOf("<",a);if(S===-1)return{value:s.slice(a).trim(),end:s.length};return{value:s.slice(a,S).trim(),end:S}}if(s[a+1]==="/")return{value:void 0,end:a};let c=s.slice(a).match(/^<(\w+)([^>]*?)\/?>/);if(!c)return{value:void 0,end:a+1};let u=c[1];if(c[0].endsWith("/>"))return{value:"",end:a+c[0].length};let m=a+c[0].length,p=`</${u}>`,g=n(s,u,m);if(g===-1)return{value:void 0,end:a+c[0].length};let y=s.slice(m,g).trim();if(!y.includes("<"))return{value:y,end:g+p.length};let h={},f=m;while(f<g){while(f<g&&/\s/.test(s[f]))f++;if(f>=g)break;if(s[f]!=="<"||s[f+1]==="/")break;let S=s.slice(f).match(/^<(\w+)/);if(!S)break;let C=S[1],P=r(s,f);if(P.value===void 0){f++;continue}if(C==="member"||h[C]!==void 0){if(!Array.isArray(h[C]))h[C]=h[C]!==void 0?[h[C]]:[];h[C].push(P.value)}else h[C]=P.value;f=P.end}return{value:h,end:g+p.length}}return r(e,0).value||{}}function Ai(e){return{StackName:e.StackName||"",StackId:e.StackId,StackStatus:e.StackStatus,CreationTime:e.CreationTime,LastUpdatedTime:e.LastUpdatedTime,StackStatusReason:e.StackStatusReason,Description:e.Description}}function Ci(e){let r=(e?.ListStacksResult||e?.ListStacksResponse?.ListStacksResult||e)?.StackSummaries?.member;if(!r)return[];return(Array.isArray(r)?r:[r]).map((s)=>({StackName:s.StackName||"",StackId:s.StackId,StackStatus:s.StackStatus,CreationTime:s.CreationTime,LastUpdatedTime:s.LastUpdatedTime,StackStatusReason:s.StackStatusReason,Description:s.Description}))}function vi(e){let r=(e?.DescribeStackEventsResult||e?.DescribeStackEventsResponse?.DescribeStackEventsResult||e)?.StackEvents?.member;if(!r)return[];return(Array.isArray(r)?r:[r]).map((s)=>({StackId:s.StackId||"",EventId:s.EventId||"",StackName:s.StackName||"",LogicalResourceId:s.LogicalResourceId||"",PhysicalResourceId:s.PhysicalResourceId,ResourceType:s.ResourceType||"",Timestamp:s.Timestamp||"",ResourceStatus:s.ResourceStatus||"",ResourceStatusReason:s.ResourceStatusReason}))}var Ti=5242880,Tt=5242880;var Ei=5242880;class Sa{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(e={}){this.region=e.region||process.env.AWS_REGION||"us-east-1",this.endpoint=e.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=e.forcePathStyle||!1,this.credentials=e.credentials,this.credentialOptions=e.credentialOptions,this.retryOptions=e.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return _i(this.credentialOptions)}buildUrl(e,n){let r=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${e}/${r}`:`${this.endpoint}/${e}`;let i=new URL(this.endpoint);return i.hostname=`${e}.${i.hostname}`,n?`${i.origin}/${r}`:i.origin}async get(e,n,r={}){let i=await this.getCredentials(),s=this.buildUrl(e,n),a={};if(r.range)a.Range=r.range;if(r.ifModifiedSince)a["If-Modified-Since"]=r.ifModifiedSince.toUTCString();if(r.ifMatch)a["If-Match"]=r.ifMatch;if(r.ifNoneMatch)a["If-None-Match"]=r.ifNoneMatch;let c=new URL(s);if(r.responseContentType)c.searchParams.set("response-content-type",r.responseContentType);if(r.responseContentDisposition)c.searchParams.set("response-content-disposition",r.responseContentDisposition);let u=Y({method:"GET",url:c.toString(),headers:a,...i,service:"s3",region:this.region}),d=await fetch(u.url,{method:u.method,headers:u.headers});if(!d.ok&&d.status!==304){let m=await d.text();throw new fe(`Failed to get object: ${m}`,d.status,e,n)}return d}async getText(e,n,r={}){return(await this.get(e,n,r)).text()}async getJSON(e,n,r={}){return(await this.get(e,n,r)).json()}async getBuffer(e,n,r={}){return(await this.get(e,n,r)).arrayBuffer()}async put(e,n,r,i={}){let s,a;if(typeof r==="string")s=new TextEncoder().encode(r).length,a=r;else if(r instanceof ArrayBuffer)s=r.byteLength,a=r;else if(r instanceof Uint8Array)s=r.byteLength,a=r;else if(r instanceof Blob)s=r.size,a=r;else return this.uploadMultipart(e,n,r,{...i,partSize:Tt});if(s>Ei){let c=Fi(a).stream();return this.uploadMultipart(e,n,c,{...i,partSize:Tt})}return this.putSimple(e,n,a,s,i)}async putSimple(e,n,r,i,s){let a=await this.getCredentials(),c=this.buildUrl(e,n),u={"Content-Length":String(i),"Content-Type":s.contentType||_n(n)};if(s.contentEncoding)u["Content-Encoding"]=s.contentEncoding;if(s.cacheControl)u["Cache-Control"]=s.cacheControl;if(s.contentDisposition)u["Content-Disposition"]=s.contentDisposition;if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.tagging)u["x-amz-tagging"]=s.tagging;if(s.metadata)for(let[y,h]of Object.entries(s.metadata))u[`x-amz-meta-${y.toLowerCase()}`]=h;let d;if(typeof r==="string")d=r;else if(r instanceof Blob)d=await r.text();else d=new TextDecoder().decode(r instanceof ArrayBuffer?new Uint8Array(r):r);let m=Y({method:"PUT",url:c,headers:u,body:d,...a,service:"s3",region:this.region}),p=await fetch(m.url,{method:m.method,headers:m.headers,body:r});if(!p.ok){let y=await p.text();throw new fe(`Failed to put object: ${y}`,p.status,e,n)}return{etag:(p.headers.get("ETag")||"").replace(/"/g,"")}}async delete(e,n){let r=await this.getCredentials(),i=this.buildUrl(e,n),s=Y({method:"DELETE",url:i,...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(!a.ok&&a.status!==204){let c=await a.text();throw new fe(`Failed to delete object: ${c}`,a.status,e,n)}}async deleteMany(e,n){let r=await this.getCredentials(),i=`${this.buildUrl(e)}?delete`,a=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((f)=>`<Object><Key>${Bi(f)}</Key></Object>`).join("")}</Delete>`,c=Y({method:"POST",url:i,headers:{"Content-Type":"application/xml"},body:a,...r,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers,body:a});if(!u.ok){let f=await u.text();throw new fe(`Failed to delete objects: ${f}`,u.status,e)}let d=await u.text(),m=[],p=[],g=/<Deleted><Key>([^<]+)<\/Key>/g,y;while((y=g.exec(d))!==null)m.push(y[1]);let h=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((y=h.exec(d))!==null)p.push({key:y[1],error:`${y[2]}: ${y[3]}`});return{deleted:m,errors:p}}async list(e,n={}){let r=await this.getCredentials(),i=new URL(this.buildUrl(e));if(i.searchParams.set("list-type","2"),n.prefix)i.searchParams.set("prefix",n.prefix);if(n.delimiter)i.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)i.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)i.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)i.searchParams.set("start-after",n.startAfter);let s=Y({method:"GET",url:i.toString(),...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(!a.ok){let u=await a.text();throw new fe(`Failed to list objects: ${u}`,a.status,e)}let c=await a.text();return wi(c)}async*listAll(e,n={}){let r;do{let i=await this.list(e,{...n,continuationToken:r});for(let s of i.contents)yield s;r=i.nextContinuationToken}while(r)}async head(e,n){let r=await this.getCredentials(),i=this.buildUrl(e,n),s=Y({method:"HEAD",url:i,...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(a.status===404)return null;if(!a.ok){let u=await a.text();throw new fe(`Failed to head object: ${u}`,a.status,e,n)}let c={};return a.headers.forEach((u,d)=>{if(d.toLowerCase().startsWith("x-amz-meta-"))c[d.slice(11)]=u}),{contentLength:Number(a.headers.get("Content-Length")||0),contentType:a.headers.get("Content-Type")||"application/octet-stream",etag:(a.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(a.headers.get("Last-Modified")||0),metadata:c,storageClass:a.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:a.headers.get("x-amz-server-side-encryption")||void 0}}async exists(e,n){return await this.head(e,n)!==null}async copy(e,n,r,i,s={}){let a=await this.getCredentials(),c=this.buildUrl(r,i),u={"x-amz-copy-source":`/${e}/${encodeURIComponent(n)}`};if(s.metadataDirective)u["x-amz-metadata-directive"]=s.metadataDirective;if(s.contentType)u["Content-Type"]=s.contentType;if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[h,f]of Object.entries(s.metadata))u[`x-amz-meta-${h.toLowerCase()}`]=f;let d=Y({method:"PUT",url:c,headers:u,...a,service:"s3",region:this.region}),m=await fetch(d.url,{method:d.method,headers:d.headers});if(!m.ok){let h=await m.text();throw new fe(`Failed to copy object: ${h}`,m.status,r,i)}let g=(await m.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:g?g[1]:""}}async getPresignedUrl(e,n,r={}){let i=await this.getCredentials(),s=this.buildUrl(e,n);return Ko({url:s,method:r.method||"GET",expiresIn:r.expiresIn||3600,...i,service:"s3",region:this.region})}async uploadMultipart(e,n,r,i={}){let s=await this.getCredentials(),a=Math.max(i.partSize||Tt,Ti),c,u;if(r instanceof ReadableStream)c=r;else if(r instanceof Blob)c=r.stream(),u=r.size;else{let p=new Blob([r]);c=p.stream(),u=p.size}let{uploadId:d,baseUrl:m}=await this.initiateMultipartUpload(e,n,i);try{let p=await this.uploadParts(e,n,m,d,c,a,s,u,i.concurrency||4,i.onProgress);return await this.completeMultipartUpload(e,n,m,d,p)}catch(p){throw await this.abortMultipartUpload(e,n,d,m).catch(()=>{}),p}}async initiateMultipartUpload(e,n,r){let i=await this.getCredentials(),s=this.buildUrl(e,n),a=`${s}?uploads`,c={"Content-Type":r.contentType||_n(n)};if(r.storageClass)c["x-amz-storage-class"]=r.storageClass;if(r.serverSideEncryption)c["x-amz-server-side-encryption"]=r.serverSideEncryption;if(r.acl)c["x-amz-acl"]=r.acl;if(r.metadata)for(let[y,h]of Object.entries(r.metadata))c[`x-amz-meta-${y.toLowerCase()}`]=h;let u=Y({method:"POST",url:a,headers:c,...i,service:"s3",region:this.region}),d=await fetch(u.url,{method:u.method,headers:u.headers});if(!d.ok){let y=await d.text();throw new fe(`Failed to initiate multipart upload: ${y}`,d.status,e,n)}let p=(await d.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!p)throw new fe("Failed to parse upload ID from response",0,e,n);let g=s;if(d.url)try{let y=new URL(d.url);y.search="",g=y.toString()}catch{}return{uploadId:p[1],baseUrl:g}}async uploadParts(e,n,r,i,s,a,c,u,d,m){let p=[],g=s.getReader(),y=1,h=new Uint8Array(0),f=0,S=u?Math.ceil(u/a):void 0,C=new Map,P=async(v,I)=>{let D=`${r}?partNumber=${I}&uploadId=${encodeURIComponent(i)}`,x={"Content-Length":String(v.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},F=Y({method:"PUT",url:D,headers:x,...c,service:"s3",region:this.region}),M=await fetch(F.url,{method:F.method,headers:F.headers,body:v,redirect:"error"});if(!M.ok){let G=await M.text();throw new fe(`Failed to upload part ${I}: ${G}`,M.status,e,n)}let O=(M.headers.get("ETag")||"").replace(/"/g,"");if(!O)throw new fe(`Missing ETag for part ${I}`,M.status,e,n);return{partNumber:I,etag:O}},E=async()=>{let v=await Promise.race(C.values());C.delete(v.partNumber),p.push(v)};while(!0){let{done:v,value:I}=await g.read();if(I){let D=new Uint8Array(h.length+I.length);D.set(h),D.set(I,h.length),h=D}while(h.length>=a||v&&h.length>0){let D=h.slice(0,a);h=h.slice(a);let x=y++;if(C.size>=d)await E();if(C.set(x,P(D,x)),f+=D.byteLength,m)m({loaded:f,total:u||f,part:x,totalParts:S||x})}if(v)break}while(C.size>0)await E();return p.sort((v,I)=>v.partNumber-I.partNumber),p}async completeMultipartUpload(e,n,r,i,s){let a=await this.getCredentials(),c=`${r}?uploadId=${encodeURIComponent(i)}`,d=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${s.map((f)=>`<Part><PartNumber>${f.partNumber}</PartNumber><ETag>"${f.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,m=Y({method:"POST",url:c,headers:{"Content-Type":"application/xml"},body:d,...a,service:"s3",region:this.region}),p=await fetch(m.url,{method:m.method,headers:m.headers,body:d});if(!p.ok){let f=await p.text();throw new fe(`Failed to complete multipart upload: ${f}`,p.status,e,n)}let y=(await p.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:y?y[1]:""}}async abortMultipartUpload(e,n,r,i){let s=await this.getCredentials(),a=`${i??this.buildUrl(e,n)}?uploadId=${encodeURIComponent(r)}`,c=Y({method:"DELETE",url:a,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}async emptyAndDeleteBucket(e){let r=[];for await(let c of this.listAll(e,{}))if(r.push(c.key),r.length>=1000)await this.deleteMany(e,r),r=[];if(r.length>0)await this.deleteMany(e,r);let i=await this.getCredentials(),s=this.buildUrl(e),a=Y({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(a.url,{method:a.method,headers:a.headers})}}class fe extends Error{statusCode;bucket;key;constructor(e,n,r,i){super(e);this.statusCode=n;this.bucket=r;this.key=i;this.name="S3Error"}}function wi(e){let n=[],r=[],i=/<Contents>([\s\S]*?)<\/Contents>/g,s;while((s=i.exec(e))!==null){let c=s[1];n.push({key:q(c,"Key")||"",lastModified:new Date(q(c,"LastModified")||0),etag:(q(c,"ETag")||"").replace(/"/g,""),size:Number(q(c,"Size")||0),storageClass:q(c,"StorageClass")||"STANDARD"})}let a=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((s=a.exec(e))!==null)r.push(s[1]);return{contents:n,commonPrefixes:r,isTruncated:q(e,"IsTruncated")==="true",continuationToken:q(e,"ContinuationToken")||void 0,nextContinuationToken:q(e,"NextContinuationToken")||void 0,keyCount:Number(q(e,"KeyCount")||0),maxKeys:Number(q(e,"MaxKeys")||1000),prefix:q(e,"Prefix")||void 0,delimiter:q(e,"Delimiter")||void 0}}function q(e,n){let r=new RegExp(`<${n}>([^<]*)</${n}>`),i=e.match(r);return i?i[1]:null}function Bi(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function _n(e){let n=e.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"}[n||""]||"application/octet-stream"}function Fi(e){if(e instanceof Blob)return e;if(typeof e==="string")return new Blob([e],{type:"text/plain"});return new Blob([e])}function bu(e){return new Sa(e)}class Su{profile;credentials=null;constructor(e="default"){this.profile=e}async init(){this.credentials=await Sn(this.profile)}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async createInvalidation(e){let n=await this.ensureCredentials(),r=e.callerReference||`invalidation-${Date.now()}`,i=`<?xml version="1.0" encoding="UTF-8"?>
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:[i||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${r}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:i?{domain:i,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:u==="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:d==="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:`${r}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${r}-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:`${r}-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:[`${r}-app`,`${r}-nginx`,`${r}-workers`]}},security:{certificate:i?{domain:i,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:u==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...d==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function Um(e){let{name:n,slug:r,domain:i,repository:s,phpVersion:a="8.3",size:c="small",database:u=r.replace(/-/g,"_"),databasePassword:d,sslEmail:m,deployStrategy:p="push",provider:g="hetzner"}=e;return{project:{name:n,slug:r,region:"us-east-1"},mode:"server",cloud:{provider:g},environments:{production:{type:"production",domain:i}},infrastructure:{compute:{mode:"server",size:c,runtime:"php",webServer:"nginx",php:{versions:[a],default:a},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:u,username:u,password:d}},sites:{main:{root:".",type:"laravel",domain:i,phpVersion:a,repository:{...s,strategy:p},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:m}}}}}function Bm(e){let{name:n,slug:r,domain:i,layers:s,phpVersion:a="8.3",architecture:c="x86_64",memory:u=1024,build:d,deploy:m=["migrate --force"],cache:p="dynamodb",scheduler:g="on",region:y="us-east-1"}=e;return{project:{name:n,slug:r,region:y},mode:"serverless",environments:{production:{type:"production",domain:i,app:{kind:"php",runtime:"provided.al2023",phpVersion:a,architecture:c,layers:s,memory:u,build:d,deploy:m,assets:"public",queues:!0,scheduler:g,cache:{driver:p},domain:i}}}}}function Fm(e){return{root:e.root??"packages/ui/dist",deploy:"server",type:"static",domain:e.domain,build:e.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:e.username??"admin",password:e.password}}}var cu=na,lu="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function hi(e){let n=e.split(".").filter(Boolean);return n.length<=2?e:n.slice(-2).join(".")}function fi(e){let n=2166136261;for(let r=0;r<e.length;r++)n^=e.charCodeAt(r),n=Math.imul(n,16777619);return n>>>0}var du=20000,uu=12000;function pu(e){return du+fi(e)%uu}function On(e,n){let r=hi(e);if(r===e)return`dashboard.${r}`;for(let i of n)if(i===r)return`dashboard.${r}`;return`dashboard.${e}`}function $n(e,n){let r=[],i=e.infrastructure?.dns?.domain;if(i&&!e.cloud?.attachTo)r.push(i);if(n&&e.environments?.[n]?.domain)r.push(e.environments[n].domain);for(let s of Object.values(e.sites??{})){let a=s;if(!a||a.redirect)continue;let c=a.domain;if(typeof c==="string")r.push(c);else if(Array.isArray(c))r.push(...c.filter((u)=>typeof u==="string"))}return r.filter((s)=>s&&!s.startsWith("dashboard."))}function mu(e,n,r){if(r)return r;let i=$n(e,n),s=i[0];if(!s)return null;return On(s,i)}function gu(e,n,r){if(r)return[r];let i=$n(e,n),s=[];for(let a of i){let c=On(a,i);if(!s.includes(c))s.push(c)}return s}function Wt(e){return Object.entries(e.sites??{}).some(([n,r])=>{if(!r)return!1;let i=r.root??"";return Lr(n)||i==="ui/dist"||i.endsWith("/ui/dist")||i.endsWith("/dist/ui")})}var cl="dashboard-";function ll(e){return cl+e.replace(/^dashboard\./,"").replace(/\./g,"-")}function Lr(e){return e==="dashboard"||e.startsWith(cl)}function Li(e,n,r){if(Wt(e))return[];if(e.cloud?.attachTo)return[];let i=r.password?{auth:{username:r.username||"admin",password:r.password,realm:r.realm}}:{},s=r.build===!1||r.build===void 0?{}:{build:r.build};if(r.live!==!1){let c=mu(e,n,r.domain);if(!c)return[];let u=r.port??pu(c),d=e.infrastructure?.appDatabase??e.infrastructure?.compute?.database,m={root:r.uiRoot,deploy:"server",domain:c,preStart:["bun install --production --no-save"],start:`bun ${lu} --box --host 127.0.0.1 --port ${u}`,port:u,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...d?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:d.password}:{}},zeroDowntime:!1,sharedPaths:[cu],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:ll(c),site:m}]}return gu(e,n,r.domain).map((c)=>({name:ll(c),site:{root:r.uiRoot,deploy:"server",type:"static",domain:c,ssl:{provider:"letsencrypt"},...s,...i}}))}function jm(e,n,r){return Li(e,n,r)[0]??null}function St(e,n){let r={...e};for(let i in n){let s=n[i],a=r[i];if(s===void 0)continue;if(Array.isArray(s)&&Array.isArray(a))r[i]=[...a,...s];else if(typeof s==="object"&&s!==null&&!Array.isArray(s)&&typeof a==="object"&&a!==null&&!Array.isArray(a))r[i]=St(a,s);else r[i]=s}return r}function dl(e,n){return St(e,n)}function Vm(...e){return e.reduce((n,r)=>St(n,r),{})}function zm(e,n){return(r)=>{let i=e(r);if(typeof n==="function")return dl(i,n(i,r));return dl(i,n)}}function Cn(e){return{infrastructure:e}}function Hm(e){return Cn({monitoring:e})}function Gm(e){return Cn({security:e})}function qm(e){return Cn({databases:e})}function Wm(e){return Cn({cache:e})}function Km(e){return Cn({cdn:e})}function Jm(e){return Cn({queues:e})}import{existsSync as Bn,readFileSync as Ct}from"node:fs";import{homedir as Fn}from"node:os";import{join as Gn}from"node:path";function fu(){let e=process.env.AWS_ACCESS_KEY_ID,n=process.env.AWS_SECRET_ACCESS_KEY;if(!e||!n)return null;return{accessKeyId:e,secretAccessKey:n,sessionToken:process.env.AWS_SESSION_TOKEN}}function hu(e){let n=e?.profile||process.env.AWS_PROFILE||"default",r=e?.credentialsFile||Gn(Fn(),".aws","credentials");if(!Bn(r))return null;try{let i=Ct(r,"utf-8");return bi(i,n)}catch{return null}}function bi(e,n){let r=e.split(`
2459
+ `),i=null,s,a,c;for(let u of r){let d=u.trim();if(!d||d.startsWith("#")||d.startsWith(";"))continue;let m=d.match(/^\[([^\]]+)\]$/);if(m){if(i===n&&s&&a)return{accessKeyId:s,secretAccessKey:a,sessionToken:c};i=m[1],s=void 0,a=void 0,c=void 0;continue}if(i===n){let[p,...g]=d.split("="),y=g.join("=").trim();switch(p.trim().toLowerCase()){case"aws_access_key_id":s=y;break;case"aws_secret_access_key":a=y;break;case"aws_session_token":c=y;break}}}if(i===n&&s&&a)return{accessKeyId:s,secretAccessKey:a,sessionToken:c};return null}async function yu(e){let n=e?.timeout??1000,r="http://169.254.169.254";try{let i=await Ge("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!i.ok)return null;let s=await i.text(),a=await Ge("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":s}},n);if(!a.ok)return null;let c=(await a.text()).trim(),u=await Ge(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${c}`,{headers:{"X-aws-ec2-metadata-token":s}},n);if(!u.ok)return null;let d=await u.json();return{accessKeyId:d.AccessKeyId,secretAccessKey:d.SecretAccessKey,sessionToken:d.Token,expiration:new Date(d.Expiration)}}catch{return null}}async function bu(e){let n=e?.timeout??1000,r=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,i=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,s=null;if(r)s=`http://169.254.170.2${r}`;else if(i)s=i;if(!s)return null;try{let a={},c=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(c)a.Authorization=c;let u=await Ge(s,{headers:a},n);if(!u.ok)return null;let d=await u.json();return{accessKeyId:d.AccessKeyId,secretAccessKey:d.SecretAccessKey,sessionToken:d.Token,expiration:new Date(d.Expiration)}}catch{return null}}async function Su(e){let n=e?.timeout??5000,r=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,i=process.env.AWS_ROLE_ARN,s=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!r||!i)return null;try{let a=Ct(r,"utf-8").trim(),c=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",u=c.startsWith("us-gov")?`https://sts.${c}.amazonaws.com`:c==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${c}.amazonaws.com`,d=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:i,RoleSessionName:s,WebIdentityToken:a}),m=await Ge(`${u}/?${d.toString()}`,{method:"POST"},n);if(!m.ok)return null;let p=await m.text(),g=$e(p,"AccessKeyId"),y=$e(p,"SecretAccessKey"),h=$e(p,"SessionToken"),f=$e(p,"Expiration");if(!g||!y)return null;return{accessKeyId:g,secretAccessKey:y,sessionToken:h??void 0,expiration:f?new Date(f):void 0}}catch{return null}}async function Mi(e){let n=fu();if(n)return n;let r=hu(e);if(r)return r;let i=await Su(e);if(i)return i;let s=await bu(e);if(s)return s;let a=await yu(e);if(a)return a;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 Xm(e){let n=null,r=null;return async()=>{if(n){if(!n.expiration)return n;let i=300000;if(n.expiration.getTime()-Date.now()>i)return n}if(r)return r;return r=Mi(e).then((i)=>(n=i,r=null,i)).catch((i)=>{throw r=null,i}),r}}async function Ge(e,n,r){let i=new AbortController,s=setTimeout(()=>i.abort(),r);try{let a=await fetch(e,{...n,signal:i.signal});return clearTimeout(s),a}catch(a){throw clearTimeout(s),a}}function $e(e,n){let r=new RegExp(`<${n}>([^<]+)</${n}>`),i=e.match(r);return i?i[1]:null}async function Tn(e){return Mi({profile:e})}function vu(e){let n=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(n)return n;let r=Gn(Fn(),".aws","config");if(Bn(r))try{let i=Ct(r,"utf-8"),s=e||process.env.AWS_PROFILE||"default",a=s==="default"?"[default]":`[profile ${s}]`,c=i.split(`
2460
+ `),u=!1;for(let d of c){let m=d.trim();if(m.startsWith("[")){u=m===a;continue}if(u&&m.startsWith("region")){let[,p]=m.split("=");if(p)return p.trim()}}}catch{}return"us-east-1"}async function ul(e){let n=e||await Mi(),r=vu(),{signRequest:i}=await import("./chunk-m8p7mw67.js"),s=r.startsWith("us-gov")?`https://sts.${r}.amazonaws.com`:r==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${r}.amazonaws.com`,a="Action=GetCallerIdentity&Version=2011-06-15",c=i({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:r}),u=await fetch(c.url,{method:c.method,headers:c.headers,body:c.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let d=await u.text(),m=$e(d,"Account");if(!m)throw Error("Failed to parse account ID from response");return m}class Cu{profile;credentials=null;region;constructor(e="us-east-1",n="default"){this.profile=n;this.region=e}async init(){if(this.credentials=await Tn(this.profile),this.credentials.region)this.region=this.credentials.region}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async request(e,n){let r=await this.ensureCredentials(),i={Action:e,Version:"2010-05-15",...vt(n)},s=new URLSearchParams(i).toString(),c=await(await Pt({method:"POST",url:`https://cloudformation.${this.region}.amazonaws.com/`,service:"cloudformation",region:this.region,headers:{"Content-Type":"application/x-www-form-urlencoded"},body:s,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken})).text();return Si(c)}async createStack(e){let n={StackName:e.stackName};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;else throw Error("Either templateBody or templateURL must be provided");if(e.parameters)for(let[s,[a,c]]of Object.entries(e.parameters).entries())n[`Parameters.member.${s+1}.ParameterKey`]=a,n[`Parameters.member.${s+1}.ParameterValue`]=c;if(e.capabilities)for(let[s,a]of e.capabilities.entries())n[`Capabilities.member.${s+1}`]=a;if(e.tags)for(let[s,[a,c]]of Object.entries(e.tags).entries())n[`Tags.member.${s+1}.Key`]=a,n[`Tags.member.${s+1}.Value`]=c;if(e.timeoutInMinutes)n.TimeoutInMinutes=e.timeoutInMinutes;if(e.onFailure)n.OnFailure=e.onFailure;let r=await this.request("CreateStack",n);return(r?.CreateStackResult||r?.CreateStackResponse?.CreateStackResult||r)?.StackId}async updateStack(e){let n={StackName:e.stackName};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;if(e.parameters)for(let[s,[a,c]]of Object.entries(e.parameters).entries())n[`Parameters.member.${s+1}.ParameterKey`]=a,n[`Parameters.member.${s+1}.ParameterValue`]=c;if(e.capabilities)for(let[s,a]of e.capabilities.entries())n[`Capabilities.member.${s+1}`]=a;if(e.tags)for(let[s,[a,c]]of Object.entries(e.tags).entries())n[`Tags.member.${s+1}.Key`]=a,n[`Tags.member.${s+1}.Value`]=c;let r=await this.request("UpdateStack",n);return(r?.UpdateStackResult||r?.UpdateStackResponse?.UpdateStackResult||r)?.StackId}async deleteStack(e){await this.request("DeleteStack",{StackName:e})}async describeStack(e){let n=await this.request("DescribeStacks",{StackName:e}),i=(n?.DescribeStacksResult||n?.DescribeStacksResponse?.DescribeStacksResult||n)?.Stacks?.member,s=Array.isArray(i)?i[0]:i;if(!s)throw Error(`Stack ${e} not found`);return Ai(s)}async listStacks(e){let n={};if(e)for(let[i,s]of e.entries())n[`StackStatusFilter.member.${i+1}`]=s;let r=await this.request("ListStacks",n);return Ci(r)}async describeStackEvents(e){let n=await this.request("DescribeStackEvents",{StackName:e});return vi(n)}async waitForStack(e,n,r){let a=0,c=null;while(a<360){a++;let u=await this.describeStack(e);if(r)try{let d=await this.describeStackEvents(e),m=[];if(c){for(let p of d){if(p.EventId===c)break;m.push(p)}m.reverse()}else if(d.length>0)m=[d[0]];for(let p of m)r(p);if(d.length>0)c=d[0].EventId}catch{}if(u.StackStatus&&n.includes(u.StackStatus))return u;if(u.StackStatus?.includes("FAILED")||u.StackStatus?.includes("ROLLBACK"))throw Error(`Stack reached failed state: ${u.StackStatus}
2461
+ Reason: ${u.StackStatusReason||"Unknown"}`);await new Promise((d)=>setTimeout(d,5000))}throw Error(`Timeout waiting for stack ${e} to complete`)}async waitForStackWithProgress(e,n,r){let s={"stack-create-complete":["CREATE_COMPLETE"],"stack-update-complete":["UPDATE_COMPLETE"],"stack-delete-complete":["DELETE_COMPLETE"]}[n];if(!s)throw Error(`Unknown waiter: ${n}`);return this.waitForStack(e,s,r)}async createChangeSet(e){let n={StackName:e.stackName,ChangeSetName:e.changeSetName,ChangeSetType:"UPDATE"};if(e.templateBody)n.TemplateBody=e.templateBody;else if(e.templateURL)n.TemplateURL=e.templateURL;if(e.parameters)for(let[i,[s,a]]of Object.entries(e.parameters).entries())n[`Parameters.member.${i+1}.ParameterKey`]=s,n[`Parameters.member.${i+1}.ParameterValue`]=a;if(e.capabilities)for(let[i,s]of e.capabilities.entries())n[`Capabilities.member.${i+1}`]=s;return(await this.request("CreateChangeSet",n)).ChangeSetId}async executeChangeSet(e,n){await this.request("ExecuteChangeSet",{ChangeSetName:e,StackName:n})}async describeStacks(e){let n=typeof e==="string"?e:e.stackName;try{return{Stacks:[await this.describeStack(n)]}}catch{return{Stacks:[]}}}async getStackOutputs(e){let n=await this.request("DescribeStacks",{StackName:e}),i=(n?.DescribeStacksResult||n?.DescribeStacksResponse?.DescribeStacksResult||n)?.Stacks?.member,s=Array.isArray(i)?i[0]:i;if(!s)return{};let a={},c=s.Outputs?.member;if(c){let u=Array.isArray(c)?c:[c];for(let d of u)if(d.OutputKey&&d.OutputValue)a[d.OutputKey]=d.OutputValue}return a}}function vt(e,n=""){let r={};for(let[i,s]of Object.entries(e)){let a=n?`${n}.${i}`:i;if(Array.isArray(s))s.forEach((c,u)=>{if(typeof c==="object")Object.assign(r,vt(c,`${a}.${u+1}`));else r[`${a}.${u+1}`]=String(c)});else if(typeof s==="object"&&s!==null)Object.assign(r,vt(s,a));else if(s!==void 0&&s!==null)r[a]=String(s)}return r}function Si(e){e=e.replace(/<\?xml[^?]*\?>\s*/,"").trim();function n(s,a,c){let u=1,d=c,m=`<${a}`,p=`</${a}>`;while(d<s.length&&u>0){let g=s.indexOf(m,d),y=s.indexOf(p,d);if(y===-1)return-1;if(g!==-1&&g<y){let h=s[g+m.length];if(h===">"||h===" "||h==="/"){let f=s.indexOf(">",g);if(f!==-1&&s[f-1]==="/")d=f+1;else u++,d=f+1}else d=g+m.length}else{if(u--,u===0)return y;d=y+p.length}}return-1}function r(s,a){while(a<s.length&&/\s/.test(s[a]))a++;if(a>=s.length||s[a]!=="<"){let S=s.indexOf("<",a);if(S===-1)return{value:s.slice(a).trim(),end:s.length};return{value:s.slice(a,S).trim(),end:S}}if(s[a+1]==="/")return{value:void 0,end:a};let c=s.slice(a).match(/^<(\w+)([^>]*?)\/?>/);if(!c)return{value:void 0,end:a+1};let u=c[1];if(c[0].endsWith("/>"))return{value:"",end:a+c[0].length};let m=a+c[0].length,p=`</${u}>`,g=n(s,u,m);if(g===-1)return{value:void 0,end:a+c[0].length};let y=s.slice(m,g).trim();if(!y.includes("<"))return{value:y,end:g+p.length};let h={},f=m;while(f<g){while(f<g&&/\s/.test(s[f]))f++;if(f>=g)break;if(s[f]!=="<"||s[f+1]==="/")break;let S=s.slice(f).match(/^<(\w+)/);if(!S)break;let C=S[1],P=r(s,f);if(P.value===void 0){f++;continue}if(C==="member"||h[C]!==void 0){if(!Array.isArray(h[C]))h[C]=h[C]!==void 0?[h[C]]:[];h[C].push(P.value)}else h[C]=P.value;f=P.end}return{value:h,end:g+p.length}}return r(e,0).value||{}}function Ai(e){return{StackName:e.StackName||"",StackId:e.StackId,StackStatus:e.StackStatus,CreationTime:e.CreationTime,LastUpdatedTime:e.LastUpdatedTime,StackStatusReason:e.StackStatusReason,Description:e.Description}}function Ci(e){let r=(e?.ListStacksResult||e?.ListStacksResponse?.ListStacksResult||e)?.StackSummaries?.member;if(!r)return[];return(Array.isArray(r)?r:[r]).map((s)=>({StackName:s.StackName||"",StackId:s.StackId,StackStatus:s.StackStatus,CreationTime:s.CreationTime,LastUpdatedTime:s.LastUpdatedTime,StackStatusReason:s.StackStatusReason,Description:s.Description}))}function vi(e){let r=(e?.DescribeStackEventsResult||e?.DescribeStackEventsResponse?.DescribeStackEventsResult||e)?.StackEvents?.member;if(!r)return[];return(Array.isArray(r)?r:[r]).map((s)=>({StackId:s.StackId||"",EventId:s.EventId||"",StackName:s.StackName||"",LogicalResourceId:s.LogicalResourceId||"",PhysicalResourceId:s.PhysicalResourceId,ResourceType:s.ResourceType||"",Timestamp:s.Timestamp||"",ResourceStatus:s.ResourceStatus||"",ResourceStatusReason:s.ResourceStatusReason}))}var Ti=5242880,Tt=5242880;var Ri=5242880;class Ea{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(e={}){this.region=e.region||process.env.AWS_REGION||"us-east-1",this.endpoint=e.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=e.forcePathStyle||!1,this.credentials=e.credentials,this.credentialOptions=e.credentialOptions,this.retryOptions=e.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Mi(this.credentialOptions)}buildUrl(e,n){let r=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${e}/${r}`:`${this.endpoint}/${e}`;let i=new URL(this.endpoint);return i.hostname=`${e}.${i.hostname}`,n?`${i.origin}/${r}`:i.origin}async get(e,n,r={}){let i=await this.getCredentials(),s=this.buildUrl(e,n),a={};if(r.range)a.Range=r.range;if(r.ifModifiedSince)a["If-Modified-Since"]=r.ifModifiedSince.toUTCString();if(r.ifMatch)a["If-Match"]=r.ifMatch;if(r.ifNoneMatch)a["If-None-Match"]=r.ifNoneMatch;let c=new URL(s);if(r.responseContentType)c.searchParams.set("response-content-type",r.responseContentType);if(r.responseContentDisposition)c.searchParams.set("response-content-disposition",r.responseContentDisposition);let u=Y({method:"GET",url:c.toString(),headers:a,...i,service:"s3",region:this.region}),d=await fetch(u.url,{method:u.method,headers:u.headers});if(!d.ok&&d.status!==304){let m=await d.text();throw new fe(`Failed to get object: ${m}`,d.status,e,n)}return d}async getText(e,n,r={}){return(await this.get(e,n,r)).text()}async getJSON(e,n,r={}){return(await this.get(e,n,r)).json()}async getBuffer(e,n,r={}){return(await this.get(e,n,r)).arrayBuffer()}async put(e,n,r,i={}){let s,a;if(typeof r==="string")s=new TextEncoder().encode(r).length,a=r;else if(r instanceof ArrayBuffer)s=r.byteLength,a=r;else if(r instanceof Uint8Array)s=r.byteLength,a=r;else if(r instanceof Blob)s=r.size,a=r;else return this.uploadMultipart(e,n,r,{...i,partSize:Tt});if(s>Ri){let c=Ii(a).stream();return this.uploadMultipart(e,n,c,{...i,partSize:Tt})}return this.putSimple(e,n,a,s,i)}async putSimple(e,n,r,i,s){let a=await this.getCredentials(),c=this.buildUrl(e,n),u={"Content-Length":String(i),"Content-Type":s.contentType||_n(n)};if(s.contentEncoding)u["Content-Encoding"]=s.contentEncoding;if(s.cacheControl)u["Cache-Control"]=s.cacheControl;if(s.contentDisposition)u["Content-Disposition"]=s.contentDisposition;if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.tagging)u["x-amz-tagging"]=s.tagging;if(s.metadata)for(let[y,h]of Object.entries(s.metadata))u[`x-amz-meta-${y.toLowerCase()}`]=h;let d;if(typeof r==="string")d=r;else if(r instanceof Blob)d=await r.text();else d=new TextDecoder().decode(r instanceof ArrayBuffer?new Uint8Array(r):r);let m=Y({method:"PUT",url:c,headers:u,body:d,...a,service:"s3",region:this.region}),p=await fetch(m.url,{method:m.method,headers:m.headers,body:r});if(!p.ok){let y=await p.text();throw new fe(`Failed to put object: ${y}`,p.status,e,n)}return{etag:(p.headers.get("ETag")||"").replace(/"/g,"")}}async delete(e,n){let r=await this.getCredentials(),i=this.buildUrl(e,n),s=Y({method:"DELETE",url:i,...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(!a.ok&&a.status!==204){let c=await a.text();throw new fe(`Failed to delete object: ${c}`,a.status,e,n)}}async deleteMany(e,n){let r=await this.getCredentials(),i=`${this.buildUrl(e)}?delete`,a=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((f)=>`<Object><Key>${Ei(f)}</Key></Object>`).join("")}</Delete>`,c=Y({method:"POST",url:i,headers:{"Content-Type":"application/xml"},body:a,...r,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers,body:a});if(!u.ok){let f=await u.text();throw new fe(`Failed to delete objects: ${f}`,u.status,e)}let d=await u.text(),m=[],p=[],g=/<Deleted><Key>([^<]+)<\/Key>/g,y;while((y=g.exec(d))!==null)m.push(y[1]);let h=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((y=h.exec(d))!==null)p.push({key:y[1],error:`${y[2]}: ${y[3]}`});return{deleted:m,errors:p}}async list(e,n={}){let r=await this.getCredentials(),i=new URL(this.buildUrl(e));if(i.searchParams.set("list-type","2"),n.prefix)i.searchParams.set("prefix",n.prefix);if(n.delimiter)i.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)i.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)i.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)i.searchParams.set("start-after",n.startAfter);let s=Y({method:"GET",url:i.toString(),...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(!a.ok){let u=await a.text();throw new fe(`Failed to list objects: ${u}`,a.status,e)}let c=await a.text();return Pi(c)}async*listAll(e,n={}){let r;do{let i=await this.list(e,{...n,continuationToken:r});for(let s of i.contents)yield s;r=i.nextContinuationToken}while(r)}async head(e,n){let r=await this.getCredentials(),i=this.buildUrl(e,n),s=Y({method:"HEAD",url:i,...r,service:"s3",region:this.region}),a=await fetch(s.url,{method:s.method,headers:s.headers});if(a.status===404)return null;if(!a.ok){let u=await a.text();throw new fe(`Failed to head object: ${u}`,a.status,e,n)}let c={};return a.headers.forEach((u,d)=>{if(d.toLowerCase().startsWith("x-amz-meta-"))c[d.slice(11)]=u}),{contentLength:Number(a.headers.get("Content-Length")||0),contentType:a.headers.get("Content-Type")||"application/octet-stream",etag:(a.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(a.headers.get("Last-Modified")||0),metadata:c,storageClass:a.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:a.headers.get("x-amz-server-side-encryption")||void 0}}async exists(e,n){return await this.head(e,n)!==null}async copy(e,n,r,i,s={}){let a=await this.getCredentials(),c=this.buildUrl(r,i),u={"x-amz-copy-source":`/${e}/${encodeURIComponent(n)}`};if(s.metadataDirective)u["x-amz-metadata-directive"]=s.metadataDirective;if(s.contentType)u["Content-Type"]=s.contentType;if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[h,f]of Object.entries(s.metadata))u[`x-amz-meta-${h.toLowerCase()}`]=f;let d=Y({method:"PUT",url:c,headers:u,...a,service:"s3",region:this.region}),m=await fetch(d.url,{method:d.method,headers:d.headers});if(!m.ok){let h=await m.text();throw new fe(`Failed to copy object: ${h}`,m.status,r,i)}let g=(await m.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:g?g[1]:""}}async getPresignedUrl(e,n,r={}){let i=await this.getCredentials(),s=this.buildUrl(e,n);return Yo({url:s,method:r.method||"GET",expiresIn:r.expiresIn||3600,...i,service:"s3",region:this.region})}async uploadMultipart(e,n,r,i={}){let s=await this.getCredentials(),a=Math.max(i.partSize||Tt,Ti),c,u;if(r instanceof ReadableStream)c=r;else if(r instanceof Blob)c=r.stream(),u=r.size;else{let p=new Blob([r]);c=p.stream(),u=p.size}let{uploadId:d,baseUrl:m}=await this.initiateMultipartUpload(e,n,i);try{let p=await this.uploadParts(e,n,m,d,c,a,s,u,i.concurrency||4,i.onProgress);return await this.completeMultipartUpload(e,n,m,d,p)}catch(p){throw await this.abortMultipartUpload(e,n,d,m).catch(()=>{}),p}}async initiateMultipartUpload(e,n,r){let i=await this.getCredentials(),s=this.buildUrl(e,n),a=`${s}?uploads`,c={"Content-Type":r.contentType||_n(n)};if(r.storageClass)c["x-amz-storage-class"]=r.storageClass;if(r.serverSideEncryption)c["x-amz-server-side-encryption"]=r.serverSideEncryption;if(r.acl)c["x-amz-acl"]=r.acl;if(r.metadata)for(let[y,h]of Object.entries(r.metadata))c[`x-amz-meta-${y.toLowerCase()}`]=h;let u=Y({method:"POST",url:a,headers:c,...i,service:"s3",region:this.region}),d=await fetch(u.url,{method:u.method,headers:u.headers});if(!d.ok){let y=await d.text();throw new fe(`Failed to initiate multipart upload: ${y}`,d.status,e,n)}let p=(await d.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!p)throw new fe("Failed to parse upload ID from response",0,e,n);let g=s;if(d.url)try{let y=new URL(d.url);y.search="",g=y.toString()}catch{}return{uploadId:p[1],baseUrl:g}}async uploadParts(e,n,r,i,s,a,c,u,d,m){let p=[],g=s.getReader(),y=1,h=new Uint8Array(0),f=0,S=u?Math.ceil(u/a):void 0,C=new Map,P=async(v,I)=>{let D=`${r}?partNumber=${I}&uploadId=${encodeURIComponent(i)}`,N={"Content-Length":String(v.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},B=Y({method:"PUT",url:D,headers:N,...c,service:"s3",region:this.region}),M=await fetch(B.url,{method:B.method,headers:B.headers,body:v,redirect:"error"});if(!M.ok){let G=await M.text();throw new fe(`Failed to upload part ${I}: ${G}`,M.status,e,n)}let O=(M.headers.get("ETag")||"").replace(/"/g,"");if(!O)throw new fe(`Missing ETag for part ${I}`,M.status,e,n);return{partNumber:I,etag:O}},E=async()=>{let v=await Promise.race(C.values());C.delete(v.partNumber),p.push(v)};while(!0){let{done:v,value:I}=await g.read();if(I){let D=new Uint8Array(h.length+I.length);D.set(h),D.set(I,h.length),h=D}while(h.length>=a||v&&h.length>0){let D=h.slice(0,a);h=h.slice(a);let N=y++;if(C.size>=d)await E();if(C.set(N,P(D,N)),f+=D.byteLength,m)m({loaded:f,total:u||f,part:N,totalParts:S||N})}if(v)break}while(C.size>0)await E();return p.sort((v,I)=>v.partNumber-I.partNumber),p}async completeMultipartUpload(e,n,r,i,s){let a=await this.getCredentials(),c=`${r}?uploadId=${encodeURIComponent(i)}`,d=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${s.map((f)=>`<Part><PartNumber>${f.partNumber}</PartNumber><ETag>"${f.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,m=Y({method:"POST",url:c,headers:{"Content-Type":"application/xml"},body:d,...a,service:"s3",region:this.region}),p=await fetch(m.url,{method:m.method,headers:m.headers,body:d});if(!p.ok){let f=await p.text();throw new fe(`Failed to complete multipart upload: ${f}`,p.status,e,n)}let y=(await p.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:y?y[1]:""}}async abortMultipartUpload(e,n,r,i){let s=await this.getCredentials(),a=`${i??this.buildUrl(e,n)}?uploadId=${encodeURIComponent(r)}`,c=Y({method:"DELETE",url:a,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}async emptyAndDeleteBucket(e){let r=[];for await(let c of this.listAll(e,{}))if(r.push(c.key),r.length>=1000)await this.deleteMany(e,r),r=[];if(r.length>0)await this.deleteMany(e,r);let i=await this.getCredentials(),s=this.buildUrl(e),a=Y({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(a.url,{method:a.method,headers:a.headers})}}class fe extends Error{statusCode;bucket;key;constructor(e,n,r,i){super(e);this.statusCode=n;this.bucket=r;this.key=i;this.name="S3Error"}}function Pi(e){let n=[],r=[],i=/<Contents>([\s\S]*?)<\/Contents>/g,s;while((s=i.exec(e))!==null){let c=s[1];n.push({key:q(c,"Key")||"",lastModified:new Date(q(c,"LastModified")||0),etag:(q(c,"ETag")||"").replace(/"/g,""),size:Number(q(c,"Size")||0),storageClass:q(c,"StorageClass")||"STANDARD"})}let a=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((s=a.exec(e))!==null)r.push(s[1]);return{contents:n,commonPrefixes:r,isTruncated:q(e,"IsTruncated")==="true",continuationToken:q(e,"ContinuationToken")||void 0,nextContinuationToken:q(e,"NextContinuationToken")||void 0,keyCount:Number(q(e,"KeyCount")||0),maxKeys:Number(q(e,"MaxKeys")||1000),prefix:q(e,"Prefix")||void 0,delimiter:q(e,"Delimiter")||void 0}}function q(e,n){let r=new RegExp(`<${n}>([^<]*)</${n}>`),i=e.match(r);return i?i[1]:null}function Ei(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function _n(e){let n=e.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"}[n||""]||"application/octet-stream"}function Ii(e){if(e instanceof Blob)return e;if(typeof e==="string")return new Blob([e],{type:"text/plain"});return new Blob([e])}function Tu(e){return new Ea(e)}class Eu{profile;credentials=null;constructor(e="default"){this.profile=e}async init(){this.credentials=await Tn(this.profile)}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async createInvalidation(e){let n=await this.ensureCredentials(),r=e.callerReference||`invalidation-${Date.now()}`,i=`<?xml version="1.0" encoding="UTF-8"?>
2462
2462
  <InvalidationBatch>
2463
2463
  <Paths>
2464
2464
  <Quantity>${e.paths.length}</Quantity>
@@ -2467,24 +2467,24 @@ Reason: ${u.StackStatusReason||"Unknown"}`);await new Promise((d)=>setTimeout(d,
2467
2467
  </Items>
2468
2468
  </Paths>
2469
2469
  <CallerReference>${r}</CallerReference>
2470
- </InvalidationBatch>`,s=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e.distributionId}/invalidation`,a=await Pt({method:"POST",url:s,service:"cloudfront",region:"us-east-1",headers:{"Content-Type":"text/xml"},body:i,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey,sessionToken:n.sessionToken});return(await Tn(a)).Id}async getInvalidation(e,n){let r=await this.ensureCredentials(),i=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation/${n}`,s=await Pt({method:"GET",url:i,service:"cloudfront",region:"us-east-1",accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken});return await Tn(s)}async listInvalidations(e){let n=await this.ensureCredentials(),r=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation`,i=await Pt({method:"GET",url:r,service:"cloudfront",region:"us-east-1",accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey,sessionToken:n.sessionToken});return(await Tn(i)).Items||[]}async waitForInvalidation(e,n,r=60,i=5000){for(let s=0;s<r;s++){if((await this.getInvalidation(e,n)).Status==="Completed")return;if(s<r-1)await new Promise((c)=>setTimeout(c,i))}throw Error(`Invalidation ${n} did not complete within the expected time`)}async invalidateAll(e){return await this.createInvalidation({distributionId:e,paths:["/*"]})}}class Rt extends Error{code;solution;details;constructor(e,n,r,i){super(e);this.code=n;this.solution=r;this.details=i;this.name="CloudError",Error.captureStackTrace?.(this,Rt)}toString(){let e=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)e+=`
2470
+ </InvalidationBatch>`,s=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e.distributionId}/invalidation`,a=await Pt({method:"POST",url:s,service:"cloudfront",region:"us-east-1",headers:{"Content-Type":"text/xml"},body:i,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey,sessionToken:n.sessionToken});return(await An(a)).Id}async getInvalidation(e,n){let r=await this.ensureCredentials(),i=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation/${n}`,s=await Pt({method:"GET",url:i,service:"cloudfront",region:"us-east-1",accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken});return await An(s)}async listInvalidations(e){let n=await this.ensureCredentials(),r=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation`,i=await Pt({method:"GET",url:r,service:"cloudfront",region:"us-east-1",accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey,sessionToken:n.sessionToken});return(await An(i)).Items||[]}async waitForInvalidation(e,n,r=60,i=5000){for(let s=0;s<r;s++){if((await this.getInvalidation(e,n)).Status==="Completed")return;if(s<r-1)await new Promise((c)=>setTimeout(c,i))}throw Error(`Invalidation ${n} did not complete within the expected time`)}async invalidateAll(e){return await this.createInvalidation({distributionId:e,paths:["/*"]})}}class Rt extends Error{code;solution;details;constructor(e,n,r,i){super(e);this.code=n;this.solution=r;this.details=i;this.name="CloudError",Error.captureStackTrace?.(this,Rt)}toString(){let e=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)e+=`
2471
2471
 
2472
2472
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){e+=`
2473
2473
 
2474
2474
  Details:`;for(let[n,r]of Object.entries(this.details))e+=`
2475
- ${n}: ${JSON.stringify(r)}`}return e}}class zo extends Rt{constructor(e,n,r){super(e,"CONFIG_ERROR",n,r);this.name="ConfigurationError"}}class Kt extends Rt{constructor(e,n,r){super(e,"CREDENTIAL_ERROR",n,r);this.name="CredentialError"}}class vu extends Rt{constructor(e,n,r){super(e,"DEPLOYMENT_ERROR",n,r);this.name="DeploymentError"}}class cl extends Rt{constructor(e,n,r){super(e,"VALIDATION_ERROR",n,r);this.name="ValidationError"}}class Cu extends Rt{statusCode;constructor(e,n,r,i){super(e,"AWS_API_ERROR",r,i);this.statusCode=n;this.name="AWSAPIError"}}var Tu={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2475
+ ${n}: ${JSON.stringify(r)}`}return e}}class Wo extends Rt{constructor(e,n,r){super(e,"CONFIG_ERROR",n,r);this.name="ConfigurationError"}}class Kt extends Rt{constructor(e,n,r){super(e,"CREDENTIAL_ERROR",n,r);this.name="CredentialError"}}class wu extends Rt{constructor(e,n,r){super(e,"DEPLOYMENT_ERROR",n,r);this.name="DeploymentError"}}class pl extends Rt{constructor(e,n,r){super(e,"VALIDATION_ERROR",n,r);this.name="ValidationError"}}class Au extends Rt{statusCode;constructor(e,n,r,i){super(e,"AWS_API_ERROR",r,i);this.statusCode=n;this.name="AWSAPIError"}}var Ru={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2476
2476
  1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
2477
2477
  2. Create ~/.aws/credentials file with your credentials
2478
2478
  3. Use an IAM role (for EC2 instances)
2479
- 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 Eu(e){return Tu[e]}function ll(e,n){let r=Eu(e);return new Rt(r.message,e,r.solution,n)}class he{static verboseMode=!1;static debugMode=!1;static setVerbose(e){this.verboseMode=e}static setDebug(e){this.debugMode=e}static verbose(e,...n){if(this.verboseMode)console.log(`[VERBOSE] ${e}`,...n)}static debug(e,...n){if(this.debugMode)console.log(`[DEBUG] ${e}`,...n)}static info(e,...n){console.log(`ℹ ${e}`,...n)}static warn(e,...n){console.warn(`⚠ ${e}`,...n)}static error(e,n){if(console.error(`✖ ${e}`),n){if(n instanceof Rt)console.error(n.toString());else console.error(n.message);if(this.debugMode&&n.stack)console.error(`
2480
- Stack trace:`),console.error(n.stack)}}static success(e){console.log(`✔ ${e}`)}}function Wm(e){if(!e)throw ll("MISSING_CONFIG");if(!e.project)throw new zo("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!e.project.name)throw new zo("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!e.project.slug)throw new zo("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(e.project.slug))throw new cl("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:e.project.slug});if(e.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(e.project.region))throw ll("INVALID_REGION",{region:e.project.region})}he.success("Configuration validation passed")}function Km(e){let n=[];if(e.environments?.production&&e.infrastructure?.database){let r=e.infrastructure.database;if((r.postgres||r.mysql)&&!r.postgres?.multiAZ&&!r.mysql?.multiAZ)n.push("Production database should use Multi-AZ for high availability")}if(e.infrastructure?.storage){for(let[r,i]of Object.entries(e.infrastructure.storage))if(i.encryption===!1)n.push(`Storage "${r}" is not encrypted - consider enabling encryption for security`)}if(e.infrastructure?.storage){for(let[r,i]of Object.entries(e.infrastructure.storage))if(i.public===!0)n.push(`Storage "${r}" is publicly accessible - ensure this is intentional`)}if(e.infrastructure?.database){let r=e.infrastructure.database;if(r.postgres||r.mysql){let i=r.postgres?.backupRetentionDays||r.mysql?.backupRetentionDays;if(!i||i<7)n.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!e.infrastructure?.monitoring)n.push("No monitoring configured - consider adding CloudWatch alarms");return n}async function Jm(e="default"){try{he.verbose("Resolving AWS credentials...");let n=await Sn(e);if(!n.accessKeyId||!n.secretAccessKey)throw new Kt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");he.verbose("Credentials resolved successfully"),he.debug("Access Key ID:",n.accessKeyId.substring(0,8)+"..."),he.verbose("Testing credentials with GetCallerIdentity...");let r;try{r=await al(n),he.verbose("Credentials are valid"),he.debug("Account ID:",r)}catch(i){if(i instanceof Error)if(i.message.includes("InvalidClientTokenId"))throw new Kt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(i.message.includes("SignatureDoesNotMatch"))throw new Kt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(i.message.includes("ExpiredToken"))throw new Kt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Kt(`Failed to validate credentials: ${i.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw i}return{valid:!0,accountId:r,region:n.region}}catch(n){if(n instanceof Kt)throw n;return{valid:!1,error:n instanceof Error?n.message:"Unknown error"}}}async function Xm(e,n){return{allowed:n,denied:[]}}function wu(e){let n=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(e.infrastructure){if(e.infrastructure.storage)n.add("s3:CreateBucket"),n.add("s3:DeleteBucket"),n.add("s3:PutBucketPolicy"),n.add("s3:PutBucketVersioning"),n.add("s3:PutBucketEncryption"),n.add("s3:PutObject"),n.add("s3:GetObject");if(e.infrastructure.compute){if(e.infrastructure.compute.server)n.add("ec2:RunInstances"),n.add("ec2:TerminateInstances"),n.add("ec2:DescribeInstances"),n.add("autoscaling:CreateAutoScalingGroup"),n.add("autoscaling:UpdateAutoScalingGroup"),n.add("autoscaling:DeleteAutoScalingGroup"),n.add("elasticloadbalancing:CreateLoadBalancer"),n.add("elasticloadbalancing:DeleteLoadBalancer");if(e.infrastructure.compute.fargate)n.add("ecs:CreateCluster"),n.add("ecs:DeleteCluster"),n.add("ecs:CreateService"),n.add("ecs:UpdateService"),n.add("ecs:DeleteService"),n.add("ecs:RegisterTaskDefinition")}if(e.infrastructure.database){if(e.infrastructure.database.postgres||e.infrastructure.database.mysql)n.add("rds:CreateDBInstance"),n.add("rds:DeleteDBInstance"),n.add("rds:ModifyDBInstance"),n.add("rds:DescribeDBInstances");if(e.infrastructure.database.dynamodb)n.add("dynamodb:CreateTable"),n.add("dynamodb:DeleteTable"),n.add("dynamodb:UpdateTable"),n.add("dynamodb:DescribeTable")}if(e.infrastructure.functions)n.add("lambda:CreateFunction"),n.add("lambda:DeleteFunction"),n.add("lambda:UpdateFunctionCode"),n.add("lambda:UpdateFunctionConfiguration"),n.add("lambda:AddPermission");if(e.infrastructure.cdn)n.add("cloudfront:CreateDistribution"),n.add("cloudfront:UpdateDistribution"),n.add("cloudfront:DeleteDistribution"),n.add("cloudfront:GetDistribution");if(e.infrastructure.network)n.add("ec2:CreateVpc"),n.add("ec2:DeleteVpc"),n.add("ec2:CreateSubnet"),n.add("ec2:DeleteSubnet"),n.add("ec2:CreateInternetGateway"),n.add("ec2:DeleteInternetGateway"),n.add("ec2:CreateNatGateway"),n.add("ec2:DeleteNatGateway"),n.add("ec2:CreateRouteTable"),n.add("ec2:DeleteRouteTable"),n.add("ec2:CreateSecurityGroup"),n.add("ec2:DeleteSecurityGroup")}return n.add("iam:CreateRole"),n.add("iam:DeleteRole"),n.add("iam:AttachRolePolicy"),n.add("iam:DetachRolePolicy"),n.add("iam:PutRolePolicy"),n.add("iam:GetRole"),n.add("iam:PassRole"),Array.from(n).sort()}function Qm(e){let n=wu(e);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]},null,2)}var Pe={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 Ym(e){let n=[];if(he.verbose("Checking AWS service quotas..."),e.infrastructure?.compute?.server){let i=e.infrastructure.compute.server.autoScaling?.max||1;n.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:i,limit:Pe.ec2["Running On-Demand Instances"],percentage:i/Pe.ec2["Running On-Demand Instances"]*100,warning:i>Pe.ec2["Running On-Demand Instances"]*0.8})}if(e.infrastructure?.network?.vpc)n.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:Pe.ec2.VPCs,percentage:1/Pe.ec2.VPCs*100,warning:!1});if(e.infrastructure?.database?.postgres||e.infrastructure?.database?.mysql)n.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:Pe.rds["DB Instances"],percentage:1/Pe.rds["DB Instances"]*100,warning:!1});if(e.infrastructure?.storage){let i=Object.keys(e.infrastructure.storage).length;n.push({service:"S3",quotaName:"Buckets",currentValue:i,limit:Pe.s3.Buckets,percentage:i/Pe.s3.Buckets*100,warning:i>Pe.s3.Buckets*0.8})}if(e.infrastructure?.functions){let i=0;for(let s of Object.values(e.infrastructure.functions))if(Array.isArray(s))i+=s.length;n.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:i,limit:1000,percentage:i/1000*100,warning:i>800})}if(e.infrastructure?.database?.dynamodb){let i=e.infrastructure.database.dynamodb.tables?.length||0;n.push({service:"DynamoDB",quotaName:"Tables",currentValue:i,limit:Pe.dynamodb.Tables,percentage:i/Pe.dynamodb.Tables*100,warning:i>Pe.dynamodb.Tables*0.8})}let r=n.filter((i)=>i.warning);if(r.length>0){he.warn("Service quota warnings detected:");for(let i of r)he.warn(` ${i.service} - ${i.quotaName}: ${i.currentValue}/${i.limit} (${i.percentage.toFixed(1)}%)`)}else he.verbose("All service quotas are within limits");return n}function Zm(e){if(e.length===0)return"No quotas to check";let n=`Service Quota Usage:
2479
+ 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 Iu(e){return Ru[e]}function ml(e,n){let r=Iu(e);return new Rt(r.message,e,r.solution,n)}class he{static verboseMode=!1;static debugMode=!1;static setVerbose(e){this.verboseMode=e}static setDebug(e){this.debugMode=e}static verbose(e,...n){if(this.verboseMode)console.log(`[VERBOSE] ${e}`,...n)}static debug(e,...n){if(this.debugMode)console.log(`[DEBUG] ${e}`,...n)}static info(e,...n){console.log(`ℹ ${e}`,...n)}static warn(e,...n){console.warn(`⚠ ${e}`,...n)}static error(e,n){if(console.error(`✖ ${e}`),n){if(n instanceof Rt)console.error(n.toString());else console.error(n.message);if(this.debugMode&&n.stack)console.error(`
2480
+ Stack trace:`),console.error(n.stack)}}static success(e){console.log(`✔ ${e}`)}}function Qm(e){if(!e)throw ml("MISSING_CONFIG");if(!e.project)throw new Wo("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!e.project.name)throw new Wo("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!e.project.slug)throw new Wo("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(e.project.slug))throw new pl("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:e.project.slug});if(e.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(e.project.region))throw ml("INVALID_REGION",{region:e.project.region})}he.success("Configuration validation passed")}function Ym(e){let n=[];if(e.environments?.production&&e.infrastructure?.database){let r=e.infrastructure.database;if((r.postgres||r.mysql)&&!r.postgres?.multiAZ&&!r.mysql?.multiAZ)n.push("Production database should use Multi-AZ for high availability")}if(e.infrastructure?.storage){for(let[r,i]of Object.entries(e.infrastructure.storage))if(i.encryption===!1)n.push(`Storage "${r}" is not encrypted - consider enabling encryption for security`)}if(e.infrastructure?.storage){for(let[r,i]of Object.entries(e.infrastructure.storage))if(i.public===!0)n.push(`Storage "${r}" is publicly accessible - ensure this is intentional`)}if(e.infrastructure?.database){let r=e.infrastructure.database;if(r.postgres||r.mysql){let i=r.postgres?.backupRetentionDays||r.mysql?.backupRetentionDays;if(!i||i<7)n.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!e.infrastructure?.monitoring)n.push("No monitoring configured - consider adding CloudWatch alarms");return n}async function Zm(e="default"){try{he.verbose("Resolving AWS credentials...");let n=await Tn(e);if(!n.accessKeyId||!n.secretAccessKey)throw new Kt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");he.verbose("Credentials resolved successfully"),he.debug("Access Key ID:",n.accessKeyId.substring(0,8)+"..."),he.verbose("Testing credentials with GetCallerIdentity...");let r;try{r=await ul(n),he.verbose("Credentials are valid"),he.debug("Account ID:",r)}catch(i){if(i instanceof Error)if(i.message.includes("InvalidClientTokenId"))throw new Kt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(i.message.includes("SignatureDoesNotMatch"))throw new Kt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(i.message.includes("ExpiredToken"))throw new Kt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Kt(`Failed to validate credentials: ${i.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw i}return{valid:!0,accountId:r,region:n.region}}catch(n){if(n instanceof Kt)throw n;return{valid:!1,error:n instanceof Error?n.message:"Unknown error"}}}async function eg(e,n){return{allowed:n,denied:[]}}function Pu(e){let n=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(e.infrastructure){if(e.infrastructure.storage)n.add("s3:CreateBucket"),n.add("s3:DeleteBucket"),n.add("s3:PutBucketPolicy"),n.add("s3:PutBucketVersioning"),n.add("s3:PutBucketEncryption"),n.add("s3:PutObject"),n.add("s3:GetObject");if(e.infrastructure.compute){if(e.infrastructure.compute.server)n.add("ec2:RunInstances"),n.add("ec2:TerminateInstances"),n.add("ec2:DescribeInstances"),n.add("autoscaling:CreateAutoScalingGroup"),n.add("autoscaling:UpdateAutoScalingGroup"),n.add("autoscaling:DeleteAutoScalingGroup"),n.add("elasticloadbalancing:CreateLoadBalancer"),n.add("elasticloadbalancing:DeleteLoadBalancer");if(e.infrastructure.compute.fargate)n.add("ecs:CreateCluster"),n.add("ecs:DeleteCluster"),n.add("ecs:CreateService"),n.add("ecs:UpdateService"),n.add("ecs:DeleteService"),n.add("ecs:RegisterTaskDefinition")}if(e.infrastructure.database){if(e.infrastructure.database.postgres||e.infrastructure.database.mysql)n.add("rds:CreateDBInstance"),n.add("rds:DeleteDBInstance"),n.add("rds:ModifyDBInstance"),n.add("rds:DescribeDBInstances");if(e.infrastructure.database.dynamodb)n.add("dynamodb:CreateTable"),n.add("dynamodb:DeleteTable"),n.add("dynamodb:UpdateTable"),n.add("dynamodb:DescribeTable")}if(e.infrastructure.functions)n.add("lambda:CreateFunction"),n.add("lambda:DeleteFunction"),n.add("lambda:UpdateFunctionCode"),n.add("lambda:UpdateFunctionConfiguration"),n.add("lambda:AddPermission");if(e.infrastructure.cdn)n.add("cloudfront:CreateDistribution"),n.add("cloudfront:UpdateDistribution"),n.add("cloudfront:DeleteDistribution"),n.add("cloudfront:GetDistribution");if(e.infrastructure.network)n.add("ec2:CreateVpc"),n.add("ec2:DeleteVpc"),n.add("ec2:CreateSubnet"),n.add("ec2:DeleteSubnet"),n.add("ec2:CreateInternetGateway"),n.add("ec2:DeleteInternetGateway"),n.add("ec2:CreateNatGateway"),n.add("ec2:DeleteNatGateway"),n.add("ec2:CreateRouteTable"),n.add("ec2:DeleteRouteTable"),n.add("ec2:CreateSecurityGroup"),n.add("ec2:DeleteSecurityGroup")}return n.add("iam:CreateRole"),n.add("iam:DeleteRole"),n.add("iam:AttachRolePolicy"),n.add("iam:DetachRolePolicy"),n.add("iam:PutRolePolicy"),n.add("iam:GetRole"),n.add("iam:PassRole"),Array.from(n).sort()}function tg(e){let n=Pu(e);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]},null,2)}var Pe={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 rg(e){let n=[];if(he.verbose("Checking AWS service quotas..."),e.infrastructure?.compute?.server){let i=e.infrastructure.compute.server.autoScaling?.max||1;n.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:i,limit:Pe.ec2["Running On-Demand Instances"],percentage:i/Pe.ec2["Running On-Demand Instances"]*100,warning:i>Pe.ec2["Running On-Demand Instances"]*0.8})}if(e.infrastructure?.network?.vpc)n.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:Pe.ec2.VPCs,percentage:1/Pe.ec2.VPCs*100,warning:!1});if(e.infrastructure?.database?.postgres||e.infrastructure?.database?.mysql)n.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:Pe.rds["DB Instances"],percentage:1/Pe.rds["DB Instances"]*100,warning:!1});if(e.infrastructure?.storage){let i=Object.keys(e.infrastructure.storage).length;n.push({service:"S3",quotaName:"Buckets",currentValue:i,limit:Pe.s3.Buckets,percentage:i/Pe.s3.Buckets*100,warning:i>Pe.s3.Buckets*0.8})}if(e.infrastructure?.functions){let i=0;for(let s of Object.values(e.infrastructure.functions))if(Array.isArray(s))i+=s.length;n.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:i,limit:1000,percentage:i/1000*100,warning:i>800})}if(e.infrastructure?.database?.dynamodb){let i=e.infrastructure.database.dynamodb.tables?.length||0;n.push({service:"DynamoDB",quotaName:"Tables",currentValue:i,limit:Pe.dynamodb.Tables,percentage:i/Pe.dynamodb.Tables*100,warning:i>Pe.dynamodb.Tables*0.8})}let r=n.filter((i)=>i.warning);if(r.length>0){he.warn("Service quota warnings detected:");for(let i of r)he.warn(` ${i.service} - ${i.quotaName}: ${i.currentValue}/${i.limit} (${i.percentage.toFixed(1)}%)`)}else he.verbose("All service quotas are within limits");return n}function ng(e){if(e.length===0)return"No quotas to check";let n=`Service Quota Usage:
2481
2481
 
2482
2482
  `,r=e.reduce((i,s)=>{if(!i[s.service])i[s.service]=[];return i[s.service].push(s),i},{});for(let[i,s]of Object.entries(r)){n+=`${i}:
2483
2483
  `;for(let a of s){let c=a.warning?"⚠":"✓";n+=` ${c} ${a.quotaName}: ${a.currentValue}/${a.limit} (${a.percentage.toFixed(1)}%)
2484
2484
  `}n+=`
2485
- `}return n}function eg(e){let n=[];for(let r of e)if(r.percentage>=100)n.push(`Request quota increase for ${r.service} - ${r.quotaName} (currently ${r.limit})`);else if(r.warning)n.push(`Consider requesting quota increase for ${r.service} - ${r.quotaName} (${r.percentage.toFixed(1)}% used)`);return n}import{createHash as Un}from"node:crypto";import{existsSync as Ye,mkdirSync as Gi,readdirSync as Wn,readFileSync as Vn,unlinkSync as We,writeFileSync as Wi}from"node:fs";import{join as Dt}from"node:path";class va{cacheDir;ttl;constructor(e,n={}){this.cacheDir=e,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!Ye(this.cacheDir))Gi(this.cacheDir,{recursive:!0})}getCachePath(e){let n=Un("sha256").update(e).digest("hex");return Dt(this.cacheDir,`${n}.json`)}get(e){let n=this.getCachePath(e);if(!Ye(n))return;try{let r=Vn(n,"utf-8"),i=JSON.parse(r);if(Date.now()-i.timestamp>this.ttl){We(n);return}return i.value}catch{We(n);return}}set(e,n,r){this.ensureCacheDir();let i=this.getCachePath(e),s={value:n,timestamp:Date.now(),hash:r};Wi(i,JSON.stringify(s),"utf-8")}has(e){return this.get(e)!==void 0}clear(){if(!Ye(this.cacheDir))return;let e=Wn(this.cacheDir);for(let n of e)We(Dt(this.cacheDir,n))}prune(){if(!Ye(this.cacheDir))return;let e=Wn(this.cacheDir),n=Date.now();for(let r of e){let i=Dt(this.cacheDir,r);try{let s=Vn(i,"utf-8"),a=JSON.parse(s);if(n-a.timestamp>this.ttl)We(i)}catch{We(i)}}}}class Ca{cache;constructor(e=Ue("cache","templates")){this.cache=new va(e,{ttl:86400000})}getTemplate(e){return this.cache.get(`template:${e}`)}setTemplate(e,n){let r=this.hashTemplate(n);this.cache.set(`template:${e}`,n,r)}hasChanged(e,n){let r=this.cache.get(`template:${e}`);if(!r)return!0;let i=this.hashTemplate(r),s=this.hashTemplate(n);return i!==s}hashTemplate(e){return Un("sha256").update(e).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Nt=null;function Au(){if(!Nt)Nt=new Ca;return Nt}import{createHash as xt}from"node:crypto";import{createReadStream as Vi,readdirSync as Ui,statSync as Ze}from"node:fs";import{join as Hi,relative as ji}from"node:path";async function dl(e,n={}){let r=n.algorithm||"sha256",i=n.chunkSize||65536;return new Promise((s,a)=>{let c=xt(r),u=Vi(e,{highWaterMark:i});u.on("data",(d)=>c.update(d)),u.on("end",()=>s(c.digest("hex"))),u.on("error",a)})}function ul(e,n="sha256"){return xt(n).update(e).digest("hex")}function tg(e,n="sha256"){return xt(n).update(e).digest("hex")}async function rg(e,n={}){let r=n.ignorePatterns||["node_modules",".git","dist","build",gn()],i=[];async function s(a){let c=Ui(a,{withFileTypes:!0});for(let u of c){let d=Hi(a,u.name),m=ji(e,d);if(r.some((p)=>m.includes(p)))continue;if(u.isDirectory())await s(d);else if(u.isFile()){let p=Ze(d),g=await dl(d,n);i.push({path:m,hash:g,size:p.size,mtime:p.mtimeMs})}}}return await s(e),i}function ng(e){let r=[...e].sort((i,s)=>i.path.localeCompare(s.path)).map((i)=>`${i.path}:${i.hash}`).join(`
2486
- `);return ul(r)}function ig(e){let n=Ze(e);return ul(`${e}:${n.size}:${n.mtimeMs}`)}function og(e,n){let r=new Map(e.map((u)=>[u.path,u])),i=new Map(n.map((u)=>[u.path,u])),s=[],a=[],c=[];for(let[u,d]of i){let m=r.get(u);if(!m)s.push(d);else if(m.hash!==d.hash)a.push(d)}for(let[u,d]of r)if(!i.has(u))c.push(d);return{added:s,modified:a,deleted:c}}class Ru{cache;constructor(){this.cache=new Map}get(e){let n=Ze(e),r=this.cache.get(e);if(r&&r.mtime===n.mtimeMs&&r.size===n.size)return r.hash;return}set(e,n){let r=Ze(e);this.cache.set(e,{hash:n,mtime:r.mtimeMs,size:r.size})}async getOrCompute(e,n={}){let r=this.get(e);if(r)return r;let i=await dl(e,n);return this.set(e,i),i}clear(){this.cache.clear()}}async function Ta(e,n={}){let r=n.concurrency||5,i=n.stopOnError??!0,s=[],a=[],c=Date.now(),u=[...e],d=[];async function m(y,h){try{let f=await y();s[h]=f}catch(f){let S=f instanceof Error?f:Error(String(f));if(a.push(S),i)throw u.length=0,S}}let p=0;while(u.length>0||d.length>0){while(d.length<r&&u.length>0){let y=u.shift(),h=p++,f=m(y,h);d.push(f)}if(d.length>0){await Promise.race(d);for(let y=d.length-1;y>=0;y--)if(await Promise.race([d[y].then(()=>!0),Promise.resolve(!1)]))d.splice(y,1)}if(i&&a.length>0)break}let g=Date.now()-c;return{results:s.filter((y)=>y!==void 0),errors:a,duration:g}}async function sg(e,n,r={}){let i=e.map((s)=>()=>n(s));return Ta(i,r)}async function ag(e,n,r=5){let i=e.map((a,c)=>()=>n(a,c)),s=await Ta(i,{concurrency:r,stopOnError:!1});if(s.errors.length>0)throw AggregateError(s.errors,"Parallel map failed");return s.results}async function cg(e,n={}){let r=n.retries||3,i=n.retryDelay||1000,s=e.map((a)=>async()=>{let c;for(let u=0;u<=r;u++)try{return await a()}catch(d){if(c=d instanceof Error?d:Error(String(d)),u<r)await Hn(i*(u+1))}throw c});return Ta(s,n)}async function lg(e){let n=[];for(let r of e){let i=await r();n.push(i)}return n}function Hn(e){return new Promise((n)=>setTimeout(n,e))}async function dg(e,n,r="Operation timed out"){return Promise.race([e(),new Promise((i,s)=>setTimeout(()=>s(Error(r)),n))])}class Iu{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(e=5,n=100){this.maxConcurrent=e;this.minInterval=n}async execute(e){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await e()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let e=Date.now()-this.lastExecution;if(e>=this.minInterval)return Promise.resolve();return Hn(this.minInterval-e)}return new Promise((e)=>this.queue.push(e))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function Pu(e,n){let r=[];for(let i=0;i<e.length;i+=n)r.push(e.slice(i,i+n));return r}async function ug(e,n,r){let i=Pu(e,n),s=[];for(let a of i){let c=await r(a);s.push(...c)}return s}function pg(e,n){let r=[],i=[],s=[],a=[],c=e.Resources||{},u=n.Resources||{},d=new Set(Object.keys(c)),m=new Set(Object.keys(u));for(let y of m)if(!d.has(y))r.push(y);for(let y of d)if(!m.has(y))s.push(y);for(let y of m)if(d.has(y)){let h=c[y],f=u[y];if(JSON.stringify(h)!==JSON.stringify(f))i.push(y);else a.push(y)}let p=JSON.stringify(e.Parameters||{})!==JSON.stringify(n.Parameters||{}),g=JSON.stringify(e.Outputs||{})!==JSON.stringify(n.Outputs||{});return{added:r,modified:i,deleted:s,unchanged:a,parametersChanged:p,outputsChanged:g,hasChanges:r.length>0||i.length>0||s.length>0||p||g}}function mg(e){let n=[];if(!e.hasChanges)return"No changes detected";if(e.added.length>0){n.push(`Added resources (${e.added.length}):`);for(let r of e.added)n.push(` + ${r}`)}if(e.modified.length>0){n.push(`Modified resources (${e.modified.length}):`);for(let r of e.modified)n.push(` ~ ${r}`)}if(e.deleted.length>0){n.push(`Deleted resources (${e.deleted.length}):`);for(let r of e.deleted)n.push(` - ${r}`)}if(e.parametersChanged)n.push("Parameters changed");if(e.outputsChanged)n.push("Outputs changed");return n.join(`
2487
- `)}function gg(e,n,r){if(e.deleted.length>0)return!0;for(let i of e.modified){let s=n.Resources[i],a=r.Resources[i];if(s.Type!==a.Type)return!0;let c=Ki(a.Type);for(let u of c){let d=s.Properties?.[u],m=a.Properties?.[u];if(JSON.stringify(d)!==JSON.stringify(m))return!0}}return!1}function Ki(e){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"]}[e]||[]}function fg(e){let n=[],r=[],i=[];n.push(...e.added);for(let s of e.modified)r.push(s);return i.push(...e.deleted),{safe:n,caution:r,dangerous:i}}function hg(e){if(!e.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(e.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(e.added.length>0&&e.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function yg(e){let n=e.added.length+e.modified.length+e.deleted.length+e.unchanged.length,r=e.added.length+e.modified.length+e.deleted.length,i=n>0?r/n*100:0;return{total:n,added:e.added.length,modified:e.modified.length,deleted:e.deleted.length,unchanged:e.unchanged.length,changePercentage:i}}var Du={$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 bg(e){let n=[];if(!e.project)n.push("Missing required field: project");else{if(!e.project.name)n.push("Missing required field: project.name");if(!e.project.slug)n.push("Missing required field: project.slug")}if(e.project?.slug&&!/^[a-z0-9-]+$/.test(e.project.slug))n.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let r=["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(e.project?.region&&!r.includes(e.project.region))n.push(`Invalid region: ${e.project.region}. Must be one of: ${r.join(", ")}`);if(e.mode&&!["server","serverless"].includes(e.mode))n.push("Invalid mode: must be one of server or serverless");return{valid:n.length===0,errors:n}}var pl={enabled:process.env.TS_CLOUD_LOCAL==="true"||!1,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 Ea(){return pl}function Sg(){return pl.enabled}function vg(e){let n=Ea();if(!n.enabled)return"";switch(e.toLowerCase()){case"dynamodb":return n.dynamodbEndpoint;case"s3":return n.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return n.localstackEndpoint;default:return n.localstackEndpoint}}function Cg(){let e=Ea();return{accessKeyId:e.awsAccessKeyId,secretAccessKey:e.awsSecretAccessKey,region:e.awsRegion}}function Tg(){let e=Ea();if(!e.enabled)return{};return{AWS_ACCESS_KEY_ID:e.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:e.awsSecretAccessKey,AWS_REGION:e.awsRegion,AWS_ENDPOINT_URL:e.localstackEndpoint,LOCALSTACK_ENDPOINT:e.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class ml{stacks=new Map;stackEvents=new Map;async createStack(e){let n=`arn:aws:cloudformation:${e.region||"us-east-1"}:123456789012:stack/${e.StackName}/${Date.now()}`;return this.stacks.set(e.StackName,{StackId:n,StackName:e.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:e.TemplateBody,Parameters:e.Parameters||[]}),this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let r=this.stacks.get(e.StackName);if(r)r.StackStatus="CREATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:n}}async updateStack(e){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);return n.StackStatus="UPDATE_IN_PROGRESS",n.TemplateBody=e.TemplateBody||n.TemplateBody,this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{n.StackStatus="UPDATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:n.StackId}}async deleteStack(e){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);n.StackStatus="DELETE_IN_PROGRESS",this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(e.StackName),this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(e){if(e.StackName){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);return{Stacks:[n]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(e){return{StackEvents:this.stackEvents.get(e.StackName)||[]}}addEvent(e,n){if(!this.stackEvents.has(e))this.stackEvents.set(e,[]);this.stackEvents.get(e).unshift(n)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class gl{buckets=new Map;async createBucket(e){return this.buckets.set(e.Bucket,new Map),{Location:`/${e.Bucket}`}}async deleteBucket(e){this.buckets.delete(e.Bucket)}async putObject(e){let n=this.buckets.get(e.Bucket);if(!n)n=new Map,this.buckets.set(e.Bucket,n);return n.set(e.Key,Buffer.from(e.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(e){let n=this.buckets.get(e.Bucket);if(!n)throw Error(`Bucket ${e.Bucket} does not exist`);let r=n.get(e.Key);if(!r)throw Error(`Object ${e.Key} does not exist`);return{Body:r,ContentLength:r.length}}async deleteObject(e){let n=this.buckets.get(e.Bucket);if(n)n.delete(e.Key)}async listObjects(e){let n=this.buckets.get(e.Bucket);if(!n)throw Error(`Bucket ${e.Bucket} does not exist`);return{Contents:Array.from(n.keys()).map((i)=>({Key:i,Size:n.get(i).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class fl{tables=new Map;data=new Map;async createTable(e){return this.tables.set(e.TableName,{TableName:e.TableName,KeySchema:e.KeySchema,AttributeDefinitions:e.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(e.TableName,new Map),{TableDescription:this.tables.get(e.TableName)}}async deleteTable(e){this.tables.delete(e.TableName),this.data.delete(e.TableName)}async putItem(e){let n=this.data.get(e.TableName);if(!n)n=new Map,this.data.set(e.TableName,n);let r=JSON.stringify(e.Item);n.set(r,e.Item)}async getItem(e){let n=this.data.get(e.TableName);if(!n)return{};let r=JSON.stringify(e.Key),i=n.get(r);return i?{Item:i}:{}}async deleteItem(e){let n=this.data.get(e.TableName);if(n){let r=JSON.stringify(e.Key);n.delete(r)}}async scan(e){let n=this.data.get(e.TableName);if(!n)return{Items:[]};return{Items:Array.from(n.values())}}reset(){this.tables.clear(),this.data.clear()}}function Eg(e){return{cloudformation:new ml,s3:new gl,dynamodb:new fl}}class wa{environments=new Map;async createPreviewEnvironment(e){let{branch:n,pr:r,commitSha:i,ttl:s=24,baseConfig:a,region:c="us-east-1"}=e,u=this.generatePreviewId(n,r,i),d=this.generatePreviewName(n,r),m=`preview-${d}`,p=new Date,g=new Date(p.getTime()+s*60*60*1000),y={id:u,name:d,branch:n,pr:r,commitSha:i,createdAt:p,expiresAt:g,status:"creating",stackName:m,region:c,resources:[]};this.environments.set(u,y);try{let h=this.createPreviewConfig(a,d);return y.status="active",y.url=`https://${d}.preview.example.com`,y}catch(h){throw y.status="failed",h}}async destroyPreviewEnvironment(e){let n=this.environments.get(e);if(!n)throw Error(`Preview environment ${e} not found`);n.status="destroying";try{n.status="destroyed",this.environments.delete(e)}catch(r){throw Error(`Failed to destroy preview environment: ${r}`)}}getPreviewEnvironment(e){return this.environments.get(e)}getPreviewEnvironmentByBranch(e){return Array.from(this.environments.values()).find((n)=>n.branch===e)}getPreviewEnvironmentByPR(e){return Array.from(this.environments.values()).find((n)=>n.pr===e)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((e)=>e.status==="active")}async cleanupExpiredEnvironments(e={}){let{maxAge:n,keepCount:r,dryRun:i=!1}=e,s=[],a=[],c=new Date,u=this.listPreviewEnvironments().sort((d,m)=>m.createdAt.getTime()-d.createdAt.getTime());for(let d=0;d<u.length;d++){let m=u[d];if(m.status!=="active")continue;let p=!1;if(m.expiresAt<c)p=!0;if(n){if((c.getTime()-m.createdAt.getTime())/3600000>n)p=!0}if(r&&d>=r)p=!0;if(p)if(i)s.push(m.id);else try{await this.destroyPreviewEnvironment(m.id),s.push(m.id)}catch(g){a.push(m.id)}}return{destroyed:s,failed:a}}async updatePreviewEnvironment(e,n){let r=this.environments.get(e);if(!r)throw Error(`Preview environment ${e} not found`);r.commitSha=n,r.status="creating";try{return r.status="active",r}catch(i){throw r.status="failed",i}}async getPreviewEnvironmentsCost(){let e={},n=0;for(let r of this.environments.values())e[r.id]=0,n+=0;return{total:n,byEnvironment:e}}generatePreviewId(e,n,r){let i=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),s=r?.substring(0,7)||Date.now().toString();return n?`pr-${n}-${s}`:`${i}-${s}`}generatePreviewName(e,n){let r=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return n?`pr-${n}`:r}createPreviewConfig(e,n){return{...e,project:{...e.project,name:`${e.project.name} Preview (${n})`,slug:`${e.project.slug}-preview-${n}`}}}}var Nu=new wa;function ku(e={}){let{workflowName:n="Preview Environment",trigger:r="pull_request",branches:i=["main","develop"],awsRegion:s="us-east-1",awsRole:a,configFile:c="cloud.config.ts",ttl:u=24}=e;return`name: ${n}
2485
+ `}return n}function ig(e){let n=[];for(let r of e)if(r.percentage>=100)n.push(`Request quota increase for ${r.service} - ${r.quotaName} (currently ${r.limit})`);else if(r.warning)n.push(`Consider requesting quota increase for ${r.service} - ${r.quotaName} (${r.percentage.toFixed(1)}% used)`);return n}import{createHash as Un}from"node:crypto";import{existsSync as Ye,mkdirSync as wi,readdirSync as Wn,readFileSync as Vn,unlinkSync as We,writeFileSync as Di}from"node:fs";import{join as Dt}from"node:path";class wa{cacheDir;ttl;constructor(e,n={}){this.cacheDir=e,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!Ye(this.cacheDir))wi(this.cacheDir,{recursive:!0})}getCachePath(e){let n=Un("sha256").update(e).digest("hex");return Dt(this.cacheDir,`${n}.json`)}get(e){let n=this.getCachePath(e);if(!Ye(n))return;try{let r=Vn(n,"utf-8"),i=JSON.parse(r);if(Date.now()-i.timestamp>this.ttl){We(n);return}return i.value}catch{We(n);return}}set(e,n,r){this.ensureCacheDir();let i=this.getCachePath(e),s={value:n,timestamp:Date.now(),hash:r};Di(i,JSON.stringify(s),"utf-8")}has(e){return this.get(e)!==void 0}clear(){if(!Ye(this.cacheDir))return;let e=Wn(this.cacheDir);for(let n of e)We(Dt(this.cacheDir,n))}prune(){if(!Ye(this.cacheDir))return;let e=Wn(this.cacheDir),n=Date.now();for(let r of e){let i=Dt(this.cacheDir,r);try{let s=Vn(i,"utf-8"),a=JSON.parse(s);if(n-a.timestamp>this.ttl)We(i)}catch{We(i)}}}}class Aa{cache;constructor(e=Be("cache","templates")){this.cache=new wa(e,{ttl:86400000})}getTemplate(e){return this.cache.get(`template:${e}`)}setTemplate(e,n){let r=this.hashTemplate(n);this.cache.set(`template:${e}`,n,r)}hasChanged(e,n){let r=this.cache.get(`template:${e}`);if(!r)return!0;let i=this.hashTemplate(r),s=this.hashTemplate(n);return i!==s}hashTemplate(e){return Un("sha256").update(e).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Nt=null;function Du(){if(!Nt)Nt=new Aa;return Nt}import{createHash as xt}from"node:crypto";import{createReadStream as Gi,readdirSync as Wi,statSync as Ze}from"node:fs";import{join as Vi,relative as Hi}from"node:path";async function gl(e,n={}){let r=n.algorithm||"sha256",i=n.chunkSize||65536;return new Promise((s,a)=>{let c=xt(r),u=Gi(e,{highWaterMark:i});u.on("data",(d)=>c.update(d)),u.on("end",()=>s(c.digest("hex"))),u.on("error",a)})}function fl(e,n="sha256"){return xt(n).update(e).digest("hex")}function og(e,n="sha256"){return xt(n).update(e).digest("hex")}async function sg(e,n={}){let r=n.ignorePatterns||["node_modules",".git","dist","build",yn()],i=[];async function s(a){let c=Wi(a,{withFileTypes:!0});for(let u of c){let d=Vi(a,u.name),m=Hi(e,d);if(r.some((p)=>m.includes(p)))continue;if(u.isDirectory())await s(d);else if(u.isFile()){let p=Ze(d),g=await gl(d,n);i.push({path:m,hash:g,size:p.size,mtime:p.mtimeMs})}}}return await s(e),i}function ag(e){let r=[...e].sort((i,s)=>i.path.localeCompare(s.path)).map((i)=>`${i.path}:${i.hash}`).join(`
2486
+ `);return fl(r)}function cg(e){let n=Ze(e);return fl(`${e}:${n.size}:${n.mtimeMs}`)}function lg(e,n){let r=new Map(e.map((u)=>[u.path,u])),i=new Map(n.map((u)=>[u.path,u])),s=[],a=[],c=[];for(let[u,d]of i){let m=r.get(u);if(!m)s.push(d);else if(m.hash!==d.hash)a.push(d)}for(let[u,d]of r)if(!i.has(u))c.push(d);return{added:s,modified:a,deleted:c}}class ku{cache;constructor(){this.cache=new Map}get(e){let n=Ze(e),r=this.cache.get(e);if(r&&r.mtime===n.mtimeMs&&r.size===n.size)return r.hash;return}set(e,n){let r=Ze(e);this.cache.set(e,{hash:n,mtime:r.mtimeMs,size:r.size})}async getOrCompute(e,n={}){let r=this.get(e);if(r)return r;let i=await gl(e,n);return this.set(e,i),i}clear(){this.cache.clear()}}async function Ra(e,n={}){let r=n.concurrency||5,i=n.stopOnError??!0,s=[],a=[],c=Date.now(),u=[...e],d=[];async function m(y,h){try{let f=await y();s[h]=f}catch(f){let S=f instanceof Error?f:Error(String(f));if(a.push(S),i)throw u.length=0,S}}let p=0;while(u.length>0||d.length>0){while(d.length<r&&u.length>0){let y=u.shift(),h=p++,f=m(y,h);d.push(f)}if(d.length>0){await Promise.race(d);for(let y=d.length-1;y>=0;y--)if(await Promise.race([d[y].then(()=>!0),Promise.resolve(!1)]))d.splice(y,1)}if(i&&a.length>0)break}let g=Date.now()-c;return{results:s.filter((y)=>y!==void 0),errors:a,duration:g}}async function dg(e,n,r={}){let i=e.map((s)=>()=>n(s));return Ra(i,r)}async function ug(e,n,r=5){let i=e.map((a,c)=>()=>n(a,c)),s=await Ra(i,{concurrency:r,stopOnError:!1});if(s.errors.length>0)throw AggregateError(s.errors,"Parallel map failed");return s.results}async function pg(e,n={}){let r=n.retries||3,i=n.retryDelay||1000,s=e.map((a)=>async()=>{let c;for(let u=0;u<=r;u++)try{return await a()}catch(d){if(c=d instanceof Error?d:Error(String(d)),u<r)await Hn(i*(u+1))}throw c});return Ra(s,n)}async function mg(e){let n=[];for(let r of e){let i=await r();n.push(i)}return n}function Hn(e){return new Promise((n)=>setTimeout(n,e))}async function gg(e,n,r="Operation timed out"){return Promise.race([e(),new Promise((i,s)=>setTimeout(()=>s(Error(r)),n))])}class Nu{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(e=5,n=100){this.maxConcurrent=e;this.minInterval=n}async execute(e){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await e()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let e=Date.now()-this.lastExecution;if(e>=this.minInterval)return Promise.resolve();return Hn(this.minInterval-e)}return new Promise((e)=>this.queue.push(e))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function xu(e,n){let r=[];for(let i=0;i<e.length;i+=n)r.push(e.slice(i,i+n));return r}async function fg(e,n,r){let i=xu(e,n),s=[];for(let a of i){let c=await r(a);s.push(...c)}return s}function hg(e,n){let r=[],i=[],s=[],a=[],c=e.Resources||{},u=n.Resources||{},d=new Set(Object.keys(c)),m=new Set(Object.keys(u));for(let y of m)if(!d.has(y))r.push(y);for(let y of d)if(!m.has(y))s.push(y);for(let y of m)if(d.has(y)){let h=c[y],f=u[y];if(JSON.stringify(h)!==JSON.stringify(f))i.push(y);else a.push(y)}let p=JSON.stringify(e.Parameters||{})!==JSON.stringify(n.Parameters||{}),g=JSON.stringify(e.Outputs||{})!==JSON.stringify(n.Outputs||{});return{added:r,modified:i,deleted:s,unchanged:a,parametersChanged:p,outputsChanged:g,hasChanges:r.length>0||i.length>0||s.length>0||p||g}}function yg(e){let n=[];if(!e.hasChanges)return"No changes detected";if(e.added.length>0){n.push(`Added resources (${e.added.length}):`);for(let r of e.added)n.push(` + ${r}`)}if(e.modified.length>0){n.push(`Modified resources (${e.modified.length}):`);for(let r of e.modified)n.push(` ~ ${r}`)}if(e.deleted.length>0){n.push(`Deleted resources (${e.deleted.length}):`);for(let r of e.deleted)n.push(` - ${r}`)}if(e.parametersChanged)n.push("Parameters changed");if(e.outputsChanged)n.push("Outputs changed");return n.join(`
2487
+ `)}function bg(e,n,r){if(e.deleted.length>0)return!0;for(let i of e.modified){let s=n.Resources[i],a=r.Resources[i];if(s.Type!==a.Type)return!0;let c=Ki(a.Type);for(let u of c){let d=s.Properties?.[u],m=a.Properties?.[u];if(JSON.stringify(d)!==JSON.stringify(m))return!0}}return!1}function Ki(e){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"]}[e]||[]}function Sg(e){let n=[],r=[],i=[];n.push(...e.added);for(let s of e.modified)r.push(s);return i.push(...e.deleted),{safe:n,caution:r,dangerous:i}}function vg(e){if(!e.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(e.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(e.added.length>0&&e.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function Cg(e){let n=e.added.length+e.modified.length+e.deleted.length+e.unchanged.length,r=e.added.length+e.modified.length+e.deleted.length,i=n>0?r/n*100:0;return{total:n,added:e.added.length,modified:e.modified.length,deleted:e.deleted.length,unchanged:e.unchanged.length,changePercentage:i}}var _u={$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 Tg(e){let n=[];if(!e.project)n.push("Missing required field: project");else{if(!e.project.name)n.push("Missing required field: project.name");if(!e.project.slug)n.push("Missing required field: project.slug")}if(e.project?.slug&&!/^[a-z0-9-]+$/.test(e.project.slug))n.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let r=["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(e.project?.region&&!r.includes(e.project.region))n.push(`Invalid region: ${e.project.region}. Must be one of: ${r.join(", ")}`);if(e.mode&&!["server","serverless"].includes(e.mode))n.push("Invalid mode: must be one of server or serverless");return{valid:n.length===0,errors:n}}var hl={enabled:process.env.TS_CLOUD_LOCAL==="true"||!1,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 Ia(){return hl}function Eg(){return hl.enabled}function wg(e){let n=Ia();if(!n.enabled)return"";switch(e.toLowerCase()){case"dynamodb":return n.dynamodbEndpoint;case"s3":return n.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return n.localstackEndpoint;default:return n.localstackEndpoint}}function Ag(){let e=Ia();return{accessKeyId:e.awsAccessKeyId,secretAccessKey:e.awsSecretAccessKey,region:e.awsRegion}}function Rg(){let e=Ia();if(!e.enabled)return{};return{AWS_ACCESS_KEY_ID:e.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:e.awsSecretAccessKey,AWS_REGION:e.awsRegion,AWS_ENDPOINT_URL:e.localstackEndpoint,LOCALSTACK_ENDPOINT:e.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class yl{stacks=new Map;stackEvents=new Map;async createStack(e){let n=`arn:aws:cloudformation:${e.region||"us-east-1"}:123456789012:stack/${e.StackName}/${Date.now()}`;return this.stacks.set(e.StackName,{StackId:n,StackName:e.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:e.TemplateBody,Parameters:e.Parameters||[]}),this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let r=this.stacks.get(e.StackName);if(r)r.StackStatus="CREATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:n}}async updateStack(e){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);return n.StackStatus="UPDATE_IN_PROGRESS",n.TemplateBody=e.TemplateBody||n.TemplateBody,this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{n.StackStatus="UPDATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:n.StackId}}async deleteStack(e){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);n.StackStatus="DELETE_IN_PROGRESS",this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(e.StackName),this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(e){if(e.StackName){let n=this.stacks.get(e.StackName);if(!n)throw Error(`Stack ${e.StackName} does not exist`);return{Stacks:[n]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(e){return{StackEvents:this.stackEvents.get(e.StackName)||[]}}addEvent(e,n){if(!this.stackEvents.has(e))this.stackEvents.set(e,[]);this.stackEvents.get(e).unshift(n)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class bl{buckets=new Map;async createBucket(e){return this.buckets.set(e.Bucket,new Map),{Location:`/${e.Bucket}`}}async deleteBucket(e){this.buckets.delete(e.Bucket)}async putObject(e){let n=this.buckets.get(e.Bucket);if(!n)n=new Map,this.buckets.set(e.Bucket,n);return n.set(e.Key,Buffer.from(e.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(e){let n=this.buckets.get(e.Bucket);if(!n)throw Error(`Bucket ${e.Bucket} does not exist`);let r=n.get(e.Key);if(!r)throw Error(`Object ${e.Key} does not exist`);return{Body:r,ContentLength:r.length}}async deleteObject(e){let n=this.buckets.get(e.Bucket);if(n)n.delete(e.Key)}async listObjects(e){let n=this.buckets.get(e.Bucket);if(!n)throw Error(`Bucket ${e.Bucket} does not exist`);return{Contents:Array.from(n.keys()).map((i)=>({Key:i,Size:n.get(i).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Sl{tables=new Map;data=new Map;async createTable(e){return this.tables.set(e.TableName,{TableName:e.TableName,KeySchema:e.KeySchema,AttributeDefinitions:e.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(e.TableName,new Map),{TableDescription:this.tables.get(e.TableName)}}async deleteTable(e){this.tables.delete(e.TableName),this.data.delete(e.TableName)}async putItem(e){let n=this.data.get(e.TableName);if(!n)n=new Map,this.data.set(e.TableName,n);let r=JSON.stringify(e.Item);n.set(r,e.Item)}async getItem(e){let n=this.data.get(e.TableName);if(!n)return{};let r=JSON.stringify(e.Key),i=n.get(r);return i?{Item:i}:{}}async deleteItem(e){let n=this.data.get(e.TableName);if(n){let r=JSON.stringify(e.Key);n.delete(r)}}async scan(e){let n=this.data.get(e.TableName);if(!n)return{Items:[]};return{Items:Array.from(n.values())}}reset(){this.tables.clear(),this.data.clear()}}function Ig(e){return{cloudformation:new yl,s3:new bl,dynamodb:new Sl}}class Pa{environments=new Map;async createPreviewEnvironment(e){let{branch:n,pr:r,commitSha:i,ttl:s=24,baseConfig:a,region:c="us-east-1"}=e,u=this.generatePreviewId(n,r,i),d=this.generatePreviewName(n,r),m=`preview-${d}`,p=new Date,g=new Date(p.getTime()+s*60*60*1000),y={id:u,name:d,branch:n,pr:r,commitSha:i,createdAt:p,expiresAt:g,status:"creating",stackName:m,region:c,resources:[]};this.environments.set(u,y);try{let h=this.createPreviewConfig(a,d);return y.status="active",y.url=`https://${d}.preview.example.com`,y}catch(h){throw y.status="failed",h}}async destroyPreviewEnvironment(e){let n=this.environments.get(e);if(!n)throw Error(`Preview environment ${e} not found`);n.status="destroying";try{n.status="destroyed",this.environments.delete(e)}catch(r){throw Error(`Failed to destroy preview environment: ${r}`)}}getPreviewEnvironment(e){return this.environments.get(e)}getPreviewEnvironmentByBranch(e){return Array.from(this.environments.values()).find((n)=>n.branch===e)}getPreviewEnvironmentByPR(e){return Array.from(this.environments.values()).find((n)=>n.pr===e)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((e)=>e.status==="active")}async cleanupExpiredEnvironments(e={}){let{maxAge:n,keepCount:r,dryRun:i=!1}=e,s=[],a=[],c=new Date,u=this.listPreviewEnvironments().sort((d,m)=>m.createdAt.getTime()-d.createdAt.getTime());for(let d=0;d<u.length;d++){let m=u[d];if(m.status!=="active")continue;let p=!1;if(m.expiresAt<c)p=!0;if(n){if((c.getTime()-m.createdAt.getTime())/3600000>n)p=!0}if(r&&d>=r)p=!0;if(p)if(i)s.push(m.id);else try{await this.destroyPreviewEnvironment(m.id),s.push(m.id)}catch(g){a.push(m.id)}}return{destroyed:s,failed:a}}async updatePreviewEnvironment(e,n){let r=this.environments.get(e);if(!r)throw Error(`Preview environment ${e} not found`);r.commitSha=n,r.status="creating";try{return r.status="active",r}catch(i){throw r.status="failed",i}}async getPreviewEnvironmentsCost(){let e={},n=0;for(let r of this.environments.values())e[r.id]=0,n+=0;return{total:n,byEnvironment:e}}generatePreviewId(e,n,r){let i=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),s=r?.substring(0,7)||Date.now().toString();return n?`pr-${n}-${s}`:`${i}-${s}`}generatePreviewName(e,n){let r=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return n?`pr-${n}`:r}createPreviewConfig(e,n){return{...e,project:{...e.project,name:`${e.project.name} Preview (${n})`,slug:`${e.project.slug}-preview-${n}`}}}}var Ou=new Pa;function $u(e={}){let{workflowName:n="Preview Environment",trigger:r="pull_request",branches:i=["main","develop"],awsRegion:s="us-east-1",awsRole:a,configFile:c="cloud.config.ts",ttl:u=24}=e;return`name: ${n}
2488
2488
 
2489
2489
  on:
2490
2490
  ${r}:
@@ -2618,7 +2618,7 @@ jobs:
2618
2618
  run: |
2619
2619
  # Clean up environments older than TTL
2620
2620
  bun run cloud env:cleanup --max-age=\${{ env.TTL_HOURS }}
2621
- `}function xu(e={}){let{schedule:n="0 0 * * *",maxAge:r=48,keepCount:i=10}=e;return`name: Cleanup Stale Preview Environments
2621
+ `}function Lu(e={}){let{schedule:n="0 0 * * *",maxAge:r=48,keepCount:i=10}=e;return`name: Cleanup Stale Preview Environments
2622
2622
 
2623
2623
  on:
2624
2624
  schedule:
@@ -2663,7 +2663,7 @@ jobs:
2663
2663
  - name: Report cleanup results
2664
2664
  run: |
2665
2665
  bun run cloud env:list --status=destroyed
2666
- `}function _u(e={}){let{schedule:n="0 8 * * 1",webhookUrl:r}=e;return`name: Preview Environment Cost Report
2666
+ `}function Mu(e={}){let{schedule:n="0 8 * * 1",webhookUrl:r}=e;return`name: Preview Environment Cost Report
2667
2667
 
2668
2668
  on:
2669
2669
  schedule:
@@ -2712,15 +2712,15 @@ jobs:
2712
2712
  curl -X POST -H 'Content-type: application/json' \\
2713
2713
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2714
2714
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2715
- `}class Aa{channels=[];addChannel(e){this.channels.push(e)}removeChannel(e){this.channels=this.channels.filter((n)=>n.type!==e)}async notify(e){let n=this.channels.map((r)=>this.sendToChannel(r,e));await Promise.allSettled(n)}async sendToChannel(e,n){switch(e.type){case"slack":await this.sendToSlack(e.config,n);break;case"discord":await this.sendToDiscord(e.config,n);break;case"email":await this.sendToEmail(e.config,n);break;case"webhook":await this.sendToWebhook(e.config,n);break}}async sendToSlack(e,n){let r=this.formatSlackMessage(n,e),i=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!i.ok)throw Error(`Failed to send Slack notification: ${i.statusText}`)}formatSlackMessage(e,n){let{environment:r,type:i}=e,s={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[i],a={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[i],c={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[i];return{username:n.username||"ts-cloud",icon_emoji:n.iconEmoji||":cloud:",channel:n.channel,attachments:[{color:a,title:`${s} ${c}`,fields:[{title:"Environment",value:r.name,short:!0},{title:"Branch",value:r.branch,short:!0},...r.pr?[{title:"PR",value:`#${r.pr}`,short:!0}]:[],{title:"Commit",value:r.commitSha.substring(0,7),short:!0},...r.url?[{title:"URL",value:r.url,short:!1}]:[],...i==="created"?[{title:"Expires",value:r.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(e.timestamp.getTime()/1000)}]}}async sendToDiscord(e,n){let r=this.formatDiscordMessage(n,e),i=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!i.ok)throw Error(`Failed to send Discord notification: ${i.statusText}`)}formatDiscordMessage(e,n){let{environment:r,type:i}=e,s={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[i],a={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[i],c={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[i];return{username:n.username||"ts-cloud",avatar_url:n.avatarUrl,embeds:[{title:`${s} ${c}`,color:a,fields:[{name:"Environment",value:r.name,inline:!0},{name:"Branch",value:r.branch,inline:!0},...r.pr?[{name:"PR",value:`#${r.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${r.commitSha.substring(0,7)}\``,inline:!0},...r.url?[{name:"URL",value:r.url,inline:!1}]:[]],timestamp:e.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(e,n){console.log(`Email notification would be sent to ${e.to.join(", ")}`)}async sendToWebhook(e,n){let r=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify({event:n.type,environment:n.environment,timestamp:n.timestamp.toISOString(),metadata:n.metadata})});if(!r.ok)throw Error(`Failed to send webhook notification: ${r.statusText}`)}}var Ou=new Aa;function wg(e){let{columns:n,data:r,border:i=!0,header:s=!0,compact:a=!1,maxWidth:c}=e;if(r.length===0)return"No data to display";let u=n.map((m)=>{let p=m.label.length,g=Math.max(...r.map((h)=>(m.formatter?m.formatter(h[m.key]):String(h[m.key]||"")).length)),y=m.width||Math.max(p,g);if(c&&y>c)y=c;return y}),d=[];if(i)d.push(kt(u,"top",a));if(s){if(d.push(jn(n.map((m)=>m.label),u,n.map((m)=>m.align||"left"),i)),i)d.push(kt(u,"middle",a))}for(let m of r){let p=n.map((g)=>{let y=g.formatter?g.formatter(m[g.key]):String(m[g.key]||"");return Qi(y,u[n.indexOf(g)])});d.push(jn(p,u,n.map((g)=>g.align||"left"),i))}if(i)d.push(kt(u,"bottom",a));return d.join(`
2716
- `)}function jn(e,n,r,i){let s=e.map((a,c)=>{let u=n[c],d=r[c];return zi(a,u,d)});if(i)return`│ ${s.join(" │ ")} │`;return s.join(" ")}function kt(e,n,r){let i=n==="top"?"┌":n==="middle"?"├":"└",s=n==="top"?"┐":n==="middle"?"┤":"┘",a=n==="top"?"┬":n==="middle"?"┼":"┴",c="─";if(r)return i+e.map((u)=>"─".repeat(u+2)).join(a)+s;return i+e.map((u)=>"─".repeat(u+2)).join(a)+s}function zi(e,n,r){let i=Kn(e).length;if(i>=n)return e;let s=n-i;switch(r){case"right":return" ".repeat(s)+e;case"center":{let a=Math.floor(s/2),c=s-a;return" ".repeat(a)+e+" ".repeat(c)}default:return e+" ".repeat(s)}}function Qi(e,n){if(Kn(e).length<=n)return e;return e.substring(0,n-1)+"…"}function Kn(e){return e.replace(/\x1B\[[0-9;]*m/g,"")}function Ag(e,n={}){let{indent:r=" ",showMetadata:i=!1}=n,s=[];function a(c,u,d){let p=u+(d?"└─ ":"├─ ")+c.label;if(s.push(p),i&&c.metadata){let g=u+(d?" ":"│ ");for(let[y,h]of Object.entries(c.metadata))s.push(`${g}${y}: ${h}`)}if(c.children&&c.children.length>0){let g=u+(d?" ":"│ ");c.children.forEach((y,h)=>{a(y,g,h===c.children.length-1)})}}return e.forEach((c,u)=>{a(c,"",u===e.length-1)}),s.join(`
2717
- `)}function Rg(e){let{total:n,current:r,width:i=40,format:s=":bar :percent :current/:total",complete:a="█",incomplete:c="░"}=e,u=Math.min(100,Math.max(0,r/n*100)),d=Math.floor(i*r/n),m=i-d,p=a.repeat(d)+c.repeat(m);return s.replace(":bar",p).replace(":percent",`${u.toFixed(0)}%`).replace(":current",String(r)).replace(":total",String(n))}function Ig(e,n=2){if(e===0)return"0 Bytes";let r=1024,i=n<0?0:n,s=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],a=Math.floor(Math.log(e)/Math.log(r));return`${Number.parseFloat((e/Math.pow(r,a)).toFixed(i))} ${s[a]}`}function Pg(e){if(e<1000)return`${e}ms`;let n=Math.floor(e/1000);if(n<60)return`${n}s`;let r=Math.floor(n/60),i=n%60;if(r<60)return i>0?`${r}m ${i}s`:`${r}m`;let s=Math.floor(r/60),a=r%60;if(s<24)return a>0?`${s}h ${a}m`:`${s}h`;let c=Math.floor(s/24),u=s%24;return u>0?`${c}d ${u}h`:`${c}d`}function Dg(e,n="•"){return e.map((r)=>`${n} ${r}`).join(`
2718
- `)}function Ng(e,n={}){let{indent:r="",separator:i=": "}=n,s=Math.max(...Object.keys(e).map((a)=>a.length));return Object.entries(e).map(([a,c])=>{let u=a.padEnd(s);return`${r}${u}${i}${c}`}).join(`
2719
- `)}class $u{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(e){this.total=e.total,this.current=e.current||0,this.width=e.width||40,this.format=e.format||":message :bar :percent :eta",this.message=e.message||"Progress",this.showETA=e.showETA!==!1,this.showPercentage=e.showPercentage!==!1,this.showCounter=e.showCounter!==!1}tick(e=1){this.current=Math.min(this.total,this.current+e),this.lastUpdate=Date.now()}update(e){this.current=Math.min(this.total,Math.max(0,e)),this.lastUpdate=Date.now()}setMessage(e){this.message=e}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let e=Date.now()-this.startTime,n=this.current/e,r=this.total-this.current;return Math.round(r/n)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let e=this.getETA();if(e<1000)return"< 1s";if(e<60000)return`${Math.round(e/1000)}s`;let n=Math.floor(e/60000);if(n<60)return`${n}m`;let r=Math.floor(n/60),i=n%60;if(r<24)return i>0?`${r}h ${i}m`:`${r}h`;let s=Math.floor(r/24),a=r%24;return a>0?`${s}d ${a}h`:`${s}d`}render(){let e=this.getPercentage(),n=Math.floor(this.width*this.current/this.total),r=this.width-n,i="█".repeat(n)+"░".repeat(r),s=`${e.toFixed(1)}%`,a=`${this.current}/${this.total}`,c=this.showETA?`ETA: ${this.getETAFormatted()}`:"",u=this.format.replace(":message",this.message).replace(":bar",i).replace(":percent",this.showPercentage?s:"").replace(":counter",this.showCounter?a:"").replace(":eta",c).replace(":current",String(this.current)).replace(":total",String(this.total));return u=u.replace(/\s+/g," ").trim(),u}isComplete(){return this.current>=this.total}}class Lu{steps;currentStepIndex=0;constructor(e){this.steps=e.map((n)=>({name:n,status:"pending"}))}startStep(e,n){if(e>=0&&e<this.steps.length)this.steps[e].status="active",this.steps[e].message=n,this.currentStepIndex=e}completeStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}failStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=e}skipStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}getStep(e){return this.steps[e]}getSteps(){return this.steps}render(){let e=[];for(let n of this.steps){let i=`${this.getStatusIcon(n.status)} ${n.name}`;if(n.message)i+=` - ${n.message}`;if(n.error)i+=`
2715
+ `}class Da{channels=[];addChannel(e){this.channels.push(e)}removeChannel(e){this.channels=this.channels.filter((n)=>n.type!==e)}async notify(e){let n=this.channels.map((r)=>this.sendToChannel(r,e));await Promise.allSettled(n)}async sendToChannel(e,n){switch(e.type){case"slack":await this.sendToSlack(e.config,n);break;case"discord":await this.sendToDiscord(e.config,n);break;case"email":await this.sendToEmail(e.config,n);break;case"webhook":await this.sendToWebhook(e.config,n);break}}async sendToSlack(e,n){let r=this.formatSlackMessage(n,e),i=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!i.ok)throw Error(`Failed to send Slack notification: ${i.statusText}`)}formatSlackMessage(e,n){let{environment:r,type:i}=e,s={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[i],a={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[i],c={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[i];return{username:n.username||"ts-cloud",icon_emoji:n.iconEmoji||":cloud:",channel:n.channel,attachments:[{color:a,title:`${s} ${c}`,fields:[{title:"Environment",value:r.name,short:!0},{title:"Branch",value:r.branch,short:!0},...r.pr?[{title:"PR",value:`#${r.pr}`,short:!0}]:[],{title:"Commit",value:r.commitSha.substring(0,7),short:!0},...r.url?[{title:"URL",value:r.url,short:!1}]:[],...i==="created"?[{title:"Expires",value:r.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(e.timestamp.getTime()/1000)}]}}async sendToDiscord(e,n){let r=this.formatDiscordMessage(n,e),i=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!i.ok)throw Error(`Failed to send Discord notification: ${i.statusText}`)}formatDiscordMessage(e,n){let{environment:r,type:i}=e,s={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[i],a={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[i],c={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[i];return{username:n.username||"ts-cloud",avatar_url:n.avatarUrl,embeds:[{title:`${s} ${c}`,color:a,fields:[{name:"Environment",value:r.name,inline:!0},{name:"Branch",value:r.branch,inline:!0},...r.pr?[{name:"PR",value:`#${r.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${r.commitSha.substring(0,7)}\``,inline:!0},...r.url?[{name:"URL",value:r.url,inline:!1}]:[]],timestamp:e.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(e,n){console.log(`Email notification would be sent to ${e.to.join(", ")}`)}async sendToWebhook(e,n){let r=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify({event:n.type,environment:n.environment,timestamp:n.timestamp.toISOString(),metadata:n.metadata})});if(!r.ok)throw Error(`Failed to send webhook notification: ${r.statusText}`)}}var Uu=new Da;function Pg(e){let{columns:n,data:r,border:i=!0,header:s=!0,compact:a=!1,maxWidth:c}=e;if(r.length===0)return"No data to display";let u=n.map((m)=>{let p=m.label.length,g=Math.max(...r.map((h)=>(m.formatter?m.formatter(h[m.key]):String(h[m.key]||"")).length)),y=m.width||Math.max(p,g);if(c&&y>c)y=c;return y}),d=[];if(i)d.push(kt(u,"top",a));if(s){if(d.push(jn(n.map((m)=>m.label),u,n.map((m)=>m.align||"left"),i)),i)d.push(kt(u,"middle",a))}for(let m of r){let p=n.map((g)=>{let y=g.formatter?g.formatter(m[g.key]):String(m[g.key]||"");return Qi(y,u[n.indexOf(g)])});d.push(jn(p,u,n.map((g)=>g.align||"left"),i))}if(i)d.push(kt(u,"bottom",a));return d.join(`
2716
+ `)}function jn(e,n,r,i){let s=e.map((a,c)=>{let u=n[c],d=r[c];return zi(a,u,d)});if(i)return`│ ${s.join(" │ ")} │`;return s.join(" ")}function kt(e,n,r){let i=n==="top"?"┌":n==="middle"?"├":"└",s=n==="top"?"┐":n==="middle"?"┤":"┘",a=n==="top"?"┬":n==="middle"?"┼":"┴",c="─";if(r)return i+e.map((u)=>"─".repeat(u+2)).join(a)+s;return i+e.map((u)=>"─".repeat(u+2)).join(a)+s}function zi(e,n,r){let i=Kn(e).length;if(i>=n)return e;let s=n-i;switch(r){case"right":return" ".repeat(s)+e;case"center":{let a=Math.floor(s/2),c=s-a;return" ".repeat(a)+e+" ".repeat(c)}default:return e+" ".repeat(s)}}function Qi(e,n){if(Kn(e).length<=n)return e;return e.substring(0,n-1)+"…"}function Kn(e){return e.replace(/\x1B\[[0-9;]*m/g,"")}function Dg(e,n={}){let{indent:r=" ",showMetadata:i=!1}=n,s=[];function a(c,u,d){let p=u+(d?"└─ ":"├─ ")+c.label;if(s.push(p),i&&c.metadata){let g=u+(d?" ":"│ ");for(let[y,h]of Object.entries(c.metadata))s.push(`${g}${y}: ${h}`)}if(c.children&&c.children.length>0){let g=u+(d?" ":"│ ");c.children.forEach((y,h)=>{a(y,g,h===c.children.length-1)})}}return e.forEach((c,u)=>{a(c,"",u===e.length-1)}),s.join(`
2717
+ `)}function kg(e){let{total:n,current:r,width:i=40,format:s=":bar :percent :current/:total",complete:a="█",incomplete:c="░"}=e,u=Math.min(100,Math.max(0,r/n*100)),d=Math.floor(i*r/n),m=i-d,p=a.repeat(d)+c.repeat(m);return s.replace(":bar",p).replace(":percent",`${u.toFixed(0)}%`).replace(":current",String(r)).replace(":total",String(n))}function Ng(e,n=2){if(e===0)return"0 Bytes";let r=1024,i=n<0?0:n,s=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],a=Math.floor(Math.log(e)/Math.log(r));return`${Number.parseFloat((e/Math.pow(r,a)).toFixed(i))} ${s[a]}`}function xg(e){if(e<1000)return`${e}ms`;let n=Math.floor(e/1000);if(n<60)return`${n}s`;let r=Math.floor(n/60),i=n%60;if(r<60)return i>0?`${r}m ${i}s`:`${r}m`;let s=Math.floor(r/60),a=r%60;if(s<24)return a>0?`${s}h ${a}m`:`${s}h`;let c=Math.floor(s/24),u=s%24;return u>0?`${c}d ${u}h`:`${c}d`}function _g(e,n="•"){return e.map((r)=>`${n} ${r}`).join(`
2718
+ `)}function Og(e,n={}){let{indent:r="",separator:i=": "}=n,s=Math.max(...Object.keys(e).map((a)=>a.length));return Object.entries(e).map(([a,c])=>{let u=a.padEnd(s);return`${r}${u}${i}${c}`}).join(`
2719
+ `)}class Bu{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(e){this.total=e.total,this.current=e.current||0,this.width=e.width||40,this.format=e.format||":message :bar :percent :eta",this.message=e.message||"Progress",this.showETA=e.showETA!==!1,this.showPercentage=e.showPercentage!==!1,this.showCounter=e.showCounter!==!1}tick(e=1){this.current=Math.min(this.total,this.current+e),this.lastUpdate=Date.now()}update(e){this.current=Math.min(this.total,Math.max(0,e)),this.lastUpdate=Date.now()}setMessage(e){this.message=e}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let e=Date.now()-this.startTime,n=this.current/e,r=this.total-this.current;return Math.round(r/n)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let e=this.getETA();if(e<1000)return"< 1s";if(e<60000)return`${Math.round(e/1000)}s`;let n=Math.floor(e/60000);if(n<60)return`${n}m`;let r=Math.floor(n/60),i=n%60;if(r<24)return i>0?`${r}h ${i}m`:`${r}h`;let s=Math.floor(r/24),a=r%24;return a>0?`${s}d ${a}h`:`${s}d`}render(){let e=this.getPercentage(),n=Math.floor(this.width*this.current/this.total),r=this.width-n,i="█".repeat(n)+"░".repeat(r),s=`${e.toFixed(1)}%`,a=`${this.current}/${this.total}`,c=this.showETA?`ETA: ${this.getETAFormatted()}`:"",u=this.format.replace(":message",this.message).replace(":bar",i).replace(":percent",this.showPercentage?s:"").replace(":counter",this.showCounter?a:"").replace(":eta",c).replace(":current",String(this.current)).replace(":total",String(this.total));return u=u.replace(/\s+/g," ").trim(),u}isComplete(){return this.current>=this.total}}class Fu{steps;currentStepIndex=0;constructor(e){this.steps=e.map((n)=>({name:n,status:"pending"}))}startStep(e,n){if(e>=0&&e<this.steps.length)this.steps[e].status="active",this.steps[e].message=n,this.currentStepIndex=e}completeStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}failStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=e}skipStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}getStep(e){return this.steps[e]}getSteps(){return this.steps}render(){let e=[];for(let n of this.steps){let i=`${this.getStatusIcon(n.status)} ${n.name}`;if(n.message)i+=` - ${n.message}`;if(n.error)i+=`
2720
2720
  Error: ${n.error}`;e.push(i)}return e.join(`
2721
- `)}getStatusIcon(e){switch(e){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((e)=>e.status==="completed"||e.status==="skipped")}hasFailed(){return this.steps.some((e)=>e.status==="failed")}}class Mu{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(e="Loading..."){this.message=e}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(e){this.message=e}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(e){return this.stop(),`✓ ${e||this.message}`}fail(e){return this.stop(),`✗ ${e||this.message}`}warn(e){return this.stop(),`⚠ ${e||this.message}`}info(e){return this.stop(),`ℹ ${e||this.message}`}}class Uu{tasks=[];add(e){return this.tasks.push({title:e,status:"pending"}),this.tasks.length-1}start(e){if(e>=0&&e<this.tasks.length)this.tasks[e].status="running"}complete(e,n){if(e>=0&&e<this.tasks.length)this.tasks[e].status="completed",this.tasks[e].output=n}fail(e,n){if(e>=0&&e<this.tasks.length)this.tasks[e].status="failed",this.tasks[e].output=n}render(){let e=[];for(let n of this.tasks){let i=`${this.getStatusIcon(n.status)} ${n.title}`;if(n.output)i+=`
2721
+ `)}getStatusIcon(e){switch(e){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((e)=>e.status==="completed"||e.status==="skipped")}hasFailed(){return this.steps.some((e)=>e.status==="failed")}}class ju{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(e="Loading..."){this.message=e}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(e){this.message=e}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(e){return this.stop(),`✓ ${e||this.message}`}fail(e){return this.stop(),`✗ ${e||this.message}`}warn(e){return this.stop(),`⚠ ${e||this.message}`}info(e){return this.stop(),`ℹ ${e||this.message}`}}class Vu{tasks=[];add(e){return this.tasks.push({title:e,status:"pending"}),this.tasks.length-1}start(e){if(e>=0&&e<this.tasks.length)this.tasks[e].status="running"}complete(e,n){if(e>=0&&e<this.tasks.length)this.tasks[e].status="completed",this.tasks[e].output=n}fail(e,n){if(e>=0&&e<this.tasks.length)this.tasks[e].status="failed",this.tasks[e].output=n}render(){let e=[];for(let n of this.tasks){let i=`${this.getStatusIcon(n.status)} ${n.title}`;if(n.output)i+=`
2722
2722
  ${n.output}`;e.push(i)}return e.join(`
2723
- `)}getStatusIcon(e){switch(e){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Ji(e,n){let r=[];for(let i=0;i<=n.length;i++)r[i]=[i];for(let i=0;i<=e.length;i++)r[0][i]=i;for(let i=1;i<=n.length;i++)for(let s=1;s<=e.length;s++)if(n.charAt(i-1)===e.charAt(s-1))r[i][s]=r[i-1][s-1];else r[i][s]=Math.min(r[i-1][s-1]+1,r[i][s-1]+1,r[i-1][s]+1);return r[n.length][e.length]}function Yi(e,n){let r=Ji(e.toLowerCase(),n.toLowerCase()),i=Math.max(e.length,n.length);if(i===0)return 1;return 1-r/i}function hl(e,n,r=0.5){return n.map((s)=>({command:s,score:Yi(e,s)})).filter((s)=>s.score>=r).sort((s,a)=>a.score-s.score).map((s)=>s.command).slice(0,5)}function kg(e,n){if(n.length===0)return`Unknown command: '${e}'
2723
+ `)}getStatusIcon(e){switch(e){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Ji(e,n){let r=[];for(let i=0;i<=n.length;i++)r[i]=[i];for(let i=0;i<=e.length;i++)r[0][i]=i;for(let i=1;i<=n.length;i++)for(let s=1;s<=e.length;s++)if(n.charAt(i-1)===e.charAt(s-1))r[i][s]=r[i-1][s-1];else r[i][s]=Math.min(r[i-1][s-1]+1,r[i][s-1]+1,r[i-1][s]+1);return r[n.length][e.length]}function Yi(e,n){let r=Ji(e.toLowerCase(),n.toLowerCase()),i=Math.max(e.length,n.length);if(i===0)return 1;return 1-r/i}function vl(e,n,r=0.5){return n.map((s)=>({command:s,score:Yi(e,s)})).filter((s)=>s.score>=r).sort((s,a)=>a.score-s.score).map((s)=>s.command).slice(0,5)}function $g(e,n){if(n.length===0)return`Unknown command: '${e}'
2724
2724
 
2725
2725
  Run 'ts-cloud --help' to see available commands.`;if(n.length===1)return`Unknown command: '${e}'
2726
2726
 
@@ -2728,17 +2728,17 @@ Did you mean: ${n[0]}?`;return`Unknown command: '${e}'
2728
2728
 
2729
2729
  Did you mean one of these?
2730
2730
  ${n.map((r)=>` • ${r}`).join(`
2731
- `)}`}function xg(e,n){return hl(e,n,0.7).length>0}function _g(e,n){let r=n.find((a)=>a.commands.some((c)=>c.name===e||c.aliases?.includes(e)));if(!r)return"No contextual help available.";let i=[];i.push(`${r.name}`),i.push("─".repeat(r.name.length)),i.push(r.description),i.push(""),i.push("Related commands:");for(let a of r.commands)if(i.push(` ${a.name.padEnd(20)} ${a.description}`),a.aliases&&a.aliases.length>0)i.push(` Aliases: ${a.aliases.join(", ")}`);let s=r.commands.find((a)=>a.name===e||a.aliases?.includes(e));if(s?.examples&&s.examples.length>0){i.push(""),i.push("Examples:");for(let a of s.examples)i.push(` ${a}`)}return i.join(`
2732
- `)}function Og(e,n){let r=[],i=e.toLowerCase();for(let s of n)for(let a of s.commands){let c=a.name.toLowerCase().includes(i),u=a.description.toLowerCase().includes(i),d=a.aliases?.some((m)=>m.toLowerCase().includes(i));if(c||u||d)r.push({command:a,category:s.name})}return r}function $g(e,n,r=10){let i=e.toLowerCase(),s=n.filter((c)=>c.toLowerCase().startsWith(i)),a=n.filter((c)=>c.toLowerCase().includes(i)&&!c.toLowerCase().startsWith(i));return[...s,...a].slice(0,r)}function Lg(e,n){let r=e.toLowerCase();return n.filter((i)=>{let s=i.name.toLowerCase().includes(r),a=i.alias?.toLowerCase().includes(r);return s||a})}function Mg(e){if(e.length===0)return"No matching flags found.";let n=[];for(let r of e){let i=` --${r.name}`;if(r.alias)i+=`, -${r.alias}`;if(i=i.padEnd(30),i+=r.description,r.required)i+=" (required)";n.push(i)}return n.join(`
2733
- `)}function Ug(e){let n=[];if(n.push(`Usage: ts-cloud ${e.name}`),n.push(""),n.push(e.description),e.aliases&&e.aliases.length>0)n.push(""),n.push(`Aliases: ${e.aliases.join(", ")}`);if(e.examples&&e.examples.length>0){n.push(""),n.push("Examples:");for(let r of e.examples)n.push(` ${r}`)}return n.join(`
2734
- `)}function Fg(e,n,r=[]){let i={valid:!0,errors:[],warnings:[],suggestions:[]},[s,...a]=e.split(" ");if(!n.includes(s)){i.valid=!1,i.errors.push(`Unknown command: ${s}`);let c=hl(s,n);if(c.length>0)i.suggestions.push(...c)}for(let c of r)if(!a.some((u)=>u===`--${c}`||u.startsWith(`--${c}=`)))i.valid=!1,i.errors.push(`Missing required flag: --${c}`);return i}class Fu{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(e){this.options={prompt:e.prompt||"> ",welcome:e.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...e}}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 e=await this.readInput();if(!e.trim())continue;this.addToHistory(e),await this.executeCommand(e)}catch(e){if(e instanceof Error)console.error(`Error: ${e.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((e)=>{process.stdout.write(this.options.prompt||"> "),e("")})}async executeCommand(e){let[n,...r]=this.parseCommand(e);if(n==="exit"||n==="quit"){this.stop();return}if(n==="help"){this.showHelp();return}if(n==="history"){this.showHistory();return}if(n==="clear"){console.clear();return}let i=this.findCommand(n);if(!i){console.error(`Unknown command: ${n}`),console.log('Type "help" to see available commands.');return}try{await i.handler(r)}catch(s){if(s instanceof Error)console.error(`Command failed: ${s.message}`)}}parseCommand(e){return e.trim().split(/\s+/)}findCommand(e){for(let[n,r]of this.options.commands)if(r.name===e||r.aliases?.includes(e))return r;return}showHelp(){console.log("Available commands:"),console.log("");let e=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 n of e){let r=` ${n.name.padEnd(20)} ${n.description}`;if(n.aliases&&n.aliases.length>0)r+=` (aliases: ${n.aliases.join(", ")})`;console.log(r)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((e,n)=>{console.log(` ${(n+1).toString().padStart(4)} ${e}`)})}addToHistory(e){if(this.history.commands[this.history.commands.length-1]===e)return;if(this.history.commands.push(e),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(e){let n=[],r=["help","history","clear","exit","quit"];for(let i of r)if(i.startsWith(e))n.push(i);for(let[i,s]of this.options.commands){if(s.name.startsWith(e))n.push(s.name);if(s.aliases){for(let a of s.aliases)if(a.startsWith(e))n.push(a)}}return n}async loadHistory(){if(!this.options.historyFile)return;try{let e=await import("node:fs/promises"),n=await e.readFile(this.options.historyFile,"utf-8");this.history.commands=n.split(`
2731
+ `)}`}function Lg(e,n){return vl(e,n,0.7).length>0}function Mg(e,n){let r=n.find((a)=>a.commands.some((c)=>c.name===e||c.aliases?.includes(e)));if(!r)return"No contextual help available.";let i=[];i.push(`${r.name}`),i.push("─".repeat(r.name.length)),i.push(r.description),i.push(""),i.push("Related commands:");for(let a of r.commands)if(i.push(` ${a.name.padEnd(20)} ${a.description}`),a.aliases&&a.aliases.length>0)i.push(` Aliases: ${a.aliases.join(", ")}`);let s=r.commands.find((a)=>a.name===e||a.aliases?.includes(e));if(s?.examples&&s.examples.length>0){i.push(""),i.push("Examples:");for(let a of s.examples)i.push(` ${a}`)}return i.join(`
2732
+ `)}function Ug(e,n){let r=[],i=e.toLowerCase();for(let s of n)for(let a of s.commands){let c=a.name.toLowerCase().includes(i),u=a.description.toLowerCase().includes(i),d=a.aliases?.some((m)=>m.toLowerCase().includes(i));if(c||u||d)r.push({command:a,category:s.name})}return r}function Bg(e,n,r=10){let i=e.toLowerCase(),s=n.filter((c)=>c.toLowerCase().startsWith(i)),a=n.filter((c)=>c.toLowerCase().includes(i)&&!c.toLowerCase().startsWith(i));return[...s,...a].slice(0,r)}function Fg(e,n){let r=e.toLowerCase();return n.filter((i)=>{let s=i.name.toLowerCase().includes(r),a=i.alias?.toLowerCase().includes(r);return s||a})}function jg(e){if(e.length===0)return"No matching flags found.";let n=[];for(let r of e){let i=` --${r.name}`;if(r.alias)i+=`, -${r.alias}`;if(i=i.padEnd(30),i+=r.description,r.required)i+=" (required)";n.push(i)}return n.join(`
2733
+ `)}function Vg(e){let n=[];if(n.push(`Usage: ts-cloud ${e.name}`),n.push(""),n.push(e.description),e.aliases&&e.aliases.length>0)n.push(""),n.push(`Aliases: ${e.aliases.join(", ")}`);if(e.examples&&e.examples.length>0){n.push(""),n.push("Examples:");for(let r of e.examples)n.push(` ${r}`)}return n.join(`
2734
+ `)}function zg(e,n,r=[]){let i={valid:!0,errors:[],warnings:[],suggestions:[]},[s,...a]=e.split(" ");if(!n.includes(s)){i.valid=!1,i.errors.push(`Unknown command: ${s}`);let c=vl(s,n);if(c.length>0)i.suggestions.push(...c)}for(let c of r)if(!a.some((u)=>u===`--${c}`||u.startsWith(`--${c}=`)))i.valid=!1,i.errors.push(`Missing required flag: --${c}`);return i}class zu{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(e){this.options={prompt:e.prompt||"> ",welcome:e.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...e}}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 e=await this.readInput();if(!e.trim())continue;this.addToHistory(e),await this.executeCommand(e)}catch(e){if(e instanceof Error)console.error(`Error: ${e.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((e)=>{process.stdout.write(this.options.prompt||"> "),e("")})}async executeCommand(e){let[n,...r]=this.parseCommand(e);if(n==="exit"||n==="quit"){this.stop();return}if(n==="help"){this.showHelp();return}if(n==="history"){this.showHistory();return}if(n==="clear"){console.clear();return}let i=this.findCommand(n);if(!i){console.error(`Unknown command: ${n}`),console.log('Type "help" to see available commands.');return}try{await i.handler(r)}catch(s){if(s instanceof Error)console.error(`Command failed: ${s.message}`)}}parseCommand(e){return e.trim().split(/\s+/)}findCommand(e){for(let[n,r]of this.options.commands)if(r.name===e||r.aliases?.includes(e))return r;return}showHelp(){console.log("Available commands:"),console.log("");let e=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 n of e){let r=` ${n.name.padEnd(20)} ${n.description}`;if(n.aliases&&n.aliases.length>0)r+=` (aliases: ${n.aliases.join(", ")})`;console.log(r)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((e,n)=>{console.log(` ${(n+1).toString().padStart(4)} ${e}`)})}addToHistory(e){if(this.history.commands[this.history.commands.length-1]===e)return;if(this.history.commands.push(e),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(e){let n=[],r=["help","history","clear","exit","quit"];for(let i of r)if(i.startsWith(e))n.push(i);for(let[i,s]of this.options.commands){if(s.name.startsWith(e))n.push(s.name);if(s.aliases){for(let a of s.aliases)if(a.startsWith(e))n.push(a)}}return n}async loadHistory(){if(!this.options.historyFile)return;try{let e=await import("node:fs/promises"),n=await e.readFile(this.options.historyFile,"utf-8");this.history.commands=n.split(`
2735
2735
  `).filter((r)=>r.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{let e=await import("node:fs/promises");await e.writeFile(this.options.historyFile,this.history.commands.join(`
2736
- `))}catch(e){console.error(`Failed to save history: ${e}`)}}searchHistory(e){return this.history.commands.filter((n)=>n.includes(e))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Bu{variables=new Map;workingDirectory=process.cwd();set(e,n){this.variables.set(e,n)}get(e){return this.variables.get(e)}has(e){return this.variables.has(e)}delete(e){this.variables.delete(e)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(e){this.workingDirectory=e}getWorkingDirectory(){return this.workingDirectory}}class ju{command={};name(e){return this.command.name=e,this}description(e){return this.command.description=e,this}aliases(...e){return this.command.aliases=e,this}handler(e){return this.command.handler=e,this}autocomplete(e){return this.command.autocomplete=e,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 Vu{entries=[];maxSize;persistFile;trackOutput;constructor(e={}){this.maxSize=e.maxSize||1000,this.persistFile=e.persistFile,this.trackOutput=e.trackOutput||!1}add(e){if(this.entries.push({...e,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(e=10){return this.entries.slice(-e)}search(e){let n=e.toLowerCase();return this.entries.filter((r)=>r.command.toLowerCase().includes(n))}searchByDate(e,n){return this.entries.filter((r)=>r.timestamp>=e&&r.timestamp<=n)}getSuccessful(){return this.entries.filter((e)=>e.success)}getFailed(){return this.entries.filter((e)=>!e.success)}getMostUsed(e=10){let n=new Map;for(let r of this.entries){let i=r.command.split(" ")[0];n.set(i,(n.get(i)||0)+1)}return Array.from(n.entries()).map(([r,i])=>({command:r,count:i})).sort((r,i)=>i.count-r.count).slice(0,e)}getStats(){let e=this.entries.length,n=this.entries.filter((u)=>u.success).length,r=this.entries.filter((u)=>!u.success).length,i=this.entries.filter((u)=>u.duration!==void 0),s=i.length>0?i.reduce((u,d)=>u+(d.duration||0),0)/i.length:0,a=this.getMostUsed(1),c=a.length>0?a[0].command:"N/A";return{total:e,successful:n,failed:r,averageDuration:s,mostUsed:c}}clear(){this.entries=[]}getByIndex(e){if(e<0||e>=this.entries.length)return;return this.entries[e]}removeByIndex(e){if(e>=0&&e<this.entries.length)this.entries.splice(e,1)}async save(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),n=JSON.stringify(this.entries,null,2);await e.writeFile(this.persistFile,n,"utf-8")}catch(e){throw Error(`Failed to save history: ${e}`)}}async load(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),n=await e.readFile(this.persistFile,"utf-8"),r=JSON.parse(n);this.entries=r.map((i)=>({...i,timestamp:new Date(i.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((r)=>[r.timestamp.toISOString(),`"${r.command.replace(/"/g,'""')}"`,r.success,r.duration||""].join(","))].join(`
2737
- `)}importJSON(e){let r=JSON.parse(e).map((i)=>({...i,timestamp:new Date(i.timestamp)}));if(this.entries.push(...r),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let e=new Map;for(let n of this.entries){let r=n.timestamp.toISOString().split("T")[0];if(!e.has(r))e.set(r,[]);e.get(r).push(n)}return e}groupByCommand(){let e=new Map;for(let n of this.entries){let r=n.command.split(" ")[0];if(!e.has(r))e.set(r,[]);e.get(r).push(n)}return e}replay(e){return this.getByIndex(e)?.command}getSuggestions(e,n=5){let r=e.toLowerCase(),i=this.entries.filter((s)=>s.command.toLowerCase().startsWith(r)).map((s)=>s.command);return[...new Set(i)].slice(0,n)}analyzePatterns(){let e=new Map,n=new Map;for(let i of this.entries){let s=i.timestamp.getHours(),a=i.timestamp.getDay();e.set(s,(e.get(s)||0)+1),n.set(a,(n.get(a)||0)+1)}let r=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:e,dayOfWeek:n,successRate:r}}}function Bg(e,n={}){let{maxWidth:r=100}=n;if(e.length===0)return"No command history";let i=[];for(let s=0;s<e.length;s++){let a=e[s],c=(s+1).toString().padStart(4),u=a.timestamp.toLocaleString(),d=a.success?"✓":"✗",m=a.command;if(m.length>r-30)m=m.substring(0,r-33)+"...";let p=`${c} ${u} ${d} ${m}`;if(a.duration)p+=` (${a.duration}ms)`;i.push(p)}return i.join(`
2738
- `)}function jg(e){let n=[];return n.push("Command History Statistics"),n.push("─".repeat(30)),n.push(`Total commands: ${e.total}`),n.push(`Successful: ${e.successful}`),n.push(`Failed: ${e.failed}`),n.push(`Success rate: ${(e.successful/e.total*100).toFixed(1)}%`),n.push(`Average duration: ${e.averageDuration.toFixed(0)}ms`),n.push(`Most used: ${e.mostUsed}`),n.join(`
2739
- `)}class yl{deployments=new Map;async deploy(e,n){let r=this.generateDeploymentId(),i={id:r,regions:n.regions.map((s)=>({region:s.code,stackName:this.getStackName(e,s.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(r,i);try{let s=n.regions.find((c)=>c.isPrimary)||n.regions[0];await this.deployToRegion(e,s,i);let a=n.regions.filter((c)=>c.code!==s.code);if(await Promise.all(a.map((c)=>this.deployToRegion(e,c,i))),n.globalResources)await this.deployGlobalResources(i,n);if(n.replication)await this.setupReplication(i,n);if(n.failover?.enabled)await this.setupFailover(i,n);return i.status="deployed",i.endTime=new Date,i}catch(s){throw i.status="failed",i.endTime=new Date,s}}async deployToRegion(e,n,r){let i=r.regions.find((s)=>s.region===n.code);if(!i)throw Error(`Region deployment not found: ${n.code}`);i.status="deploying",i.startTime=new Date;try{let s=this.createRegionConfig(e,n);await this.deployStack(i.stackName,s,n.code),i.status="deployed",i.endTime=new Date,i.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${i.stackName}/guid`,endpoint:`https://${i.stackName}.${n.code}.example.com`}}catch(s){throw i.status="failed",i.endTime=new Date,i.error=s instanceof Error?s.message:String(s),s}}async deployGlobalResources(e,n){let r={};if(n.globalResources?.route53)r.route53=await this.deployRoute53(e,n);if(n.globalResources?.cloudfront)r.cloudfront=await this.deployCloudFront(e,n);if(n.globalResources?.waf)r.waf=await this.deployWAF(e);e.globalResources=r}async deployRoute53(e,n){let r=[],i=[];for(let s of e.regions){if(s.status!=="deployed")continue;let a={id:`health-${s.region}`,endpoint:s.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:s.region};r.push(a);let c={name:"example.com",type:"A",region:s.region,setIdentifier:s.region,healthCheckId:a.id,resourceRecords:[s.outputs?.endpoint]};i.push(c)}return{healthChecks:r,recordSets:i,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(e,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:e.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let a=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:a?.weight||100}}),status:"Deployed"}}async deployWAF(e){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(e,n){if(n.replication?.s3)await this.setupS3Replication(e);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(e);if(n.replication?.secrets)await this.setupSecretsReplication(e)}async setupS3Replication(e){let n=e.regions.filter((r)=>r.status==="deployed");for(let r=0;r<n.length-1;r++){let i=n[r],s=n[r+1];console.log(`Setting up S3 replication: ${i.region} -> ${s.region}`)}}async setupDynamoDBReplication(e){let n=e.regions.filter((r)=>r.status==="deployed").map((r)=>r.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(e){let n=e.regions.filter((r)=>r.status==="deployed").map((r)=>r.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(e,n){let r=e.regions.find((s,a)=>n.regions[a]?.isPrimary)||e.regions[0],i=e.regions.filter((s)=>s.region!==r.region);console.log(`Setting up failover: primary=${r.region}, secondary=${i.map((s)=>s.region).join(", ")}`)}async destroy(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((r)=>this.destroyRegionStack(r))),this.deployments.delete(e)}catch(r){throw n.status="failed",r}}async destroyGlobalResources(e){if(e.waf)console.log("Destroying WAF resources");if(e.cloudfront)console.log("Destroying CloudFront distribution");if(e.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(e){if(e.status!=="deployed")return;e.status="rolling-back";try{console.log(`Destroying stack ${e.stackName} in ${e.region}`),e.status="pending"}catch(n){throw e.status="failed",e.error=n instanceof Error?n.message:String(n),n}}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getStackName(e,n){return`${e.project.slug}-${n}`}createRegionConfig(e,n){return{...e,infrastructure:{...e.infrastructure}}}async deployStack(e,n,r){console.log(`Deploying stack ${e} to ${r}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var Vg=new yl;class bl{references=[];exports=new Map;addExport(e){let n=`${e.region}:${e.exportName}`;if(!this.exports.has(e.region))this.exports.set(e.region,[]);this.exports.get(e.region).push(e)}getExport(e,n){let r=this.exports.get(e);if(!r)return;return r.find((s)=>s.exportName===n)?.value}createReference(e,n,r,i){let s=`/cross-region/${e}/${r}/${i}`;return this.references.push({sourceRegion:e,targetRegion:n,resourceType:r,resourceId:i,value:s}),s}async resolveReference(e,n){let r=this.references.find((i)=>i.targetRegion===e&&i.value===n);if(!r)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${r.sourceRegion}:123456789012:${r.resourceType}/${r.resourceId}`}getReferencesForRegion(e){return this.references.filter((n)=>n.sourceRegion===e||n.targetRegion===e)}clear(){this.references=[],this.exports.clear()}}class Sl{resources=new Map;register(e){this.resources.set(e.id,e)}get(e){return this.resources.get(e)}getByType(e){return Array.from(this.resources.values()).filter((n)=>n.type===e)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(e){this.resources.delete(e)}clear(){this.resources.clear()}}class vl{pairs=[];addPair(e){this.pairs.push(e)}getPairedRegion(e){let n=this.pairs.find((r)=>r.primary===e||r.secondary===e);if(!n)return;return n.primary===e?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((e)=>e.replicationConfig)}getFailoverPairs(){return this.pairs.filter((e)=>e.failoverConfig?.automatic)}arePaired(e,n){return this.pairs.some((r)=>r.primary===e&&r.secondary===n||r.primary===n&&r.secondary===e)}clear(){this.pairs=[]}}class Cl{dependencies=[];addDependency(e){this.dependencies.push(e)}getDependencies(e,n){return this.dependencies.filter((r)=>r.dependentStack===e&&r.dependentRegion===n)}getDependents(e,n){return this.dependencies.filter((r)=>r.dependsOnStack===e&&r.dependsOnRegion===n)}hasDependencies(e,n){return this.getDependencies(e,n).length>0}getDeploymentOrder(e){let n=new Set,r=[],i=(s)=>{let a=`${s.name}:${s.region}`;if(n.has(a))return;n.add(a);let c=this.getDependencies(s.name,s.region);for(let u of c)i({name:u.dependsOnStack,region:u.dependsOnRegion});r.push(s)};for(let s of e)i(s);return r}detectCircularDependencies(){let e=new Set,n=new Set,r=(i,s)=>{let a=`${i}:${s}`;if(n.has(a))return!0;if(e.has(a))return!1;e.add(a),n.add(a);let c=this.getDependencies(i,s);for(let u of c)if(r(u.dependsOnStack,u.dependsOnRegion))return!0;return n.delete(a),!1};for(let i of this.dependencies)if(r(i.dependentStack,i.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var zg=new bl,Hg=new Sl,Gg=new vl,qg=new Cl;var nt=[{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 Oi(e){return nt.find((n)=>n.code===e)}function Wg(){return nt}function Kg(e){let n=e.toLowerCase();return nt.filter((r)=>r.location.toLowerCase().includes(n))}function Jg(e){return nt.filter((n)=>n.compliance.includes(e))}function Xg(e){return nt.filter((n)=>n.pricing.tier===e)}function Qg(e){return nt.some((n)=>n.code===e)}function Yg(e){if(e.continent==="North America")return Oi("us-east-1");if(e.continent==="Europe")return Oi("eu-west-1");if(e.continent==="Asia")return Oi("ap-southeast-1");return Oi("us-east-1")}function Zg(e){let n=[...nt];if(e.compliance)n=n.filter((r)=>e.compliance.every((i)=>r.compliance.includes(i)));if(e.requiredServices)n=n.filter((r)=>e.requiredServices.every((i)=>r.services[i]));if(e.pricingSensitive)n.sort((r,i)=>r.pricing.multiplier-i.pricing.multiplier);return n.slice(0,5)}function ef(e){let n=Oi(e);if(!n)throw Error(`Invalid region: ${e}`);let r=[];for(let i of nt){if(i.code===e)continue;let s=Zi(n,i),a=Xi(n,i);r.push({primary:n,secondary:i,distance:s,sameContinent:a})}return r.sort((i,s)=>{if(i.sameContinent!==s.sameContinent)return i.sameContinent?1:-1;return i.distance-s.distance}),r.slice(0,3)}function Zi(e,n){let r={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},i=Ve(e.location),s=Ve(n.location);return Math.abs((r[i]||0)-(r[s]||0))}function Xi(e,n){return Ve(e.location)===Ve(n.location)}function Ve(e){if(e.includes("USA")||e.includes("Canada"))return"North America";if(e.includes("Europe")||e.includes("Ireland")||e.includes("Germany"))return"Europe";if(e.includes("Asia")||e.includes("Singapore")||e.includes("Japan"))return"Asia";if(e.includes("Brazil"))return"South America";if(e.includes("Australia"))return"Oceania";return"Unknown"}function zu(e){return`${e.name} (${e.code})`}function tf(e){return e.map((n)=>zu(n)).join(`
2740
- `)}function rf(){let e={total:nt.length,byContinent:{},byPricingTier:{}};for(let n of nt){let r=Ve(n.location);e.byContinent[r]=(e.byContinent[r]||0)+1,e.byPricingTier[n.pricing.tier]=(e.byPricingTier[n.pricing.tier]||0)+1}return e}class Tl{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(e){this.accounts.set(e.id,e)}getAccount(e){return this.accounts.get(e)}getAccountByAlias(e){return Array.from(this.accounts.values()).find((n)=>n.alias===e)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(e){return Array.from(this.accounts.values()).filter((n)=>n.role===e)}createCrossAccountRole(e,n,r,i,s){let a={roleArn:`arn:aws:iam::${n}:role/${r}`,roleName:r,sourceAccountId:e,targetAccountId:n,permissions:i,externalId:s?.externalId,sessionDuration:s?.sessionDuration||3600};return this.crossAccountRoles.push(a),a}getAssumeRolePolicyDocument(e,n){let r={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e}:root`},Action:"sts:AssumeRole"}]};if(n)r.Statement[0].Condition={StringEquals:{"sts:ExternalId":n}};return r}generateCrossAccountPolicy(e){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e,Resource:"*"}]}}mapEnvironmentToAccount(e,n,r){this.accountMappings.push({environment:e,accountId:n,region:r})}getAccountForEnvironment(e){return this.accountMappings.find((n)=>n.environment===e)}async assumeRole(e,n,r){return console.log(`Assuming role: ${e} with session: ${n}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(e){let n=this.accounts.get(e);if(!n)throw Error(`Account not found: ${e}`);if(n.assumeRoleArn){let r=await this.assumeRole(n.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(e){return this.crossAccountRoles.filter((n)=>n.sourceAccountId===e||n.targetAccountId===e)}async validateAccountAccess(e){try{let n=await this.getCredentialsForAccount(e);return console.log(`Validating access to account: ${e}`),!0}catch{return!1}}async getConsolidatedBilling(){let e={};for(let r of this.accounts.values())e[r.id]=Math.random()*1000;return{totalCost:Object.values(e).reduce((r,i)=>r+i,0),byAccount:e}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class El{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(e){this.organizationId=e}createOrganizationalUnit(e,n){let r={id:`ou-${Date.now()}`,name:e,parentId:n,accounts:[]};return this.organizationalUnits.set(r.id,r),r}getOrganizationalUnit(e){return this.organizationalUnits.get(e)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(e,n){let r=this.organizationalUnits.get(e);if(!r)throw Error(`Organizational unit not found: ${e}`);if(!r.accounts.includes(n))r.accounts.push(n)}removeAccountFromOU(e,n){let r=this.organizationalUnits.get(e);if(!r)throw Error(`Organizational unit not found: ${e}`);r.accounts=r.accounts.filter((i)=>i!==n)}getAccountsInOU(e){let n=this.organizationalUnits.get(e);if(!n)return[];return[...n.accounts]}applyServiceControlPolicy(e,n){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:e,policyDocument:n}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var nf=new Tl,of=new El;var Hu={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"}]}},sf={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"]}}}]}}},af={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 cf(e){return Hu[e]}function lf(e,n){return{Type:"AWS::IAM::Role",Properties:{RoleName:e.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e.sourceAccountId}:root`},Action:"sts:AssumeRole",...e.externalId&&{Condition:{StringEquals:{"sts:ExternalId":e.externalId}}}}]},Policies:[{PolicyName:`${e.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e.permissions,Resource:"*"}]}}],...n&&{ManagedPolicyArns:n},MaxSessionDuration:e.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:e.sourceAccountId}]}}}function df(e){let n=[],r=[],i=e.accounts.filter((d)=>d.role==="management");if(i.length===0)n.push("No management account defined");if(i.length>1)n.push("Multiple management accounts defined");let s=e.accounts.map((d)=>d.email),a=s.filter((d,m)=>s.indexOf(d)!==m);if(a.length>0)n.push(`Duplicate email addresses: ${a.join(", ")}`);let c=e.accounts.map((d)=>d.alias),u=c.filter((d,m)=>c.indexOf(d)!==m);if(u.length>0)n.push(`Duplicate aliases: ${u.join(", ")}`);if(!e.accounts.some((d)=>d.role==="security"))r.push("No dedicated security account - consider adding one for audit logs");if(e.accounts.length<3)r.push("Less than 3 accounts - consider separating environments");if(!e.accounts.some((d)=>d.role==="production"))r.push("No production account defined");return{valid:n.length===0,errors:n,warnings:r}}function uf(e){let n=[];if(n.push(`${e.name}`),n.push("─".repeat(e.name.length)),n.push(e.description),n.push(""),e.organizationalUnits){n.push("Organizational Units:");for(let r of e.organizationalUnits){let i=r.parent?" └─ ":" ";n.push(`${i}${r.name}`)}n.push("")}n.push("Accounts:");for(let r of e.accounts)n.push(` ${r.alias.padEnd(20)} ${r.role.padEnd(15)} ${r.email}`),n.push(` ${"".padEnd(20)} ${r.description}`),n.push("");return n.join(`
2741
- `)}function pf(e={}){let{workflowName:n="Deploy",trigger:r="push",branches:i=["main"],environments:s=["production"],awsRegion:a="us-east-1",awsRole:c,bunVersion:u="latest",deployCommand:d="bun run cloud deploy",testCommand:m="bun test",buildCommand:p="bun run build"}=e,g=!!c;return`name: ${n}
2736
+ `))}catch(e){console.error(`Failed to save history: ${e}`)}}searchHistory(e){return this.history.commands.filter((n)=>n.includes(e))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Hu{variables=new Map;workingDirectory=process.cwd();set(e,n){this.variables.set(e,n)}get(e){return this.variables.get(e)}has(e){return this.variables.has(e)}delete(e){this.variables.delete(e)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(e){this.workingDirectory=e}getWorkingDirectory(){return this.workingDirectory}}class Gu{command={};name(e){return this.command.name=e,this}description(e){return this.command.description=e,this}aliases(...e){return this.command.aliases=e,this}handler(e){return this.command.handler=e,this}autocomplete(e){return this.command.autocomplete=e,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 qu{entries=[];maxSize;persistFile;trackOutput;constructor(e={}){this.maxSize=e.maxSize||1000,this.persistFile=e.persistFile,this.trackOutput=e.trackOutput||!1}add(e){if(this.entries.push({...e,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(e=10){return this.entries.slice(-e)}search(e){let n=e.toLowerCase();return this.entries.filter((r)=>r.command.toLowerCase().includes(n))}searchByDate(e,n){return this.entries.filter((r)=>r.timestamp>=e&&r.timestamp<=n)}getSuccessful(){return this.entries.filter((e)=>e.success)}getFailed(){return this.entries.filter((e)=>!e.success)}getMostUsed(e=10){let n=new Map;for(let r of this.entries){let i=r.command.split(" ")[0];n.set(i,(n.get(i)||0)+1)}return Array.from(n.entries()).map(([r,i])=>({command:r,count:i})).sort((r,i)=>i.count-r.count).slice(0,e)}getStats(){let e=this.entries.length,n=this.entries.filter((u)=>u.success).length,r=this.entries.filter((u)=>!u.success).length,i=this.entries.filter((u)=>u.duration!==void 0),s=i.length>0?i.reduce((u,d)=>u+(d.duration||0),0)/i.length:0,a=this.getMostUsed(1),c=a.length>0?a[0].command:"N/A";return{total:e,successful:n,failed:r,averageDuration:s,mostUsed:c}}clear(){this.entries=[]}getByIndex(e){if(e<0||e>=this.entries.length)return;return this.entries[e]}removeByIndex(e){if(e>=0&&e<this.entries.length)this.entries.splice(e,1)}async save(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),n=JSON.stringify(this.entries,null,2);await e.writeFile(this.persistFile,n,"utf-8")}catch(e){throw Error(`Failed to save history: ${e}`)}}async load(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),n=await e.readFile(this.persistFile,"utf-8"),r=JSON.parse(n);this.entries=r.map((i)=>({...i,timestamp:new Date(i.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((r)=>[r.timestamp.toISOString(),`"${r.command.replace(/"/g,'""')}"`,r.success,r.duration||""].join(","))].join(`
2737
+ `)}importJSON(e){let r=JSON.parse(e).map((i)=>({...i,timestamp:new Date(i.timestamp)}));if(this.entries.push(...r),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let e=new Map;for(let n of this.entries){let r=n.timestamp.toISOString().split("T")[0];if(!e.has(r))e.set(r,[]);e.get(r).push(n)}return e}groupByCommand(){let e=new Map;for(let n of this.entries){let r=n.command.split(" ")[0];if(!e.has(r))e.set(r,[]);e.get(r).push(n)}return e}replay(e){return this.getByIndex(e)?.command}getSuggestions(e,n=5){let r=e.toLowerCase(),i=this.entries.filter((s)=>s.command.toLowerCase().startsWith(r)).map((s)=>s.command);return[...new Set(i)].slice(0,n)}analyzePatterns(){let e=new Map,n=new Map;for(let i of this.entries){let s=i.timestamp.getHours(),a=i.timestamp.getDay();e.set(s,(e.get(s)||0)+1),n.set(a,(n.get(a)||0)+1)}let r=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:e,dayOfWeek:n,successRate:r}}}function Hg(e,n={}){let{maxWidth:r=100}=n;if(e.length===0)return"No command history";let i=[];for(let s=0;s<e.length;s++){let a=e[s],c=(s+1).toString().padStart(4),u=a.timestamp.toLocaleString(),d=a.success?"✓":"✗",m=a.command;if(m.length>r-30)m=m.substring(0,r-33)+"...";let p=`${c} ${u} ${d} ${m}`;if(a.duration)p+=` (${a.duration}ms)`;i.push(p)}return i.join(`
2738
+ `)}function Gg(e){let n=[];return n.push("Command History Statistics"),n.push("─".repeat(30)),n.push(`Total commands: ${e.total}`),n.push(`Successful: ${e.successful}`),n.push(`Failed: ${e.failed}`),n.push(`Success rate: ${(e.successful/e.total*100).toFixed(1)}%`),n.push(`Average duration: ${e.averageDuration.toFixed(0)}ms`),n.push(`Most used: ${e.mostUsed}`),n.join(`
2739
+ `)}class Cl{deployments=new Map;async deploy(e,n){let r=this.generateDeploymentId(),i={id:r,regions:n.regions.map((s)=>({region:s.code,stackName:this.getStackName(e,s.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(r,i);try{let s=n.regions.find((c)=>c.isPrimary)||n.regions[0];await this.deployToRegion(e,s,i);let a=n.regions.filter((c)=>c.code!==s.code);if(await Promise.all(a.map((c)=>this.deployToRegion(e,c,i))),n.globalResources)await this.deployGlobalResources(i,n);if(n.replication)await this.setupReplication(i,n);if(n.failover?.enabled)await this.setupFailover(i,n);return i.status="deployed",i.endTime=new Date,i}catch(s){throw i.status="failed",i.endTime=new Date,s}}async deployToRegion(e,n,r){let i=r.regions.find((s)=>s.region===n.code);if(!i)throw Error(`Region deployment not found: ${n.code}`);i.status="deploying",i.startTime=new Date;try{let s=this.createRegionConfig(e,n);await this.deployStack(i.stackName,s,n.code),i.status="deployed",i.endTime=new Date,i.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${i.stackName}/guid`,endpoint:`https://${i.stackName}.${n.code}.example.com`}}catch(s){throw i.status="failed",i.endTime=new Date,i.error=s instanceof Error?s.message:String(s),s}}async deployGlobalResources(e,n){let r={};if(n.globalResources?.route53)r.route53=await this.deployRoute53(e,n);if(n.globalResources?.cloudfront)r.cloudfront=await this.deployCloudFront(e,n);if(n.globalResources?.waf)r.waf=await this.deployWAF(e);e.globalResources=r}async deployRoute53(e,n){let r=[],i=[];for(let s of e.regions){if(s.status!=="deployed")continue;let a={id:`health-${s.region}`,endpoint:s.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:s.region};r.push(a);let c={name:"example.com",type:"A",region:s.region,setIdentifier:s.region,healthCheckId:a.id,resourceRecords:[s.outputs?.endpoint]};i.push(c)}return{healthChecks:r,recordSets:i,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(e,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:e.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let a=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:a?.weight||100}}),status:"Deployed"}}async deployWAF(e){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(e,n){if(n.replication?.s3)await this.setupS3Replication(e);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(e);if(n.replication?.secrets)await this.setupSecretsReplication(e)}async setupS3Replication(e){let n=e.regions.filter((r)=>r.status==="deployed");for(let r=0;r<n.length-1;r++){let i=n[r],s=n[r+1];console.log(`Setting up S3 replication: ${i.region} -> ${s.region}`)}}async setupDynamoDBReplication(e){let n=e.regions.filter((r)=>r.status==="deployed").map((r)=>r.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(e){let n=e.regions.filter((r)=>r.status==="deployed").map((r)=>r.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(e,n){let r=e.regions.find((s,a)=>n.regions[a]?.isPrimary)||e.regions[0],i=e.regions.filter((s)=>s.region!==r.region);console.log(`Setting up failover: primary=${r.region}, secondary=${i.map((s)=>s.region).join(", ")}`)}async destroy(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((r)=>this.destroyRegionStack(r))),this.deployments.delete(e)}catch(r){throw n.status="failed",r}}async destroyGlobalResources(e){if(e.waf)console.log("Destroying WAF resources");if(e.cloudfront)console.log("Destroying CloudFront distribution");if(e.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(e){if(e.status!=="deployed")return;e.status="rolling-back";try{console.log(`Destroying stack ${e.stackName} in ${e.region}`),e.status="pending"}catch(n){throw e.status="failed",e.error=n instanceof Error?n.message:String(n),n}}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getStackName(e,n){return`${e.project.slug}-${n}`}createRegionConfig(e,n){return{...e,infrastructure:{...e.infrastructure}}}async deployStack(e,n,r){console.log(`Deploying stack ${e} to ${r}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var qg=new Cl;class Tl{references=[];exports=new Map;addExport(e){let n=`${e.region}:${e.exportName}`;if(!this.exports.has(e.region))this.exports.set(e.region,[]);this.exports.get(e.region).push(e)}getExport(e,n){let r=this.exports.get(e);if(!r)return;return r.find((s)=>s.exportName===n)?.value}createReference(e,n,r,i){let s=`/cross-region/${e}/${r}/${i}`;return this.references.push({sourceRegion:e,targetRegion:n,resourceType:r,resourceId:i,value:s}),s}async resolveReference(e,n){let r=this.references.find((i)=>i.targetRegion===e&&i.value===n);if(!r)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${r.sourceRegion}:123456789012:${r.resourceType}/${r.resourceId}`}getReferencesForRegion(e){return this.references.filter((n)=>n.sourceRegion===e||n.targetRegion===e)}clear(){this.references=[],this.exports.clear()}}class El{resources=new Map;register(e){this.resources.set(e.id,e)}get(e){return this.resources.get(e)}getByType(e){return Array.from(this.resources.values()).filter((n)=>n.type===e)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(e){this.resources.delete(e)}clear(){this.resources.clear()}}class wl{pairs=[];addPair(e){this.pairs.push(e)}getPairedRegion(e){let n=this.pairs.find((r)=>r.primary===e||r.secondary===e);if(!n)return;return n.primary===e?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((e)=>e.replicationConfig)}getFailoverPairs(){return this.pairs.filter((e)=>e.failoverConfig?.automatic)}arePaired(e,n){return this.pairs.some((r)=>r.primary===e&&r.secondary===n||r.primary===n&&r.secondary===e)}clear(){this.pairs=[]}}class Al{dependencies=[];addDependency(e){this.dependencies.push(e)}getDependencies(e,n){return this.dependencies.filter((r)=>r.dependentStack===e&&r.dependentRegion===n)}getDependents(e,n){return this.dependencies.filter((r)=>r.dependsOnStack===e&&r.dependsOnRegion===n)}hasDependencies(e,n){return this.getDependencies(e,n).length>0}getDeploymentOrder(e){let n=new Set,r=[],i=(s)=>{let a=`${s.name}:${s.region}`;if(n.has(a))return;n.add(a);let c=this.getDependencies(s.name,s.region);for(let u of c)i({name:u.dependsOnStack,region:u.dependsOnRegion});r.push(s)};for(let s of e)i(s);return r}detectCircularDependencies(){let e=new Set,n=new Set,r=(i,s)=>{let a=`${i}:${s}`;if(n.has(a))return!0;if(e.has(a))return!1;e.add(a),n.add(a);let c=this.getDependencies(i,s);for(let u of c)if(r(u.dependsOnStack,u.dependsOnRegion))return!0;return n.delete(a),!1};for(let i of this.dependencies)if(r(i.dependentStack,i.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var Wg=new Tl,Kg=new El,Jg=new wl,Xg=new Al;var nt=[{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 Ui(e){return nt.find((n)=>n.code===e)}function Qg(){return nt}function Yg(e){let n=e.toLowerCase();return nt.filter((r)=>r.location.toLowerCase().includes(n))}function Zg(e){return nt.filter((n)=>n.compliance.includes(e))}function ef(e){return nt.filter((n)=>n.pricing.tier===e)}function tf(e){return nt.some((n)=>n.code===e)}function rf(e){if(e.continent==="North America")return Ui("us-east-1");if(e.continent==="Europe")return Ui("eu-west-1");if(e.continent==="Asia")return Ui("ap-southeast-1");return Ui("us-east-1")}function nf(e){let n=[...nt];if(e.compliance)n=n.filter((r)=>e.compliance.every((i)=>r.compliance.includes(i)));if(e.requiredServices)n=n.filter((r)=>e.requiredServices.every((i)=>r.services[i]));if(e.pricingSensitive)n.sort((r,i)=>r.pricing.multiplier-i.pricing.multiplier);return n.slice(0,5)}function of(e){let n=Ui(e);if(!n)throw Error(`Invalid region: ${e}`);let r=[];for(let i of nt){if(i.code===e)continue;let s=Zi(n,i),a=Xi(n,i);r.push({primary:n,secondary:i,distance:s,sameContinent:a})}return r.sort((i,s)=>{if(i.sameContinent!==s.sameContinent)return i.sameContinent?1:-1;return i.distance-s.distance}),r.slice(0,3)}function Zi(e,n){let r={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},i=Ue(e.location),s=Ue(n.location);return Math.abs((r[i]||0)-(r[s]||0))}function Xi(e,n){return Ue(e.location)===Ue(n.location)}function Ue(e){if(e.includes("USA")||e.includes("Canada"))return"North America";if(e.includes("Europe")||e.includes("Ireland")||e.includes("Germany"))return"Europe";if(e.includes("Asia")||e.includes("Singapore")||e.includes("Japan"))return"Asia";if(e.includes("Brazil"))return"South America";if(e.includes("Australia"))return"Oceania";return"Unknown"}function Wu(e){return`${e.name} (${e.code})`}function sf(e){return e.map((n)=>Wu(n)).join(`
2740
+ `)}function af(){let e={total:nt.length,byContinent:{},byPricingTier:{}};for(let n of nt){let r=Ue(n.location);e.byContinent[r]=(e.byContinent[r]||0)+1,e.byPricingTier[n.pricing.tier]=(e.byPricingTier[n.pricing.tier]||0)+1}return e}class Rl{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(e){this.accounts.set(e.id,e)}getAccount(e){return this.accounts.get(e)}getAccountByAlias(e){return Array.from(this.accounts.values()).find((n)=>n.alias===e)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(e){return Array.from(this.accounts.values()).filter((n)=>n.role===e)}createCrossAccountRole(e,n,r,i,s){let a={roleArn:`arn:aws:iam::${n}:role/${r}`,roleName:r,sourceAccountId:e,targetAccountId:n,permissions:i,externalId:s?.externalId,sessionDuration:s?.sessionDuration||3600};return this.crossAccountRoles.push(a),a}getAssumeRolePolicyDocument(e,n){let r={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e}:root`},Action:"sts:AssumeRole"}]};if(n)r.Statement[0].Condition={StringEquals:{"sts:ExternalId":n}};return r}generateCrossAccountPolicy(e){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e,Resource:"*"}]}}mapEnvironmentToAccount(e,n,r){this.accountMappings.push({environment:e,accountId:n,region:r})}getAccountForEnvironment(e){return this.accountMappings.find((n)=>n.environment===e)}async assumeRole(e,n,r){return console.log(`Assuming role: ${e} with session: ${n}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(e){let n=this.accounts.get(e);if(!n)throw Error(`Account not found: ${e}`);if(n.assumeRoleArn){let r=await this.assumeRole(n.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey,sessionToken:r.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(e){return this.crossAccountRoles.filter((n)=>n.sourceAccountId===e||n.targetAccountId===e)}async validateAccountAccess(e){try{let n=await this.getCredentialsForAccount(e);return console.log(`Validating access to account: ${e}`),!0}catch{return!1}}async getConsolidatedBilling(){let e={};for(let r of this.accounts.values())e[r.id]=Math.random()*1000;return{totalCost:Object.values(e).reduce((r,i)=>r+i,0),byAccount:e}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Il{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(e){this.organizationId=e}createOrganizationalUnit(e,n){let r={id:`ou-${Date.now()}`,name:e,parentId:n,accounts:[]};return this.organizationalUnits.set(r.id,r),r}getOrganizationalUnit(e){return this.organizationalUnits.get(e)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(e,n){let r=this.organizationalUnits.get(e);if(!r)throw Error(`Organizational unit not found: ${e}`);if(!r.accounts.includes(n))r.accounts.push(n)}removeAccountFromOU(e,n){let r=this.organizationalUnits.get(e);if(!r)throw Error(`Organizational unit not found: ${e}`);r.accounts=r.accounts.filter((i)=>i!==n)}getAccountsInOU(e){let n=this.organizationalUnits.get(e);if(!n)return[];return[...n.accounts]}applyServiceControlPolicy(e,n){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:e,policyDocument:n}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var cf=new Rl,lf=new Il;var Ku={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"}]}},df={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"]}}}]}}},uf={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 pf(e){return Ku[e]}function mf(e,n){return{Type:"AWS::IAM::Role",Properties:{RoleName:e.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e.sourceAccountId}:root`},Action:"sts:AssumeRole",...e.externalId&&{Condition:{StringEquals:{"sts:ExternalId":e.externalId}}}}]},Policies:[{PolicyName:`${e.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e.permissions,Resource:"*"}]}}],...n&&{ManagedPolicyArns:n},MaxSessionDuration:e.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:e.sourceAccountId}]}}}function gf(e){let n=[],r=[],i=e.accounts.filter((d)=>d.role==="management");if(i.length===0)n.push("No management account defined");if(i.length>1)n.push("Multiple management accounts defined");let s=e.accounts.map((d)=>d.email),a=s.filter((d,m)=>s.indexOf(d)!==m);if(a.length>0)n.push(`Duplicate email addresses: ${a.join(", ")}`);let c=e.accounts.map((d)=>d.alias),u=c.filter((d,m)=>c.indexOf(d)!==m);if(u.length>0)n.push(`Duplicate aliases: ${u.join(", ")}`);if(!e.accounts.some((d)=>d.role==="security"))r.push("No dedicated security account - consider adding one for audit logs");if(e.accounts.length<3)r.push("Less than 3 accounts - consider separating environments");if(!e.accounts.some((d)=>d.role==="production"))r.push("No production account defined");return{valid:n.length===0,errors:n,warnings:r}}function ff(e){let n=[];if(n.push(`${e.name}`),n.push("─".repeat(e.name.length)),n.push(e.description),n.push(""),e.organizationalUnits){n.push("Organizational Units:");for(let r of e.organizationalUnits){let i=r.parent?" └─ ":" ";n.push(`${i}${r.name}`)}n.push("")}n.push("Accounts:");for(let r of e.accounts)n.push(` ${r.alias.padEnd(20)} ${r.role.padEnd(15)} ${r.email}`),n.push(` ${"".padEnd(20)} ${r.description}`),n.push("");return n.join(`
2741
+ `)}function hf(e={}){let{workflowName:n="Deploy",trigger:r="push",branches:i=["main"],environments:s=["production"],awsRegion:a="us-east-1",awsRole:c,bunVersion:u="latest",deployCommand:d="bun run cloud deploy",testCommand:m="bun test",buildCommand:p="bun run build"}=e,g=!!c;return`name: ${n}
2742
2742
 
2743
2743
  on:
2744
2744
  ${r}:
@@ -2807,7 +2807,7 @@ jobs:
2807
2807
 
2808
2808
  - name: Post-deployment tests
2809
2809
  run: bun run cloud test:smoke
2810
- `}function mf(e){let{environments:n,awsRegion:r="us-east-1",awsRole:i}=e,s=!!i;return`name: Multi-Environment Deploy
2810
+ `}function yf(e){let{environments:n,awsRegion:r="us-east-1",awsRole:i}=e,s=!!i;return`name: Multi-Environment Deploy
2811
2811
 
2812
2812
  on:
2813
2813
  push:
@@ -2863,7 +2863,7 @@ ${n.map((a,c)=>` ${c>0?"elif":"if"} [[ "\${{ github.ref }}" == "refs/he
2863
2863
 
2864
2864
  - name: Deploy
2865
2865
  run: bun run cloud deploy --env=\${{ needs.determine-environment.outputs.environment }}
2866
- `}function gf(e={}){let{awsRegion:n="us-east-1",awsRole:r,ttl:i=24}=e,s=!!r;return`name: PR Preview Environment
2866
+ `}function bf(e={}){let{awsRegion:n="us-east-1",awsRole:r,ttl:i=24}=e,s=!!r;return`name: PR Preview Environment
2867
2867
 
2868
2868
  on:
2869
2869
  pull_request:
@@ -2968,7 +2968,7 @@ jobs:
2968
2968
  bun run cloud env:preview --destroy \\
2969
2969
  --branch=\${{ github.head_ref }} \\
2970
2970
  --pr=\${{ github.event.pull_request.number }}
2971
- `}function ff(e){let{schedule:n,environment:r,awsRegion:i="us-east-1",awsRole:s}=e;return`name: Scheduled Deployment
2971
+ `}function Sf(e){let{schedule:n,environment:r,awsRegion:i="us-east-1",awsRole:s}=e;return`name: Scheduled Deployment
2972
2972
 
2973
2973
  on:
2974
2974
  schedule:
@@ -3010,7 +3010,7 @@ jobs:
3010
3010
 
3011
3011
  - name: Deploy
3012
3012
  run: bun run cloud deploy --env=\${{ env.ENVIRONMENT }}
3013
- `}function hf(e){let{matrix:n,awsRole:r}=e,i=!!r;return`name: Matrix Deployment
3013
+ `}function vf(e){let{matrix:n,awsRole:r}=e,i=!!r;return`name: Matrix Deployment
3014
3014
 
3015
3015
  on:
3016
3016
  workflow_dispatch:
@@ -3057,7 +3057,7 @@ ${n.map((s)=>` - environment: ${s.environment}
3057
3057
 
3058
3058
  - name: Deploy to \${{ matrix.environment }} (\${{ matrix.region }})
3059
3059
  run: bun run cloud deploy --env=\${{ matrix.environment }} --region=\${{ matrix.region }}
3060
- `}function yf(e={}){let{stages:n=["test","build","deploy"],environments:r=["production"],awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:a="bun run cloud deploy",testCommand:c="bun test",buildCommand:u="bun run build"}=e;return`stages:
3060
+ `}function Cf(e={}){let{stages:n=["test","build","deploy"],environments:r=["production"],awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:a="bun run cloud deploy",testCommand:c="bun test",buildCommand:u="bun run build"}=e;return`stages:
3061
3061
  ${n.map((d)=>` - ${d}`).join(`
3062
3062
  `)}
3063
3063
 
@@ -3105,7 +3105,7 @@ deploy:
3105
3105
  only:
3106
3106
  - main
3107
3107
  when: manual
3108
- `}function bf(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((s)=>`
3108
+ `}function Tf(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((s)=>`
3109
3109
  deploy:${s.name}:
3110
3110
  stage: deploy
3111
3111
  script:
@@ -3146,7 +3146,7 @@ build:
3146
3146
  paths:
3147
3147
  - dist/
3148
3148
  ${i}
3149
- `}function Sf(e={}){let{awsRegion:n="us-east-1",ttl:r=24}=e;return`stages:
3149
+ `}function Ef(e={}){let{awsRegion:n="us-east-1",ttl:r=24}=e;return`stages:
3150
3150
  - build
3151
3151
  - deploy
3152
3152
  - cleanup
@@ -3191,7 +3191,7 @@ cleanup:preview:
3191
3191
  when: manual
3192
3192
  only:
3193
3193
  - merge_requests
3194
- `}function vf(e){let{environment:n,awsRegion:r="us-east-1"}=e;return`stages:
3194
+ `}function wf(e){let{environment:n,awsRegion:r="us-east-1"}=e;return`stages:
3195
3195
  - deploy
3196
3196
 
3197
3197
  variables:
@@ -3210,7 +3210,7 @@ deploy:scheduled:
3210
3210
  name: \${ENVIRONMENT}
3211
3211
  only:
3212
3212
  - schedules
3213
- `}function Cf(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((s)=>`
3213
+ `}function Af(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((s)=>`
3214
3214
  deploy:${s}:
3215
3215
  stage: deploy
3216
3216
  script:
@@ -3231,7 +3231,7 @@ variables:
3231
3231
  default:
3232
3232
  image: oven/bun:latest
3233
3233
  ${i}
3234
- `}function Tf(e={}){let{awsRegion:n="us-east-1",dockerImage:r="oven/bun:latest",deployCommand:i="bun run cloud deploy",testCommand:s="bun test",buildCommand:a="bun run build",workflows:c=!0}=e;return`version: 2.1
3234
+ `}function Rf(e={}){let{awsRegion:n="us-east-1",dockerImage:r="oven/bun:latest",deployCommand:i="bun run cloud deploy",testCommand:s="bun test",buildCommand:a="bun run build",workflows:c=!0}=e;return`version: 2.1
3235
3235
 
3236
3236
  orbs:
3237
3237
  aws-cli: circleci/aws-cli@4.0
@@ -3314,7 +3314,7 @@ ${c?`workflows:
3314
3314
  branches:
3315
3315
  only: main
3316
3316
  `:""}
3317
- `}function Ef(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((a)=>`
3317
+ `}function If(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((a)=>`
3318
3318
  deploy-${a.name}:
3319
3319
  executor: bun-executor
3320
3320
  steps:
@@ -3390,7 +3390,7 @@ workflows:
3390
3390
  requires:
3391
3391
  - test
3392
3392
  ${s}
3393
- `}function wf(e){let{schedule:n,environment:r,awsRegion:i="us-east-1"}=e;return`version: 2.1
3393
+ `}function Pf(e){let{schedule:n,environment:r,awsRegion:i="us-east-1"}=e;return`version: 2.1
3394
3394
 
3395
3395
  orbs:
3396
3396
  aws-cli: circleci/aws-cli@4.0
@@ -3427,7 +3427,7 @@ workflows:
3427
3427
  only: main
3428
3428
  jobs:
3429
3429
  - deploy
3430
- `}function Af(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((a)=>`
3430
+ `}function Df(e){let{environments:n,awsRegion:r="us-east-1"}=e,i=n.map((a)=>`
3431
3431
  deploy-${a}:
3432
3432
  executor: bun-executor
3433
3433
  steps:
@@ -3503,7 +3503,7 @@ workflows:
3503
3503
  requires:
3504
3504
  - test
3505
3505
  ${s}
3506
- `}function Rf(e){let{regions:n,environment:r}=e,i=n.map((a)=>`
3506
+ `}function kf(e){let{regions:n,environment:r}=e,i=n.map((a)=>`
3507
3507
  deploy-${a.replace(/-/g,"_")}:
3508
3508
  executor: bun-executor
3509
3509
  environment:
@@ -3572,7 +3572,7 @@ workflows:
3572
3572
  requires:
3573
3573
  - test
3574
3574
  ${s}
3575
- `}class Ra{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(e){this.backupVaults.set(e.name,e)}getVault(e){return this.backupVaults.get(e)}createBackupPlan(e){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.backupPlans.set(n,r),r}getBackupPlan(e){return this.backupPlans.get(e)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(e){let{dbInstanceArn:n,schedule:r="0 2 * * *",retentionDays:i=7,vaultName:s="default-vault"}=e;return this.createBackupPlan({name:"RDS Daily Backup",schedule:r,retentionDays:i,vaultName:s,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:i}})}createDynamoDBBackupPlan(e){let{tableArn:n,schedule:r="0 3 * * *",retentionDays:i=35,crossRegionCopy:s}=e;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:r,retentionDays:i,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:i},tags:s?{CrossRegionCopy:s.join(",")}:void 0})}createEFSBackupPlan(e){let{fileSystemArn:n,schedule:r="0 1 * * *",retentionDays:i=30}=e;return this.createBackupPlan({name:"EFS Daily Backup",schedule:r,retentionDays:i,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:i}})}enableContinuousBackup(e,n=35){let r=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,i={id:r,resourceId:e,enabled:!0,retentionDays:n};return this.continuousBackups.set(r,i),i}getContinuousBackup(e){return this.continuousBackups.get(e)}enablePointInTimeRecovery(e,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(e){let{backupId:n,resourceType:r,targetRegion:i}=e,s={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:r,status:"pending",startTime:new Date,targetRegion:i};return this.restoreJobs.set(s.id,s),setTimeout(()=>{s.status="running"},100),setTimeout(()=>{s.status="completed",s.endTime=new Date},1000),s}async restoreToPointInTime(e){let{sourceResourceArn:n,targetResourceName:r,restoreTime:i,resourceType:s}=e,a={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${i.getTime()}`,resourceType:s,status:"pending",startTime:new Date};return this.restoreJobs.set(a.id,a),console.log(`Restoring ${s} from ${n} to ${r} at ${i.toISOString()}`),setTimeout(()=>{a.status="completed",a.endTime=new Date},2000),a}getRestoreJob(e){return this.restoreJobs.get(e)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(e){let{sourceVault:n,sourceRegion:r,targetRegions:i}=e;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${r}`),console.log(` Targets: ${i.join(", ")}`)}generateBackupVaultCF(e){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:e.name,...e.encryptionKeyArn&&{EncryptionKeyArn:e.encryptionKeyArn},...e.accessPolicy&&{AccessPolicy:e.accessPolicy}}}}generateBackupPlanCF(e){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:e.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:e.vaultName,ScheduleExpression:`cron(${e.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:e.lifecycle?{...e.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:e.lifecycle.moveTocoldStorageAfterDays},...e.lifecycle.deleteAfterDays&&{DeleteAfterDays:e.lifecycle.deleteAfterDays}}:void 0}]},...e.tags&&{BackupPlanTags:e.tags}}}}generateBackupSelectionCF(e){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${e.id}`},BackupSelection:{SelectionName:`${e.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:e.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var Gu=new Ra;class Ia{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(e){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.drPlans.set(n,r),r}createRDSDRPlan(e){let{primaryDbArn:n,secondaryDbArn:r,primaryRegion:i,secondaryRegion:s,rto:a=60,rpo:c=5}=e;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:i,secondaryRegion:s,rto:a,rpo:c,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:r,replicationEnabled:!0}],runbook:this.generateRDSRunbook(i,s),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(e){let{tableArn:n,regions:r,rto:i=15,rpo:s=1}=e;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:r[0],secondaryRegion:r[1],rto:i,rpo:s,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(r)})}generateRDSRunbook(e,n){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 "+e,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 "+n,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(e){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(e,n=!1){let r=this.drPlans.get(e);if(!r)throw Error(`DR plan not found: ${e}`);let i=Date.now(),s=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${r.name}`),console.log(`Primary: ${r.primaryRegion} -> Secondary: ${r.secondaryRegion}`),console.log(`RTO: ${r.rto} minutes, RPO: ${r.rpo} minutes`),console.log("");for(let c of r.runbook.steps){if(console.log(`Step ${c.order}: ${c.name}`),console.log(` ${c.description}`),console.log(` Action: ${c.action}`),console.log(` Estimated: ${c.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(c.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");s++,console.log("")}return{success:!0,duration:(Date.now()-i)/1000/60,completedSteps:s}}scheduleFailoverTest(e,n){let r={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"scheduled",startTime:n};return this.failoverTests.set(r.id,r),r}async runFailoverTest(e){let n=this.drPlans.get(e);if(!n)throw Error(`DR plan not found: ${e}`);let r={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"running",startTime:new Date,results:[]};this.failoverTests.set(r.id,r),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let i of n.runbook.steps){let s=Date.now();console.log(`Testing step ${i.order}: ${i.name}`);let a={step:i.name,status:"success",duration:(Date.now()-s)/1000,message:`Successfully validated step ${i.order}`};r.results.push(a)}return r.status="completed",r.endTime=new Date,r}getDRPlan(e){return this.drPlans.get(e)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(e){return this.failoverTests.get(e)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(e){let n=[],r=[];if(e.rto<e.rpo)r.push("RTO cannot be less than RPO");if(e.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(e.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(e.resources.length===0)r.push("No resources defined in DR plan");for(let a of e.resources){if(!a.replicationEnabled)n.push(`Resource ${a.resourceId} does not have replication enabled`);if(!a.secondaryArn&&a.resourceType!=="dynamodb")n.push(`Resource ${a.resourceId} does not have secondary resource defined`)}if(e.runbook.steps.length===0)r.push("No recovery steps defined in runbook");let i=e.runbook.steps.reduce((a,c)=>a+c.estimatedDuration,0);if(i>e.rto)n.push(`Estimated recovery duration (${i}m) exceeds RTO (${e.rto}m)`);let s=e.runbook.steps.filter((a)=>!a.automatable);if(s.length>0)n.push(`${s.length} manual steps in runbook - consider automation`);return{valid:r.length===0,warnings:n,errors:r}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var qu=new Ia;class Pa{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(e){return this.configRecorders.set(e.name,e),e}createDeliveryChannel(e){return this.deliveryChannels.set(e.name,e),e}createConfigRule(e){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,...e};return this.configRules.set(n,r),r}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(e=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:e},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(e){return this.createConfigRule({name:e.name,description:e.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:e.lambdaFunctionArn,scope:e.resourceTypes?{complianceResourceTypes:e.resourceTypes}:void 0,maxExecutionFrequency:e.maxExecutionFrequency,inputParameters:e.inputParameters})}createCompliancePreset(e){let n=[];switch(e){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(e){return this.configRules.get(e)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(e){return this.configRecorders.get(e)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(e){return this.deliveryChannels.get(e)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(e){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:e.name,Description:e.description,Source:{Owner:e.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(e.source==="AWS_MANAGED"&&e.identifier)n.Properties.Source.SourceIdentifier=e.identifier;if(e.source==="CUSTOM_LAMBDA"&&e.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=e.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(e.inputParameters)n.Properties.InputParameters=JSON.stringify(e.inputParameters);if(e.scope){if(n.Properties.Scope={},e.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=e.scope.complianceResourceTypes;if(e.scope.tagKey)n.Properties.Scope.TagKey=e.scope.tagKey;if(e.scope.tagValue)n.Properties.Scope.TagValue=e.scope.tagValue}if(e.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=e.maxExecutionFrequency;return n}generateConfigRecorderCF(e){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:e.name,RoleArn:e.roleArn,RecordingGroup:e.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(e){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:e.name,S3BucketName:e.s3BucketName,...e.s3KeyPrefix&&{S3KeyPrefix:e.s3KeyPrefix},...e.snsTopicArn&&{SnsTopicARN:e.snsTopicArn},...e.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:e.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var Wu=new Pa;class Da{trails=new Map;trailCounter=0;createTrail(e){let n=`trail-${Date.now()}-${this.trailCounter++}`,r={id:n,...e};return this.trails.set(n,r),r}createOrganizationTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn})}createSecurityAuditTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(e){let n=[];if(e.s3DataBuckets&&e.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:e.s3DataBuckets.map((r)=>`arn:aws:s3:::${r}/*`)});if(e.lambdaFunctions&&e.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:e.lambdaFunctions});return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:e.selectors})}createReadOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(e){return this.trails.get(e)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(e){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:e.name,S3BucketName:e.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:e.includeGlobalServiceEvents??!0,IsMultiRegionTrail:e.isMultiRegionTrail??!0,EnableLogFileValidation:e.enableLogFileValidation??!0}};if(e.s3KeyPrefix)n.Properties.S3KeyPrefix=e.s3KeyPrefix;if(e.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=e.cloudWatchLogsLogGroupArn;if(e.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=e.cloudWatchLogsRoleArn;if(e.snsTopicName)n.Properties.SnsTopicName=e.snsTopicName;if(e.kmsKeyId)n.Properties.KMSKeyId=e.kmsKeyId;if(e.eventSelectors)n.Properties.EventSelectors=e.eventSelectors.map((r)=>({ReadWriteType:r.readWriteType,IncludeManagementEvents:r.includeManagementEvents??!0,...r.dataResources&&{DataResources:r.dataResources.map((i)=>({Type:i.type,Values:i.values}))},...r.excludeManagementEventSources&&{ExcludeManagementEventSources:r.excludeManagementEventSources}}));if(e.insightSelectors)n.Properties.InsightSelectors=e.insightSelectors.map((r)=>({InsightType:r.insightType}));if(e.advancedEventSelectors)n.Properties.AdvancedEventSelectors=e.advancedEventSelectors.map((r)=>({Name:r.name,FieldSelectors:r.fieldSelectors.map((i)=>({Field:i.field,...i.equals&&{Equals:i.equals},...i.startsWith&&{StartsWith:i.startsWith},...i.endsWith&&{EndsWith:i.endsWith},...i.notEquals&&{NotEquals:i.notEquals},...i.notStartsWith&&{NotStartsWith:i.notStartsWith},...i.notEndsWith&&{NotEndsWith:i.notEndsWith}}))}));return n}generateBucketPolicy(e,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${e}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((r)=>`arn:aws:s3:::${e}/AWSLogs/${r}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var Ku=new Da;class Na{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(e){let n=`detector-${Date.now()}-${this.detectorCounter++}`,r={id:n,...e};return this.detectors.set(n,r),r}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(e){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,r={id:n,...e};return this.threatIntelSets.set(n,r),r}createIPSet(e){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,r={id:n,...e};return this.ipSets.set(n,r),r}createFindingFilter(e){let n=`filter-${Date.now()}-${this.filterCounter++}`,r={id:n,...e};return this.filters.set(n,r),r}createLowSeverityArchiveFilter(e){return this.createFindingFilter({detectorId:e,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(e,n,r){return this.createFindingFilter({detectorId:e,name:`filter-finding-types-${r.toLowerCase()}`,description:`${r==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:r,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(e,n){return this.createFindingFilter({detectorId:e,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(e){return this.detectors.get(e)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(e){return this.threatIntelSets.get(e)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(e){return this.ipSets.get(e)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(e){return this.filters.get(e)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(e){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:e.enable}};if(e.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=e.findingPublishingFrequency;if(e.dataSources){if(n.Properties.DataSources={},e.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:e.dataSources.s3Logs.enable};if(e.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:e.dataSources.kubernetes.auditLogs.enable}};if(e.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:e.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(e.features)n.Properties.Features=e.features.map((r)=>({Name:r.name,Status:r.status,...r.additionalConfiguration&&{AdditionalConfiguration:r.additionalConfiguration}}));return n}generateThreatIntelSetCF(e){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateIPSetCF(e){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateFilterCF(e){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:e.detectorId,Name:e.name,Description:e.description,Action:e.action,Rank:e.rank,FindingCriteria:{Criterion:e.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 Ju=new Na;class Or{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(e){let n=`hub-${Date.now()}-${this.hubCounter++}`,r={id:n,...e};return this.hubs.set(n,r),r}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Or.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Or.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Or.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Or.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(e){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:e.map((n)=>({value:n,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(e,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${e}`,description:`Automatically suppress known false positives from ${e}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:e,comparison:"EQUALS"}],title:n.map((r)=>({value:r,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(e){return this.hubs.get(e)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(e){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(e.controlFindingGenerator)n.Properties.ControlFindingGenerator=e.controlFindingGenerator;if(e.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=e.enableDefaultStandards;return n}generateStandardCF(e){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:e.arn}};if(e.disabledControls&&e.disabledControls.length>0)n.Properties.DisabledStandardsControls=e.disabledControls.map((r)=>({StandardsControlArn:r,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(e){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:e.ruleName,Description:e.description,Actions:e.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:e.criteria,RuleStatus:e.ruleStatus,RuleOrder:e.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var Xu=new Or;class ka{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(e){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,r={id:n,...e};return this.deployments.set(n,r),r}createALBDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn,switchoverTimeSeconds:0},autoPromote:e.autoPromote,healthCheckConfig:e.healthCheckConfig})}createRoute53Deployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:e.hostedZoneId,switchoverTimeSeconds:e.switchoverTimeSeconds||60}})}createECSDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,taskDefinitionArn:e.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,taskDefinitionArn:e.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn},autoRollback:e.autoRollback??!0})}async executeDeployment(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${r.name}`),console.log(` Active environment: ${r.activeEnvironment}`),console.log(` Routing type: ${r.routingConfig.type}`);let s=r.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${s}`),console.log(`\\n1. Deploying to ${s} environment`),!n)await new Promise((a)=>setTimeout(a,100));if(console.log(`\\n2. Running health checks on ${s} environment`),r.healthCheckConfig){let a=await this.runHealthChecks(r,s,n);if(i.healthChecksPassed=a,!a){if(i.errors?.push("Health checks failed"),i.endTime=new Date,r.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),i.rolledBackAt=new Date;return this.recordDeployment(e,i),i}}else i.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${s} environment`),!n)r.activeEnvironment=s,i.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${s} environment`),!n)await new Promise((a)=>setTimeout(a,100));return i.success=!0,i.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(e,i),i}async rollback(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let i=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=i,r.success=!0,r.rolledBackAt=new Date,r.endTime=new Date,console.log(` Switched back to: ${i}`),this.recordDeployment(e,r),r}async runHealthChecks(e,n,r){let i=e.healthCheckConfig;if(console.log(` Health check path: ${i.path||"/"}`),console.log(` Healthy threshold: ${i.healthyThreshold}`),console.log(` Interval: ${i.interval}s`),r)return console.log(" [SKIPPED - DRY RUN]"),!0;let s=0,a=i.healthyThreshold+2;for(let c=0;c<a;c++)if(await new Promise((d)=>setTimeout(d,50)),Math.random()>0.1){if(s++,console.log(` Check ${c+1}: ✓ Healthy (${s}/${i.healthyThreshold})`),s>=i.healthyThreshold)return!0}else s=0,console.log(` Check ${c+1}: ✗ Unhealthy`);return!1}recordDeployment(e,n){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(n)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateALBListenerCF(e){let n=e.activeEnvironment==="blue"?e.blueEnvironment:e.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:e.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(e,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:e.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:e.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Qu=new ka;class $i{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(e){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,r={id:n,...e};return this.deployments.set(n,r),r}createLambdaCanaryDeployment(e){let n=e.strategy||"BALANCED",r=$i.Strategies[n].map((i)=>({...i,alarmThresholds:{errorRate:e.errorRateThreshold||1,latencyP99:e.latencyThreshold||1000}}));return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",functionVersionArn:e.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:e.canaryVersionArn,weight:0},stages:r,currentStage:0,status:"pending",autoPromote:e.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(e){let n=e.strategy||"CONSERVATIVE",r=$i.Strategies[n];return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",taskDefinitionArn:e.baselineTaskDefinitionArn,targetGroupArn:e.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:e.canaryTaskDefinitionArn,targetGroupArn:e.canaryTargetGroupArn,weight:0},stages:r,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${r.name}`),console.log(` Strategy: ${r.stages.length} stages`),console.log(` Auto-promote: ${r.autoPromote}`),console.log(` Auto-rollback: ${r.autoRollback}`),console.log(""),r.status="in_progress";for(let s=0;s<r.stages.length;s++){let a=r.stages[s];if(r.currentStage=s,console.log(`Stage ${s+1}/${r.stages.length}: ${a.name}`),console.log(` Traffic: ${a.trafficPercentage}% canary, ${100-a.trafficPercentage}% baseline`),console.log(` Duration: ${a.durationMinutes} minutes`),!n)r.baselineVersion.weight=100-a.trafficPercentage,r.canaryVersion.weight=a.trafficPercentage;if(!await this.monitorStage(r,a,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),r.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(e,n),i.rolledBack=!0,i.reason="Metrics exceeded thresholds";return i.endTime=new Date,r.status="rolled_back",this.recordDeployment(e,i),i}console.log(" ✓ Stage completed successfully"),i.completedStages++,console.log("")}return r.status="completed",i.success=!0,i.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(e,i),i}async monitorStage(e,n,r){if(console.log(" Monitoring metrics..."),r)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((s)=>setTimeout(s,100));let i={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)*n.trafficPercentage/100)};if(e.metrics=i,console.log(` Baseline: ${i.baselineErrorRate.toFixed(2)}% errors, ${i.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${i.canaryErrorRate.toFixed(2)}% errors, ${i.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:s,latencyP99:a}=n.alarmThresholds;if(s&&i.canaryErrorRate>s)return console.log(` ⚠ Error rate exceeded threshold: ${i.canaryErrorRate.toFixed(2)}% > ${s}%`),!1;if(a&&i.canaryLatencyP99>a)return console.log(` ⚠ Latency P99 exceeded threshold: ${i.canaryLatencyP99.toFixed(0)}ms > ${a}ms`),!1}return!0}async rollback(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${r.name}`),!n)r.baselineVersion.weight=100,r.canaryVersion.weight=0,r.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);console.log(`Promoting canary to baseline: ${n.name}`);let r=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=r,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(e,n){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(n)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateLambdaAliasCF(e,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:e.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:e.baselineVersion.version,FunctionWeight:e.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:e.baselineVersion.targetGroupArn,Weight:e.baselineVersion.weight},{TargetGroupArn:e.canaryVersion.targetGroupArn,Weight:e.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Yu=new $i;class xa{tests=new Map;testCounter=0;createTest(e){let n=`abtest-${Date.now()}-${this.testCounter++}`,r={id:n,...e};return this.tests.set(n,r),r}createSimpleABTest(e){let n=e.variantTrafficPercentage||50;return this.createTest({name:e.name,description:e.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:e.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:e.variantTargetGroupArn,weight:n}],routingStrategy:{type:e.stickySession?"cookie":"random",cookieName:e.stickySession?"ab_variant":void 0,stickySession:e.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(e){let n=e.variants.reduce((r,i)=>r+i.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:e.name,description:e.description,variants:e.variants.map((r,i)=>({id:`variant-${i}`,name:r.name,description:r.description,trafficPercentage:r.trafficPercentage,targetGroupArn:r.targetGroupArn,weight:r.trafficPercentage})),routingStrategy:e.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(e){return this.createTest({name:e.name,description:`Route based on ${e.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:e.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(e){return this.createTest({name:e.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${e.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((r)=>{console.log(` - ${r.name}: ${r.trafficPercentage}%`)})}pauseTest(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(e,n,r){let i=this.tests.get(e);if(!i)throw Error(`Test not found: ${e}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);let a=s.trafficPercentage;s.trafficPercentage=r,s.weight=r,console.log(`Updated ${s.name} traffic: ${a}% → ${r}%`)}analyzeResults(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let r=n.variants[0],i=0;for(let m of n.variants){let p=n.metrics.variants[m.id];if(p&&p.conversionRate>i)i=p.conversionRate,r=m}let s=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],a=n.metrics.variants[r.id],c=(a.conversionRate-s.conversionRate)/s.conversionRate*100,u=100,d=a.requests>u&&s.requests>u&&Math.abs(c)>10;return{testId:e,winningVariant:r.name,confidence:d?95:75,improvement:c,statisticalSignificance:d,metrics:n.metrics,recommendation:this.generateRecommendation(c,d,r.name)}}declareWinner(e,n){let r=this.tests.get(e);if(!r)throw Error(`Test not found: ${e}`);let i=r.variants.find((s)=>s.id===n);if(!i)throw Error(`Variant not found: ${n}`);r.variants.forEach((s)=>{if(s.id===n)s.trafficPercentage=100,s.weight=100;else s.trafficPercentage=0,s.weight=0}),r.status="completed",r.endTime=new Date,r.winner=n,console.log(`Declared winner: ${i.name}`),console.log(` All traffic now routed to ${i.name}`)}collectMetrics(e){let n={},r=0;for(let i of e.variants){let s=Math.floor(Math.random()*1000)+500,a=Math.floor(s*(Math.random()*0.1+0.05)),c=a/s*100;n[i.id]={requests:s,conversions:a,conversionRate:c,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:a*(Math.random()*50+100)},r+=s}return{variants:n,totalRequests:r,startTime:e.startTime,lastUpdated:new Date}}generateRecommendation(e,n,r){if(!n)return"Continue test - sample size too small or no significant difference detected";if(e>20)return`Strong winner detected - ${r} shows ${e.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(e>10)return`Moderate improvement - ${r} shows ${e.toFixed(1)}% improvement. Consider deploying.`;if(e>0)return`Minor improvement - ${r} shows ${e.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(e){return this.tests.get(e)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:e.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:e.routingStrategy.stickySession||!1,DurationSeconds:e.routingStrategy.sessionDuration?e.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(e){return`'use strict';
3575
+ `}class ka{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(e){this.backupVaults.set(e.name,e)}getVault(e){return this.backupVaults.get(e)}createBackupPlan(e){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.backupPlans.set(n,r),r}getBackupPlan(e){return this.backupPlans.get(e)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(e){let{dbInstanceArn:n,schedule:r="0 2 * * *",retentionDays:i=7,vaultName:s="default-vault"}=e;return this.createBackupPlan({name:"RDS Daily Backup",schedule:r,retentionDays:i,vaultName:s,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:i}})}createDynamoDBBackupPlan(e){let{tableArn:n,schedule:r="0 3 * * *",retentionDays:i=35,crossRegionCopy:s}=e;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:r,retentionDays:i,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:i},tags:s?{CrossRegionCopy:s.join(",")}:void 0})}createEFSBackupPlan(e){let{fileSystemArn:n,schedule:r="0 1 * * *",retentionDays:i=30}=e;return this.createBackupPlan({name:"EFS Daily Backup",schedule:r,retentionDays:i,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:i}})}enableContinuousBackup(e,n=35){let r=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,i={id:r,resourceId:e,enabled:!0,retentionDays:n};return this.continuousBackups.set(r,i),i}getContinuousBackup(e){return this.continuousBackups.get(e)}enablePointInTimeRecovery(e,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(e){let{backupId:n,resourceType:r,targetRegion:i}=e,s={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:r,status:"pending",startTime:new Date,targetRegion:i};return this.restoreJobs.set(s.id,s),setTimeout(()=>{s.status="running"},100),setTimeout(()=>{s.status="completed",s.endTime=new Date},1000),s}async restoreToPointInTime(e){let{sourceResourceArn:n,targetResourceName:r,restoreTime:i,resourceType:s}=e,a={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${i.getTime()}`,resourceType:s,status:"pending",startTime:new Date};return this.restoreJobs.set(a.id,a),console.log(`Restoring ${s} from ${n} to ${r} at ${i.toISOString()}`),setTimeout(()=>{a.status="completed",a.endTime=new Date},2000),a}getRestoreJob(e){return this.restoreJobs.get(e)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(e){let{sourceVault:n,sourceRegion:r,targetRegions:i}=e;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${r}`),console.log(` Targets: ${i.join(", ")}`)}generateBackupVaultCF(e){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:e.name,...e.encryptionKeyArn&&{EncryptionKeyArn:e.encryptionKeyArn},...e.accessPolicy&&{AccessPolicy:e.accessPolicy}}}}generateBackupPlanCF(e){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:e.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:e.vaultName,ScheduleExpression:`cron(${e.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:e.lifecycle?{...e.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:e.lifecycle.moveTocoldStorageAfterDays},...e.lifecycle.deleteAfterDays&&{DeleteAfterDays:e.lifecycle.deleteAfterDays}}:void 0}]},...e.tags&&{BackupPlanTags:e.tags}}}}generateBackupSelectionCF(e){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${e.id}`},BackupSelection:{SelectionName:`${e.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:e.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var Ju=new ka;class Na{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(e){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.drPlans.set(n,r),r}createRDSDRPlan(e){let{primaryDbArn:n,secondaryDbArn:r,primaryRegion:i,secondaryRegion:s,rto:a=60,rpo:c=5}=e;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:i,secondaryRegion:s,rto:a,rpo:c,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:r,replicationEnabled:!0}],runbook:this.generateRDSRunbook(i,s),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(e){let{tableArn:n,regions:r,rto:i=15,rpo:s=1}=e;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:r[0],secondaryRegion:r[1],rto:i,rpo:s,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(r)})}generateRDSRunbook(e,n){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 "+e,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 "+n,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(e){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(e,n=!1){let r=this.drPlans.get(e);if(!r)throw Error(`DR plan not found: ${e}`);let i=Date.now(),s=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${r.name}`),console.log(`Primary: ${r.primaryRegion} -> Secondary: ${r.secondaryRegion}`),console.log(`RTO: ${r.rto} minutes, RPO: ${r.rpo} minutes`),console.log("");for(let c of r.runbook.steps){if(console.log(`Step ${c.order}: ${c.name}`),console.log(` ${c.description}`),console.log(` Action: ${c.action}`),console.log(` Estimated: ${c.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(c.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");s++,console.log("")}return{success:!0,duration:(Date.now()-i)/1000/60,completedSteps:s}}scheduleFailoverTest(e,n){let r={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"scheduled",startTime:n};return this.failoverTests.set(r.id,r),r}async runFailoverTest(e){let n=this.drPlans.get(e);if(!n)throw Error(`DR plan not found: ${e}`);let r={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"running",startTime:new Date,results:[]};this.failoverTests.set(r.id,r),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let i of n.runbook.steps){let s=Date.now();console.log(`Testing step ${i.order}: ${i.name}`);let a={step:i.name,status:"success",duration:(Date.now()-s)/1000,message:`Successfully validated step ${i.order}`};r.results.push(a)}return r.status="completed",r.endTime=new Date,r}getDRPlan(e){return this.drPlans.get(e)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(e){return this.failoverTests.get(e)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(e){let n=[],r=[];if(e.rto<e.rpo)r.push("RTO cannot be less than RPO");if(e.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(e.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(e.resources.length===0)r.push("No resources defined in DR plan");for(let a of e.resources){if(!a.replicationEnabled)n.push(`Resource ${a.resourceId} does not have replication enabled`);if(!a.secondaryArn&&a.resourceType!=="dynamodb")n.push(`Resource ${a.resourceId} does not have secondary resource defined`)}if(e.runbook.steps.length===0)r.push("No recovery steps defined in runbook");let i=e.runbook.steps.reduce((a,c)=>a+c.estimatedDuration,0);if(i>e.rto)n.push(`Estimated recovery duration (${i}m) exceeds RTO (${e.rto}m)`);let s=e.runbook.steps.filter((a)=>!a.automatable);if(s.length>0)n.push(`${s.length} manual steps in runbook - consider automation`);return{valid:r.length===0,warnings:n,errors:r}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var Xu=new Na;class xa{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(e){return this.configRecorders.set(e.name,e),e}createDeliveryChannel(e){return this.deliveryChannels.set(e.name,e),e}createConfigRule(e){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,...e};return this.configRules.set(n,r),r}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(e=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:e},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(e){return this.createConfigRule({name:e.name,description:e.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:e.lambdaFunctionArn,scope:e.resourceTypes?{complianceResourceTypes:e.resourceTypes}:void 0,maxExecutionFrequency:e.maxExecutionFrequency,inputParameters:e.inputParameters})}createCompliancePreset(e){let n=[];switch(e){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(e){return this.configRules.get(e)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(e){return this.configRecorders.get(e)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(e){return this.deliveryChannels.get(e)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(e){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:e.name,Description:e.description,Source:{Owner:e.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(e.source==="AWS_MANAGED"&&e.identifier)n.Properties.Source.SourceIdentifier=e.identifier;if(e.source==="CUSTOM_LAMBDA"&&e.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=e.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(e.inputParameters)n.Properties.InputParameters=JSON.stringify(e.inputParameters);if(e.scope){if(n.Properties.Scope={},e.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=e.scope.complianceResourceTypes;if(e.scope.tagKey)n.Properties.Scope.TagKey=e.scope.tagKey;if(e.scope.tagValue)n.Properties.Scope.TagValue=e.scope.tagValue}if(e.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=e.maxExecutionFrequency;return n}generateConfigRecorderCF(e){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:e.name,RoleArn:e.roleArn,RecordingGroup:e.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(e){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:e.name,S3BucketName:e.s3BucketName,...e.s3KeyPrefix&&{S3KeyPrefix:e.s3KeyPrefix},...e.snsTopicArn&&{SnsTopicARN:e.snsTopicArn},...e.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:e.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var Qu=new xa;class _a{trails=new Map;trailCounter=0;createTrail(e){let n=`trail-${Date.now()}-${this.trailCounter++}`,r={id:n,...e};return this.trails.set(n,r),r}createOrganizationTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn})}createSecurityAuditTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(e){let n=[];if(e.s3DataBuckets&&e.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:e.s3DataBuckets.map((r)=>`arn:aws:s3:::${r}/*`)});if(e.lambdaFunctions&&e.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:e.lambdaFunctions});return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:e.selectors})}createReadOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(e){return this.trails.get(e)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(e){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:e.name,S3BucketName:e.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:e.includeGlobalServiceEvents??!0,IsMultiRegionTrail:e.isMultiRegionTrail??!0,EnableLogFileValidation:e.enableLogFileValidation??!0}};if(e.s3KeyPrefix)n.Properties.S3KeyPrefix=e.s3KeyPrefix;if(e.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=e.cloudWatchLogsLogGroupArn;if(e.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=e.cloudWatchLogsRoleArn;if(e.snsTopicName)n.Properties.SnsTopicName=e.snsTopicName;if(e.kmsKeyId)n.Properties.KMSKeyId=e.kmsKeyId;if(e.eventSelectors)n.Properties.EventSelectors=e.eventSelectors.map((r)=>({ReadWriteType:r.readWriteType,IncludeManagementEvents:r.includeManagementEvents??!0,...r.dataResources&&{DataResources:r.dataResources.map((i)=>({Type:i.type,Values:i.values}))},...r.excludeManagementEventSources&&{ExcludeManagementEventSources:r.excludeManagementEventSources}}));if(e.insightSelectors)n.Properties.InsightSelectors=e.insightSelectors.map((r)=>({InsightType:r.insightType}));if(e.advancedEventSelectors)n.Properties.AdvancedEventSelectors=e.advancedEventSelectors.map((r)=>({Name:r.name,FieldSelectors:r.fieldSelectors.map((i)=>({Field:i.field,...i.equals&&{Equals:i.equals},...i.startsWith&&{StartsWith:i.startsWith},...i.endsWith&&{EndsWith:i.endsWith},...i.notEquals&&{NotEquals:i.notEquals},...i.notStartsWith&&{NotStartsWith:i.notStartsWith},...i.notEndsWith&&{NotEndsWith:i.notEndsWith}}))}));return n}generateBucketPolicy(e,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${e}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((r)=>`arn:aws:s3:::${e}/AWSLogs/${r}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var Yu=new _a;class Oa{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(e){let n=`detector-${Date.now()}-${this.detectorCounter++}`,r={id:n,...e};return this.detectors.set(n,r),r}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(e){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,r={id:n,...e};return this.threatIntelSets.set(n,r),r}createIPSet(e){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,r={id:n,...e};return this.ipSets.set(n,r),r}createFindingFilter(e){let n=`filter-${Date.now()}-${this.filterCounter++}`,r={id:n,...e};return this.filters.set(n,r),r}createLowSeverityArchiveFilter(e){return this.createFindingFilter({detectorId:e,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(e,n,r){return this.createFindingFilter({detectorId:e,name:`filter-finding-types-${r.toLowerCase()}`,description:`${r==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:r,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(e,n){return this.createFindingFilter({detectorId:e,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(e){return this.detectors.get(e)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(e){return this.threatIntelSets.get(e)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(e){return this.ipSets.get(e)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(e){return this.filters.get(e)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(e){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:e.enable}};if(e.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=e.findingPublishingFrequency;if(e.dataSources){if(n.Properties.DataSources={},e.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:e.dataSources.s3Logs.enable};if(e.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:e.dataSources.kubernetes.auditLogs.enable}};if(e.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:e.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(e.features)n.Properties.Features=e.features.map((r)=>({Name:r.name,Status:r.status,...r.additionalConfiguration&&{AdditionalConfiguration:r.additionalConfiguration}}));return n}generateThreatIntelSetCF(e){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateIPSetCF(e){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateFilterCF(e){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:e.detectorId,Name:e.name,Description:e.description,Action:e.action,Rank:e.rank,FindingCriteria:{Criterion:e.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 Zu=new Oa;class Mr{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(e){let n=`hub-${Date.now()}-${this.hubCounter++}`,r={id:n,...e};return this.hubs.set(n,r),r}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Mr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Mr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Mr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Mr.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(e){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:e.map((n)=>({value:n,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(e,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${e}`,description:`Automatically suppress known false positives from ${e}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:e,comparison:"EQUALS"}],title:n.map((r)=>({value:r,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(e){return this.hubs.get(e)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(e){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(e.controlFindingGenerator)n.Properties.ControlFindingGenerator=e.controlFindingGenerator;if(e.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=e.enableDefaultStandards;return n}generateStandardCF(e){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:e.arn}};if(e.disabledControls&&e.disabledControls.length>0)n.Properties.DisabledStandardsControls=e.disabledControls.map((r)=>({StandardsControlArn:r,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(e){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:e.ruleName,Description:e.description,Actions:e.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:e.criteria,RuleStatus:e.ruleStatus,RuleOrder:e.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var ep=new Mr;class $a{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(e){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,r={id:n,...e};return this.deployments.set(n,r),r}createALBDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn,switchoverTimeSeconds:0},autoPromote:e.autoPromote,healthCheckConfig:e.healthCheckConfig})}createRoute53Deployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:e.hostedZoneId,switchoverTimeSeconds:e.switchoverTimeSeconds||60}})}createECSDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,taskDefinitionArn:e.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,taskDefinitionArn:e.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn},autoRollback:e.autoRollback??!0})}async executeDeployment(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${r.name}`),console.log(` Active environment: ${r.activeEnvironment}`),console.log(` Routing type: ${r.routingConfig.type}`);let s=r.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${s}`),console.log(`\\n1. Deploying to ${s} environment`),!n)await new Promise((a)=>setTimeout(a,100));if(console.log(`\\n2. Running health checks on ${s} environment`),r.healthCheckConfig){let a=await this.runHealthChecks(r,s,n);if(i.healthChecksPassed=a,!a){if(i.errors?.push("Health checks failed"),i.endTime=new Date,r.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),i.rolledBackAt=new Date;return this.recordDeployment(e,i),i}}else i.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${s} environment`),!n)r.activeEnvironment=s,i.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${s} environment`),!n)await new Promise((a)=>setTimeout(a,100));return i.success=!0,i.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(e,i),i}async rollback(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let i=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=i,r.success=!0,r.rolledBackAt=new Date,r.endTime=new Date,console.log(` Switched back to: ${i}`),this.recordDeployment(e,r),r}async runHealthChecks(e,n,r){let i=e.healthCheckConfig;if(console.log(` Health check path: ${i.path||"/"}`),console.log(` Healthy threshold: ${i.healthyThreshold}`),console.log(` Interval: ${i.interval}s`),r)return console.log(" [SKIPPED - DRY RUN]"),!0;let s=0,a=i.healthyThreshold+2;for(let c=0;c<a;c++)if(await new Promise((d)=>setTimeout(d,50)),Math.random()>0.1){if(s++,console.log(` Check ${c+1}: ✓ Healthy (${s}/${i.healthyThreshold})`),s>=i.healthyThreshold)return!0}else s=0,console.log(` Check ${c+1}: ✗ Unhealthy`);return!1}recordDeployment(e,n){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(n)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateALBListenerCF(e){let n=e.activeEnvironment==="blue"?e.blueEnvironment:e.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:e.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(e,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:e.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:e.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var tp=new $a;class Bi{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(e){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,r={id:n,...e};return this.deployments.set(n,r),r}createLambdaCanaryDeployment(e){let n=e.strategy||"BALANCED",r=Bi.Strategies[n].map((i)=>({...i,alarmThresholds:{errorRate:e.errorRateThreshold||1,latencyP99:e.latencyThreshold||1000}}));return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",functionVersionArn:e.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:e.canaryVersionArn,weight:0},stages:r,currentStage:0,status:"pending",autoPromote:e.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(e){let n=e.strategy||"CONSERVATIVE",r=Bi.Strategies[n];return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",taskDefinitionArn:e.baselineTaskDefinitionArn,targetGroupArn:e.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:e.canaryTaskDefinitionArn,targetGroupArn:e.canaryTargetGroupArn,weight:0},stages:r,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${r.name}`),console.log(` Strategy: ${r.stages.length} stages`),console.log(` Auto-promote: ${r.autoPromote}`),console.log(` Auto-rollback: ${r.autoRollback}`),console.log(""),r.status="in_progress";for(let s=0;s<r.stages.length;s++){let a=r.stages[s];if(r.currentStage=s,console.log(`Stage ${s+1}/${r.stages.length}: ${a.name}`),console.log(` Traffic: ${a.trafficPercentage}% canary, ${100-a.trafficPercentage}% baseline`),console.log(` Duration: ${a.durationMinutes} minutes`),!n)r.baselineVersion.weight=100-a.trafficPercentage,r.canaryVersion.weight=a.trafficPercentage;if(!await this.monitorStage(r,a,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),r.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(e,n),i.rolledBack=!0,i.reason="Metrics exceeded thresholds";return i.endTime=new Date,r.status="rolled_back",this.recordDeployment(e,i),i}console.log(" ✓ Stage completed successfully"),i.completedStages++,console.log("")}return r.status="completed",i.success=!0,i.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(e,i),i}async monitorStage(e,n,r){if(console.log(" Monitoring metrics..."),r)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((s)=>setTimeout(s,100));let i={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)*n.trafficPercentage/100)};if(e.metrics=i,console.log(` Baseline: ${i.baselineErrorRate.toFixed(2)}% errors, ${i.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${i.canaryErrorRate.toFixed(2)}% errors, ${i.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:s,latencyP99:a}=n.alarmThresholds;if(s&&i.canaryErrorRate>s)return console.log(` ⚠ Error rate exceeded threshold: ${i.canaryErrorRate.toFixed(2)}% > ${s}%`),!1;if(a&&i.canaryLatencyP99>a)return console.log(` ⚠ Latency P99 exceeded threshold: ${i.canaryLatencyP99.toFixed(0)}ms > ${a}ms`),!1}return!0}async rollback(e,n=!1){let r=this.deployments.get(e);if(!r)throw Error(`Deployment not found: ${e}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${r.name}`),!n)r.baselineVersion.weight=100,r.canaryVersion.weight=0,r.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);console.log(`Promoting canary to baseline: ${n.name}`);let r=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=r,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(e,n){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(n)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateLambdaAliasCF(e,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:e.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:e.baselineVersion.version,FunctionWeight:e.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:e.baselineVersion.targetGroupArn,Weight:e.baselineVersion.weight},{TargetGroupArn:e.canaryVersion.targetGroupArn,Weight:e.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var rp=new Bi;class La{tests=new Map;testCounter=0;createTest(e){let n=`abtest-${Date.now()}-${this.testCounter++}`,r={id:n,...e};return this.tests.set(n,r),r}createSimpleABTest(e){let n=e.variantTrafficPercentage||50;return this.createTest({name:e.name,description:e.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:e.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:e.variantTargetGroupArn,weight:n}],routingStrategy:{type:e.stickySession?"cookie":"random",cookieName:e.stickySession?"ab_variant":void 0,stickySession:e.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(e){let n=e.variants.reduce((r,i)=>r+i.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:e.name,description:e.description,variants:e.variants.map((r,i)=>({id:`variant-${i}`,name:r.name,description:r.description,trafficPercentage:r.trafficPercentage,targetGroupArn:r.targetGroupArn,weight:r.trafficPercentage})),routingStrategy:e.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(e){return this.createTest({name:e.name,description:`Route based on ${e.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:e.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(e){return this.createTest({name:e.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${e.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((r)=>{console.log(` - ${r.name}: ${r.trafficPercentage}%`)})}pauseTest(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(e,n,r){let i=this.tests.get(e);if(!i)throw Error(`Test not found: ${e}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);let a=s.trafficPercentage;s.trafficPercentage=r,s.weight=r,console.log(`Updated ${s.name} traffic: ${a}% → ${r}%`)}analyzeResults(e){let n=this.tests.get(e);if(!n)throw Error(`Test not found: ${e}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let r=n.variants[0],i=0;for(let m of n.variants){let p=n.metrics.variants[m.id];if(p&&p.conversionRate>i)i=p.conversionRate,r=m}let s=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],a=n.metrics.variants[r.id],c=(a.conversionRate-s.conversionRate)/s.conversionRate*100,u=100,d=a.requests>u&&s.requests>u&&Math.abs(c)>10;return{testId:e,winningVariant:r.name,confidence:d?95:75,improvement:c,statisticalSignificance:d,metrics:n.metrics,recommendation:this.generateRecommendation(c,d,r.name)}}declareWinner(e,n){let r=this.tests.get(e);if(!r)throw Error(`Test not found: ${e}`);let i=r.variants.find((s)=>s.id===n);if(!i)throw Error(`Variant not found: ${n}`);r.variants.forEach((s)=>{if(s.id===n)s.trafficPercentage=100,s.weight=100;else s.trafficPercentage=0,s.weight=0}),r.status="completed",r.endTime=new Date,r.winner=n,console.log(`Declared winner: ${i.name}`),console.log(` All traffic now routed to ${i.name}`)}collectMetrics(e){let n={},r=0;for(let i of e.variants){let s=Math.floor(Math.random()*1000)+500,a=Math.floor(s*(Math.random()*0.1+0.05)),c=a/s*100;n[i.id]={requests:s,conversions:a,conversionRate:c,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:a*(Math.random()*50+100)},r+=s}return{variants:n,totalRequests:r,startTime:e.startTime,lastUpdated:new Date}}generateRecommendation(e,n,r){if(!n)return"Continue test - sample size too small or no significant difference detected";if(e>20)return`Strong winner detected - ${r} shows ${e.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(e>10)return`Moderate improvement - ${r} shows ${e.toFixed(1)}% improvement. Consider deploying.`;if(e>0)return`Minor improvement - ${r} shows ${e.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(e){return this.tests.get(e)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:e.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:e.routingStrategy.stickySession||!1,DurationSeconds:e.routingStrategy.sessionDuration?e.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(e){return`'use strict';
3576
3576
 
3577
3577
  exports.handler = (event, _context, _callback) => {
3578
3578
  const request = event.Records[0].cf.request;
@@ -3619,7 +3619,7 @@ exports.handler = (event, _context, _callback) => {
3619
3619
  }`).join(" else ")}
3620
3620
 
3621
3621
  callback(null, request);
3622
- };`}clear(){this.tests.clear(),this.testCounter=0}}var Zu=new xa;class _a{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(e,n){let r=`rollout-${Date.now()}-${this.counter++}`,i={id:r,name:e,stages:n,currentStage:0};return this.rollouts.set(r,i),i}createFeatureFlag(e,n=0){let r=`flag-${Date.now()}-${this.counter++}`,i={id:r,name:e,enabled:!1,rolloutPercentage:n,targetingRules:[]};return this.flags.set(r,i),i}createDeploymentGate(e,n,r,i){let s=`gate-${Date.now()}-${this.counter++}`,a={id:s,name:e,type:n,approvers:r,conditions:i};return this.gates.set(s,a),a}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var ep=new _a;class wl{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(e){let n=`xray-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createLambdaConfig(e){return this.createConfig({name:`${e.functionName}-xray`,serviceName:e.functionName,samplingRate:e.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(e){return this.createConfig({name:`${e.serviceName}-xray`,serviceName:`${e.clusterName}/${e.serviceName}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(e){return this.createConfig({name:`${e.apiName}-${e.stage}-xray`,serviceName:`${e.apiName}/${e.stage}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(e){let n=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,...e};return this.samplingRules.set(n,r),r}createHighPrioritySamplingRule(e){return this.createSamplingRule({ruleName:e.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:e.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:e.urlPath,version:1})}createErrorSamplingRule(e){return this.createSamplingRule({ruleName:`${e}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(e,n=0.05){return this.createSamplingRule({ruleName:`${e}-default`,priority:1000,fixedRate:n,reservoirSize:10,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(e){return this.samplingRules.get(e)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(e){return{TracingConfig:{Mode:e.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(e){return{TracingEnabled:e.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(e){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:e.ruleName,Priority:e.priority,FixedRate:e.fixedRate,ReservoirSize:e.reservoirSize,ServiceName:e.serviceName,ServiceType:e.serviceType,Host:e.host,HTTPMethod:e.httpMethod,URLPath:e.urlPath,Version:e.version,ResourceARN:"*"}}}}createTrace(e,n){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:e,spans:n}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var If=new wl;class Al{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(e){let n=`namespace-${Date.now()}-${this.namespaceCounter++}`,r={id:n,...e};return this.namespaces.set(n,r),r}createMetric(e){let n=`metric-${Date.now()}-${this.metricCounter++}`,r={id:n,...e};return this.metrics.set(n,r),r}createBusinessMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Service",value:e.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:e.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:e.errorType},{name:"Type",value:"Error"}]})}createAlarm(e,n){let r=this.metrics.get(e);if(!r)throw Error(`Metric not found: ${e}`);let s={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...n};if(!r.alarms)r.alarms=[];return r.alarms.push(s),s}createErrorRateAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when error rate exceeds ${e.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:e.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createLatencyAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when latency exceeds ${e.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:e.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createThroughputAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when throughput drops below ${e.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:e.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createCompositeAlarm(e){return{name:e.name,description:e.description,alarmRule:e.alarmRule,actionsEnabled:e.actionsEnabled??!0,alarmActions:e.alarmActions}}getNamespace(e){return this.namespaces.get(e)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(e){return this.metrics.get(e)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(e,n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,ComparisonOperator:n.comparisonOperator,EvaluationPeriods:n.evaluationPeriods,MetricName:e.name,Namespace:e.namespace,Period:n.period,Statistic:n.statistic,Threshold:n.threshold,TreatMissingData:n.treatMissingData||"notBreaching",ActionsEnabled:n.actionsEnabled??!0,...n.alarmActions&&{AlarmActions:n.alarmActions},...n.okActions&&{OKActions:n.okActions},...n.insufficientDataActions&&{InsufficientDataActions:n.insufficientDataActions},...e.dimensions&&{Dimensions:e.dimensions.map((r)=>({Name:r.name,Value:r.value}))}}}}generateCompositeAlarmCF(e){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:e.name,AlarmDescription:e.description,AlarmRule:e.alarmRule,ActionsEnabled:e.actionsEnabled,...e.alarmActions&&{AlarmActions:e.alarmActions}}}}generateDashboardWidget(e){return{type:"metric",properties:{metrics:[[e.namespace,e.name,...e.dimensions?.flatMap((n)=>[n.name,n.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:e.name}}}publishCustomMetric(e,n,r,i={},s="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:e,name:n,dimensions:i,value:r,unit:s,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var Pf=new Al;class Oa{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(e){let n=`log-group-${Date.now()}-${this.logGroupCounter++}`,r={id:n,...e};return this.logGroups.set(n,r),r}createLambdaLogGroup(e,n=7){return this.createLogGroup({name:`/aws/lambda/${e}`,retentionDays:n})}createECSLogGroup(e){return this.createLogGroup({name:`/ecs/${e.clusterName}/${e.serviceName}`,retentionDays:e.retentionDays||14})}createAPIGatewayLogGroup(e,n,r=30){return this.createLogGroup({name:`/aws/apigateway/${e}/${n}`,retentionDays:r})}createApplicationLogGroup(e){return this.createLogGroup({name:`/application/${e.appName}/${e.environment}`,retentionDays:e.retentionDays||30,kmsKeyId:e.kmsKeyId})}createMetricFilter(e,n){let r=this.logGroups.get(e);if(!r)throw Error(`Log group not found: ${e}`);let s={id:`filter-${Date.now()}-${this.filterCounter++}`,...n};if(!r.metricFilters)r.metricFilters=[];return r.metricFilters.push(s),s}createErrorCountFilter(e,n){return this.createMetricFilter(e,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:n,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(e,n){return this.createMetricFilter(e,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:n,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(e){return this.createMetricFilter(e.logGroupId,{name:e.name,filterPattern:e.pattern,metricTransformations:[{metricName:e.metricName,metricNamespace:e.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(e,n){let r=this.logGroups.get(e);if(!r)throw Error(`Log group not found: ${e}`);let s={id:`subscription-${Date.now()}-${this.filterCounter++}`,...n};if(!r.subscriptionFilters)r.subscriptionFilters=[];return r.subscriptionFilters.push(s),s}createKinesisSubscription(e){let n=this.logGroups.get(e.logGroupId);if(!n)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"KinesisSubscription",logGroupName:n.name,filterPattern:e.filterPattern||"",destinationArn:e.kinesisStreamArn,roleArn:e.roleArn,distribution:"Random"})}createLambdaSubscription(e){let n=this.logGroups.get(e.logGroupId);if(!n)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"LambdaSubscription",logGroupName:n.name,filterPattern:e.filterPattern||"",destinationArn:e.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(e){let n=`query-${Date.now()}-${this.queryCounter++}`,r={id:n,...e};return this.insightsQueries.set(n,r),r}createErrorAnalysisQuery(e){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3622
+ };`}clear(){this.tests.clear(),this.testCounter=0}}var np=new La;class Ma{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(e,n){let r=`rollout-${Date.now()}-${this.counter++}`,i={id:r,name:e,stages:n,currentStage:0};return this.rollouts.set(r,i),i}createFeatureFlag(e,n=0){let r=`flag-${Date.now()}-${this.counter++}`,i={id:r,name:e,enabled:!1,rolloutPercentage:n,targetingRules:[]};return this.flags.set(r,i),i}createDeploymentGate(e,n,r,i){let s=`gate-${Date.now()}-${this.counter++}`,a={id:s,name:e,type:n,approvers:r,conditions:i};return this.gates.set(s,a),a}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var ip=new Ma;class Pl{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(e){let n=`xray-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createLambdaConfig(e){return this.createConfig({name:`${e.functionName}-xray`,serviceName:e.functionName,samplingRate:e.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(e){return this.createConfig({name:`${e.serviceName}-xray`,serviceName:`${e.clusterName}/${e.serviceName}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(e){return this.createConfig({name:`${e.apiName}-${e.stage}-xray`,serviceName:`${e.apiName}/${e.stage}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(e){let n=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,...e};return this.samplingRules.set(n,r),r}createHighPrioritySamplingRule(e){return this.createSamplingRule({ruleName:e.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:e.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:e.urlPath,version:1})}createErrorSamplingRule(e){return this.createSamplingRule({ruleName:`${e}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(e,n=0.05){return this.createSamplingRule({ruleName:`${e}-default`,priority:1000,fixedRate:n,reservoirSize:10,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(e){return this.samplingRules.get(e)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(e){return{TracingConfig:{Mode:e.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(e){return{TracingEnabled:e.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(e){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:e.ruleName,Priority:e.priority,FixedRate:e.fixedRate,ReservoirSize:e.reservoirSize,ServiceName:e.serviceName,ServiceType:e.serviceType,Host:e.host,HTTPMethod:e.httpMethod,URLPath:e.urlPath,Version:e.version,ResourceARN:"*"}}}}createTrace(e,n){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:e,spans:n}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var Nf=new Pl;class Dl{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(e){let n=`namespace-${Date.now()}-${this.namespaceCounter++}`,r={id:n,...e};return this.namespaces.set(n,r),r}createMetric(e){let n=`metric-${Date.now()}-${this.metricCounter++}`,r={id:n,...e};return this.metrics.set(n,r),r}createBusinessMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Service",value:e.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:e.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:e.errorType},{name:"Type",value:"Error"}]})}createAlarm(e,n){let r=this.metrics.get(e);if(!r)throw Error(`Metric not found: ${e}`);let s={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...n};if(!r.alarms)r.alarms=[];return r.alarms.push(s),s}createErrorRateAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when error rate exceeds ${e.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:e.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createLatencyAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when latency exceeds ${e.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:e.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createThroughputAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when throughput drops below ${e.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:e.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createCompositeAlarm(e){return{name:e.name,description:e.description,alarmRule:e.alarmRule,actionsEnabled:e.actionsEnabled??!0,alarmActions:e.alarmActions}}getNamespace(e){return this.namespaces.get(e)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(e){return this.metrics.get(e)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(e,n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,ComparisonOperator:n.comparisonOperator,EvaluationPeriods:n.evaluationPeriods,MetricName:e.name,Namespace:e.namespace,Period:n.period,Statistic:n.statistic,Threshold:n.threshold,TreatMissingData:n.treatMissingData||"notBreaching",ActionsEnabled:n.actionsEnabled??!0,...n.alarmActions&&{AlarmActions:n.alarmActions},...n.okActions&&{OKActions:n.okActions},...n.insufficientDataActions&&{InsufficientDataActions:n.insufficientDataActions},...e.dimensions&&{Dimensions:e.dimensions.map((r)=>({Name:r.name,Value:r.value}))}}}}generateCompositeAlarmCF(e){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:e.name,AlarmDescription:e.description,AlarmRule:e.alarmRule,ActionsEnabled:e.actionsEnabled,...e.alarmActions&&{AlarmActions:e.alarmActions}}}}generateDashboardWidget(e){return{type:"metric",properties:{metrics:[[e.namespace,e.name,...e.dimensions?.flatMap((n)=>[n.name,n.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:e.name}}}publishCustomMetric(e,n,r,i={},s="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:e,name:n,dimensions:i,value:r,unit:s,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var xf=new Dl;class Ua{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(e){let n=`log-group-${Date.now()}-${this.logGroupCounter++}`,r={id:n,...e};return this.logGroups.set(n,r),r}createLambdaLogGroup(e,n=7){return this.createLogGroup({name:`/aws/lambda/${e}`,retentionDays:n})}createECSLogGroup(e){return this.createLogGroup({name:`/ecs/${e.clusterName}/${e.serviceName}`,retentionDays:e.retentionDays||14})}createAPIGatewayLogGroup(e,n,r=30){return this.createLogGroup({name:`/aws/apigateway/${e}/${n}`,retentionDays:r})}createApplicationLogGroup(e){return this.createLogGroup({name:`/application/${e.appName}/${e.environment}`,retentionDays:e.retentionDays||30,kmsKeyId:e.kmsKeyId})}createMetricFilter(e,n){let r=this.logGroups.get(e);if(!r)throw Error(`Log group not found: ${e}`);let s={id:`filter-${Date.now()}-${this.filterCounter++}`,...n};if(!r.metricFilters)r.metricFilters=[];return r.metricFilters.push(s),s}createErrorCountFilter(e,n){return this.createMetricFilter(e,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:n,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(e,n){return this.createMetricFilter(e,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:n,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(e){return this.createMetricFilter(e.logGroupId,{name:e.name,filterPattern:e.pattern,metricTransformations:[{metricName:e.metricName,metricNamespace:e.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(e,n){let r=this.logGroups.get(e);if(!r)throw Error(`Log group not found: ${e}`);let s={id:`subscription-${Date.now()}-${this.filterCounter++}`,...n};if(!r.subscriptionFilters)r.subscriptionFilters=[];return r.subscriptionFilters.push(s),s}createKinesisSubscription(e){let n=this.logGroups.get(e.logGroupId);if(!n)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"KinesisSubscription",logGroupName:n.name,filterPattern:e.filterPattern||"",destinationArn:e.kinesisStreamArn,roleArn:e.roleArn,distribution:"Random"})}createLambdaSubscription(e){let n=this.logGroups.get(e.logGroupId);if(!n)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"LambdaSubscription",logGroupName:n.name,filterPattern:e.filterPattern||"",destinationArn:e.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(e){let n=`query-${Date.now()}-${this.queryCounter++}`,r={id:n,...e};return this.insightsQueries.set(n,r),r}createErrorAnalysisQuery(e){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3623
3623
  | filter @message like /ERROR/
3624
3624
  | stats count() by bin(5m)
3625
3625
  | sort @timestamp desc`,logGroupNames:e})}createLatencyAnalysisQuery(e){return this.createInsightsQuery({name:"Latency Analysis",description:"Analyze request latency patterns",query:`fields @timestamp, @duration
@@ -3629,7 +3629,7 @@ exports.handler = (event, _context, _callback) => {
3629
3629
  | filter @message like /ERROR/
3630
3630
  | stats count() as error_count by @message
3631
3631
  | sort error_count desc
3632
- | limit 20`,logGroupNames:e})}getLogGroup(e){return this.logGroups.get(e)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(e){return this.insightsQueries.get(e)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(e){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:e.name,...e.retentionDays&&{RetentionInDays:e.retentionDays},...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId}}}}generateMetricFilterCF(e,n){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:e.name,MetricTransformations:n.metricTransformations.map((r)=>({MetricName:r.metricName,MetricNamespace:r.metricNamespace,MetricValue:r.metricValue,...r.defaultValue!==void 0&&{DefaultValue:r.defaultValue},...r.unit&&{Unit:r.unit},...r.dimensions&&{Dimensions:r.dimensions}}))}}}generateSubscriptionFilterCF(e){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:e.name,FilterPattern:e.filterPattern,LogGroupName:e.logGroupName,DestinationArn:e.destinationArn,...e.roleArn&&{RoleArn:e.roleArn},...e.distribution&&{Distribution:e.distribution}}}}generateQueryDefinitionCF(e){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:e.name,QueryString:e.query,LogGroupNames:e.logGroupNames}}}createLogAggregation(e,n,r=7){let i=`aggregation-${Date.now()}-${this.logGroupCounter++}`,s=this.createLogGroup({name:e,retentionDays:r});return n.forEach((a)=>{this.createMetricFilter(s.id,{name:a.metric,filterPattern:a.pattern,metricTransformations:[{metricName:a.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:i,logGroup:e,filters:n,retention:r}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var tp=new Oa;class $r{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(e){let n=`canary-${Date.now()}-${this.canaryCounter++}`,r={id:n,...e};return this.canaries.set(n,r),r}createHeartbeatCanary(e){let n=`
3632
+ | limit 20`,logGroupNames:e})}getLogGroup(e){return this.logGroups.get(e)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(e){return this.insightsQueries.get(e)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(e){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:e.name,...e.retentionDays&&{RetentionInDays:e.retentionDays},...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId}}}}generateMetricFilterCF(e,n){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:e.name,MetricTransformations:n.metricTransformations.map((r)=>({MetricName:r.metricName,MetricNamespace:r.metricNamespace,MetricValue:r.metricValue,...r.defaultValue!==void 0&&{DefaultValue:r.defaultValue},...r.unit&&{Unit:r.unit},...r.dimensions&&{Dimensions:r.dimensions}}))}}}generateSubscriptionFilterCF(e){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:e.name,FilterPattern:e.filterPattern,LogGroupName:e.logGroupName,DestinationArn:e.destinationArn,...e.roleArn&&{RoleArn:e.roleArn},...e.distribution&&{Distribution:e.distribution}}}}generateQueryDefinitionCF(e){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:e.name,QueryString:e.query,LogGroupNames:e.logGroupNames}}}createLogAggregation(e,n,r=7){let i=`aggregation-${Date.now()}-${this.logGroupCounter++}`,s=this.createLogGroup({name:e,retentionDays:r});return n.forEach((a)=>{this.createMetricFilter(s.id,{name:a.metric,filterPattern:a.pattern,metricTransformations:[{metricName:a.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:i,logGroup:e,filters:n,retention:r}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var op=new Ua;class Ur{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(e){let n=`canary-${Date.now()}-${this.canaryCounter++}`,r={id:n,...e};return this.canaries.set(n,r),r}createHeartbeatCanary(e){let n=`
3633
3633
  const synthetics = require('Synthetics');
3634
3634
  const log = require('SyntheticsLogger');
3635
3635
 
@@ -3649,7 +3649,7 @@ const heartbeat = async function () {
3649
3649
  exports.handler = async () => {
3650
3650
  return await heartbeat();
3651
3651
  };
3652
- `;return this.createCanary({name:e.name,description:`Heartbeat monitor for ${e.url}`,runtimeVersion:$r.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:n},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(e){let r=`
3652
+ `;return this.createCanary({name:e.name,description:`Heartbeat monitor for ${e.url}`,runtimeVersion:Ur.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:n},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(e){let r=`
3653
3653
  const synthetics = require('Synthetics');
3654
3654
  const log = require('SyntheticsLogger');
3655
3655
 
@@ -3678,7 +3678,7 @@ const apiCheck = async function () {
3678
3678
  exports.handler = async () => {
3679
3679
  return await apiCheck();
3680
3680
  };
3681
- `;return this.createCanary({name:e.name,description:`API monitor for ${e.baseUrl}`,runtimeVersion:$r.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:r},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(e){let n=`
3681
+ `;return this.createCanary({name:e.name,description:`API monitor for ${e.baseUrl}`,runtimeVersion:Ur.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:r},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(e){let n=`
3682
3682
  const synthetics = require('Synthetics');
3683
3683
  const log = require('SyntheticsLogger');
3684
3684
 
@@ -3698,7 +3698,7 @@ const visualCheck = async function () {
3698
3698
  exports.handler = async () => {
3699
3699
  return await visualCheck();
3700
3700
  };
3701
- `;return this.createCanary({name:e.name,description:`Visual regression monitor for ${e.url}`,runtimeVersion:$r.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:n},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(e){let r=`
3701
+ `;return this.createCanary({name:e.name,description:`Visual regression monitor for ${e.url}`,runtimeVersion:Ur.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:n},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(e){let r=`
3702
3702
  const synthetics = require('Synthetics');
3703
3703
  const log = require('SyntheticsLogger');
3704
3704
 
@@ -3720,35 +3720,35 @@ const workflowCheck = async function () {
3720
3720
  exports.handler = async () => {
3721
3721
  return await workflowCheck();
3722
3722
  };
3723
- `;return this.createCanary({name:e.name,description:e.description,runtimeVersion:$r.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:r},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(e){switch(e.type){case"click":return`await page.click('${e.selector}');`;case"type":return`await page.type('${e.selector}', '${e.value}');`;case"wait":return`await page.waitForTimeout(${e.duration});`;case"waitForSelector":return`await page.waitForSelector('${e.selector}');`;default:return""}}createAlarm(e,n){let r=this.canaries.get(e);if(!r)throw Error(`Canary not found: ${e}`);let s={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...n};if(!r.alarms)r.alarms=[];return r.alarms.push(s),s}getCanary(e){return this.canaries.get(e)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(e){let n={Type:"AWS::Synthetics::Canary",Properties:{Name:e.name,RuntimeVersion:e.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:e.schedule.expression,...e.schedule.durationInSeconds&&{DurationInSeconds:e.schedule.durationInSeconds}},ArtifactS3Location:e.artifactS3Location,StartCanaryAfterCreation:!0}};if(e.code.type==="script")n.Properties.Code={Handler:e.handler,Script:e.code.script};else n.Properties.Code={Handler:e.handler,S3Bucket:e.code.s3Bucket,S3Key:e.code.s3Key,...e.code.s3Version&&{S3ObjectVersion:e.code.s3Version}};if(e.runConfig)n.Properties.RunConfig={TimeoutInSeconds:e.runConfig.timeoutInSeconds,MemoryInMB:e.runConfig.memoryInMB,...e.runConfig.environmentVariables&&{EnvironmentVariables:e.runConfig.environmentVariables},...e.runConfig.activeTracing!==void 0&&{ActiveTracing:e.runConfig.activeTracing}};if(e.vpcConfig)n.Properties.VPCConfig={SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.vpcConfig.securityGroupIds};if(e.successRetentionPeriod)n.Properties.SuccessRetentionPeriod=e.successRetentionPeriod;if(e.failureRetentionPeriod)n.Properties.FailureRetentionPeriod=e.failureRetentionPeriod;return n}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 rp=new $r;class Rl{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(e){let n=`migration-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.plans.set(n,r),r}createMigration(e){let n=`migration-${Date.now()}-${this.migrationCounter++}`,r=this.generateChecksum(e.up+e.down),i={id:n,checksum:r,...e};return this.migrations.set(n,i),i}createSchemaMigration(e){let{up:n,down:r}=this.generateSchemaSQL(e.changes,e.tableName,e.engine);return this.createMigration({version:e.version,name:e.name,description:`Schema changes for ${e.tableName}`,up:n,down:r})}createDataMigration(e){return this.createMigration({version:e.version,name:e.name,description:e.description,up:e.upSQL,down:e.downSQL})}addMigrationToPlan(e,n){let r=this.plans.get(e);if(!r)throw Error(`Migration plan not found: ${e}`);r.migrations.push(n)}async executePlan(e,n=!1){let r=this.plans.get(e);if(!r)throw Error(`Migration plan not found: ${e}`);let i=Date.now(),s=[],a=[];if(console.log(`${n?"[DRY RUN] ":""}Executing migration plan: ${r.name}`),console.log(`Database: ${r.database.type} - ${r.database.identifier}`),console.log(`Migrations to apply: ${r.migrations.length}
3723
+ `;return this.createCanary({name:e.name,description:e.description,runtimeVersion:Ur.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:r},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(e){switch(e.type){case"click":return`await page.click('${e.selector}');`;case"type":return`await page.type('${e.selector}', '${e.value}');`;case"wait":return`await page.waitForTimeout(${e.duration});`;case"waitForSelector":return`await page.waitForSelector('${e.selector}');`;default:return""}}createAlarm(e,n){let r=this.canaries.get(e);if(!r)throw Error(`Canary not found: ${e}`);let s={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...n};if(!r.alarms)r.alarms=[];return r.alarms.push(s),s}getCanary(e){return this.canaries.get(e)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(e){let n={Type:"AWS::Synthetics::Canary",Properties:{Name:e.name,RuntimeVersion:e.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:e.schedule.expression,...e.schedule.durationInSeconds&&{DurationInSeconds:e.schedule.durationInSeconds}},ArtifactS3Location:e.artifactS3Location,StartCanaryAfterCreation:!0}};if(e.code.type==="script")n.Properties.Code={Handler:e.handler,Script:e.code.script};else n.Properties.Code={Handler:e.handler,S3Bucket:e.code.s3Bucket,S3Key:e.code.s3Key,...e.code.s3Version&&{S3ObjectVersion:e.code.s3Version}};if(e.runConfig)n.Properties.RunConfig={TimeoutInSeconds:e.runConfig.timeoutInSeconds,MemoryInMB:e.runConfig.memoryInMB,...e.runConfig.environmentVariables&&{EnvironmentVariables:e.runConfig.environmentVariables},...e.runConfig.activeTracing!==void 0&&{ActiveTracing:e.runConfig.activeTracing}};if(e.vpcConfig)n.Properties.VPCConfig={SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.vpcConfig.securityGroupIds};if(e.successRetentionPeriod)n.Properties.SuccessRetentionPeriod=e.successRetentionPeriod;if(e.failureRetentionPeriod)n.Properties.FailureRetentionPeriod=e.failureRetentionPeriod;return n}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 sp=new Ur;class kl{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(e){let n=`migration-plan-${Date.now()}-${this.planCounter++}`,r={id:n,...e};return this.plans.set(n,r),r}createMigration(e){let n=`migration-${Date.now()}-${this.migrationCounter++}`,r=this.generateChecksum(e.up+e.down),i={id:n,checksum:r,...e};return this.migrations.set(n,i),i}createSchemaMigration(e){let{up:n,down:r}=this.generateSchemaSQL(e.changes,e.tableName,e.engine);return this.createMigration({version:e.version,name:e.name,description:`Schema changes for ${e.tableName}`,up:n,down:r})}createDataMigration(e){return this.createMigration({version:e.version,name:e.name,description:e.description,up:e.upSQL,down:e.downSQL})}addMigrationToPlan(e,n){let r=this.plans.get(e);if(!r)throw Error(`Migration plan not found: ${e}`);r.migrations.push(n)}async executePlan(e,n=!1){let r=this.plans.get(e);if(!r)throw Error(`Migration plan not found: ${e}`);let i=Date.now(),s=[],a=[];if(console.log(`${n?"[DRY RUN] ":""}Executing migration plan: ${r.name}`),console.log(`Database: ${r.database.type} - ${r.database.identifier}`),console.log(`Migrations to apply: ${r.migrations.length}
3724
3724
  `),r.backupBeforeMigration&&!n)console.log("Creating database backup before migration...");for(let u of r.migrations)try{if(console.log(`Applying migration: ${u.version} - ${u.name}`),!n){if(this.generateChecksum(u.up+u.down)!==u.checksum)throw Error("Migration checksum mismatch - migration has been modified");let m=Date.now();u.appliedAt=new Date,u.executionTimeMs=Date.now()-m,console.log(`✓ Applied in ${u.executionTimeMs}ms
3725
3725
  `)}else console.log(`[SKIPPED - DRY RUN]
3726
3726
  `);s.push(u.version)}catch(d){if(console.error(`✗ Failed: ${d instanceof Error?d.message:String(d)}
3727
3727
  `),a.push(u.version),!n)return console.log("Rolling back previously applied migrations..."),await this.rollbackMigrations(s.reverse(),r),{success:!1,version:u.version,appliedMigrations:[],failedMigrations:a,executionTimeMs:Date.now()-i,error:d instanceof Error?d.message:String(d),rollbackPerformed:!0}}let c=Date.now()-i;return console.log(`${n?"[DRY RUN] ":""}Migration plan completed successfully`),console.log(`Total time: ${c}ms`),{success:!0,version:r.migrations[r.migrations.length-1]?.version||"unknown",appliedMigrations:s,failedMigrations:a,executionTimeMs:c}}async rollbackMigrations(e,n){for(let r of e){let i=n.migrations.find((s)=>s.version===r);if(i)console.log(`Rolling back: ${i.version} - ${i.name}`),i.rolledBackAt=new Date,console.log(`✓ Rolled back
3728
3728
  `)}}getMigrationStatus(e){let n=this.plans.get(e);if(!n)throw Error(`Migration plan not found: ${e}`);let r=n.migrations.filter((s)=>s.appliedAt&&!s.rolledBackAt),i=n.migrations.filter((s)=>!s.appliedAt);return{currentVersion:r[r.length-1]?.version||"0.0.0",pendingMigrations:i,appliedMigrations:r,lastMigration:r[r.length-1]}}generateSchemaSQL(e,n,r="postgres"){let i=[],s=[];for(let a of e)switch(a.type){case"add_column":i.push(`ALTER TABLE ${n} ADD COLUMN ${a.columnName} ${a.columnType}${a.nullable===!1?" NOT NULL":""}${a.defaultValue?` DEFAULT ${a.defaultValue}`:""}; `),s.push(`ALTER TABLE ${n} DROP COLUMN ${a.columnName};`);break;case"drop_column":i.push(`ALTER TABLE ${n} DROP COLUMN ${a.columnName};`),s.push(`-- Cannot restore dropped column ${a.columnName}`);break;case"modify_column":if(r==="postgres")i.push(`ALTER TABLE ${n} ALTER COLUMN ${a.columnName} TYPE ${a.newType};`);else i.push(`ALTER TABLE ${n} MODIFY COLUMN ${a.columnName} ${a.newType};`);s.push(`-- Reverting ${a.columnName} type change requires manual intervention`);break;case"add_index":i.push(`CREATE INDEX ${a.indexName} ON ${n} (${(a.columns??[]).join(", ")});`),s.push(`DROP INDEX ${a.indexName};`);break;case"drop_index":i.push(`DROP INDEX ${a.indexName};`),s.push(`-- Cannot restore index ${a.indexName} without schema details`);break}return{up:i.join(`
3729
3729
  `),down:s.reverse().join(`
3730
- `)}}generateChecksum(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return n.toString(16)}validatePlan(e){let n=this.plans.get(e);if(!n)return{valid:!1,errors:["Migration plan not found"]};let r=[],i=new Set;for(let s of n.migrations){if(i.has(s.version))r.push(`Duplicate migration version: ${s.version}`);i.add(s.version)}for(let s of n.migrations)if(!s.down||s.down.trim()==="")r.push(`Migration ${s.version} is missing rollback SQL`);for(let s of n.migrations)if(this.generateChecksum(s.up+s.down)!==s.checksum)r.push(`Migration ${s.version} has invalid checksum`);return{valid:r.length===0,errors:r}}getPlan(e){return this.plans.get(e)}listPlans(){return Array.from(this.plans.values())}getMigration(e){return this.migrations.get(e)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var Df=new Rl;class $a{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(e){let n=`replica-${Date.now()}-${this.replicaCounter++}`,r={id:n,status:"creating",...e};return this.replicas.set(n,r),r}createRDSReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.region||"us-east-1",instanceClass:e.instanceClass||"db.t3.medium",multiAZ:e.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.targetRegion,instanceClass:e.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(e){let n=`replication-group-${Date.now()}-${this.groupCounter++}`,r={id:n,...e};return this.replicationGroups.set(n,r),r}createAutoScalingReplicationGroup(e){return this.createReplicationGroup({name:e.name,primaryDatabase:e.primaryDatabase,replicas:[],loadBalancing:e.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:e.minReplicas,maxReplicas:e.maxReplicas,targetCPU:e.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(e,n){let r=this.replicationGroups.get(e);if(!r)throw Error(`Replication group not found: ${e}`);r.replicas.push(n)}createProxy(e){let n=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,r={id:n,...e};return this.proxies.set(n,r),r}createConnectionPoolProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:e.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}createServerlessProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}addProxyTarget(e){let n=`proxy-target-${Date.now()}-${this.targetCounter++}`,r={id:n,...e};return this.proxyTargets.set(n,r),r}promoteReplica(e){let n=this.replicas.get(e);if(!n)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${n.name}`),console.log(`Region: ${n.region}`),console.log(`
3730
+ `)}}generateChecksum(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return n.toString(16)}validatePlan(e){let n=this.plans.get(e);if(!n)return{valid:!1,errors:["Migration plan not found"]};let r=[],i=new Set;for(let s of n.migrations){if(i.has(s.version))r.push(`Duplicate migration version: ${s.version}`);i.add(s.version)}for(let s of n.migrations)if(!s.down||s.down.trim()==="")r.push(`Migration ${s.version} is missing rollback SQL`);for(let s of n.migrations)if(this.generateChecksum(s.up+s.down)!==s.checksum)r.push(`Migration ${s.version} has invalid checksum`);return{valid:r.length===0,errors:r}}getPlan(e){return this.plans.get(e)}listPlans(){return Array.from(this.plans.values())}getMigration(e){return this.migrations.get(e)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var _f=new kl;class Ba{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(e){let n=`replica-${Date.now()}-${this.replicaCounter++}`,r={id:n,status:"creating",...e};return this.replicas.set(n,r),r}createRDSReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.region||"us-east-1",instanceClass:e.instanceClass||"db.t3.medium",multiAZ:e.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.targetRegion,instanceClass:e.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(e){let n=`replication-group-${Date.now()}-${this.groupCounter++}`,r={id:n,...e};return this.replicationGroups.set(n,r),r}createAutoScalingReplicationGroup(e){return this.createReplicationGroup({name:e.name,primaryDatabase:e.primaryDatabase,replicas:[],loadBalancing:e.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:e.minReplicas,maxReplicas:e.maxReplicas,targetCPU:e.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(e,n){let r=this.replicationGroups.get(e);if(!r)throw Error(`Replication group not found: ${e}`);r.replicas.push(n)}createProxy(e){let n=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,r={id:n,...e};return this.proxies.set(n,r),r}createConnectionPoolProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:e.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}createServerlessProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}addProxyTarget(e){let n=`proxy-target-${Date.now()}-${this.targetCounter++}`,r={id:n,...e};return this.proxyTargets.set(n,r),r}promoteReplica(e){let n=this.replicas.get(e);if(!n)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${n.name}`),console.log(`Region: ${n.region}`),console.log(`
3731
3731
  1. Checking replication lag...`),n.replicationLag&&n.replicationLag>5000)return{success:!1,message:`Replication lag too high: ${n.replicationLag}ms`};return console.log(` Replication lag: ${n.replicationLag||0}ms (acceptable)`),console.log(`
3732
3732
  2. Promoting replica to standalone instance...`),console.log(`
3733
3733
  3. Updating DNS records...`),console.log(`
3734
3734
  4. Updating application configuration...`),console.log(`
3735
- ✓ Promotion completed successfully`),n.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(e){if(!this.replicas.get(e))throw Error(`Replica not found: ${e}`);return Math.floor(Math.random()*1000)}getReplica(e){return this.replicas.get(e)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(e){return this.replicationGroups.get(e)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(e){return this.proxies.get(e)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(e){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:e.sourceDatabase,DBInstanceIdentifier:e.name,DBInstanceClass:e.instanceClass,MultiAZ:e.multiAZ||!1,AutoMinorVersionUpgrade:e.autoMinorVersionUpgrade??!0,...e.backupRetentionPeriod&&{BackupRetentionPeriod:e.backupRetentionPeriod},...e.preferredBackupWindow&&{PreferredBackupWindow:e.preferredBackupWindow},...e.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:e.preferredMaintenanceWindow}}}}generateProxyCF(e){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:e.name,EngineFamily:e.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:e.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:e.vpcSubnetIds,VpcSecurityGroupIds:e.securityGroupIds,RequireTLS:e.requireTLS??!0,IdleClientTimeout:e.idleClientTimeout||1800,...e.maxConnectionsPercent&&{MaxConnectionsPercent:e.maxConnectionsPercent},...e.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:e.maxIdleConnectionsPercent},...e.connectionBorrowTimeout&&{ConnectionBorrowTimeout:e.connectionBorrowTimeout}}}}generateProxyTargetCF(e,n){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:n.name,TargetGroupName:"default",DBInstanceIdentifiers:[e.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 np=new $a;class Il{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(e){let n=`pi-${Date.now()}-${this.insightsCounter++}`,r={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,retentionPeriod:e.retentionPeriod||7,kmsKeyId:e.kmsKeyId};return this.insights.set(n,r),r}enableSlowQueryLog(e){let n=`slow-query-${Date.now()}-${this.logCounter++}`,r={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,logDestination:e.logDestination,cloudwatchLogGroup:e.cloudwatchLogGroup,s3Bucket:e.s3Bucket,s3Prefix:e.s3Bucket?"slow-queries/":void 0,minExecutionTime:e.minExecutionTime||1000};return this.slowQueryLogs.set(n,r),r}recordQueryMetric(e){let n=`metric-${Date.now()}-${this.metricCounter++}`,r={id:n,timestamp:new Date,...e};return this.queryMetrics.set(n,r),r}generatePerformanceReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r={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)},i=Array.from(this.queryMetrics.values()),s=i.sort((d,m)=>m.executionCount-d.executionCount).slice(0,10),a=i.filter((d)=>d.avgExecutionTime>1000).sort((d,m)=>m.avgExecutionTime-d.avgExecutionTime).slice(0,10),c=this.generateRecommendations(r,a),u={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,reportType:e.reportType,metrics:r,topQueries:s,slowQueries:a,recommendations:c,generatedAt:new Date};return this.reports.set(n,u),u}generateRecommendations(e,n){let r=[];if(e.avgCPU>70)r.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${e.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(e.cacheHitRatio<95)r.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${e.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(e.deadlocks>0)r.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${e.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(n.length>0)r.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${n.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(e.avgReadLatency>10||e.avgWriteLatency>10)r.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 r}analyzeQuery(e){let n=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,r=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],i=[];if(e.toLowerCase().includes("select *"))i.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!e.toLowerCase().includes("where")&&e.toLowerCase().includes("select"))i.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:n,queryId:n,sql:e,executionPlan:r,bottlenecks:i,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:r[0].cost}}recommendIndex(e){let n=`index-rec-${Date.now()}-${this.recommendationCounter++}`,r=`idx_${e.tableName}_${e.columns.join("_")}`,i={id:n,tableName:e.tableName,columns:e.columns,reason:e.reason,estimatedImprovement:e.estimatedImprovement||50,estimatedSize:e.columns.length*10,createSQL:`CREATE INDEX ${r} ON ${e.tableName} (${e.columns.join(", ")});`};return this.indexRecommendations.set(n,i),i}getInsights(e){return this.insights.get(e)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(e){return this.slowQueryLogs.get(e)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(e){return this.reports.get(e)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(e){return{EnablePerformanceInsights:e.enabled,PerformanceInsightsRetentionPeriod:e.retentionPeriod,...e.kmsKeyId&&{PerformanceInsightsKMSKeyId:e.kmsKeyId}}}generateSlowQueryAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",...e.snsTopicArn&&{AlarmActions:[e.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 Nf=new Il;class Pl{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(e){let n=`db-user-${Date.now()}-${this.userCounter++}`,r={id:n,createdAt:new Date,...e};return this.users.set(n,r),r}createReadOnlyUser(e){let n=e.tables?e.tables.map((r)=>({database:e.database,table:r,privileges:["SELECT"]})):[{database:e.database,privileges:["SELECT"]}];return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(e){let n=e.tables?e.tables.map((r)=>({database:e.database,table:r,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:e.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(e){return this.createUser({username:e.username,database:e.database,privileges:[{database:e.database,privileges:["ALL"]}],passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(e){let n=e.tables.map((r)=>({database:e.database,table:r.name,privileges:r.privileges}));return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(e){let n=`role-${Date.now()}-${this.roleCounter++}`,r={id:n,users:[],...e};return this.roles.set(n,r),r}assignUserToRole(e,n){let r=this.users.get(e),i=this.roles.get(n);if(!r)throw Error(`User not found: ${e}`);if(!i)throw Error(`Role not found: ${n}`);i.users.push(e);for(let s of i.privileges){let a=r.privileges.find((c)=>c.database===s.database&&c.table===s.table);if(a)a.privileges=Array.from(new Set([...a.privileges,...s.privileges]));else r.privileges.push({...s})}}grantPrivileges(e,n){let r=this.users.get(e);if(!r)return{success:!1,message:"User not found"};for(let i of n){let s=r.privileges.find((a)=>a.database===i.database&&a.table===i.table);if(s)s.privileges=Array.from(new Set([...s.privileges,...i.privileges]));else r.privileges.push(i)}return this.auditAccess({username:r.username,action:"GRANT",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(e,n){let r=this.users.get(e);if(!r)return{success:!1,message:"User not found"};for(let i of n){let s=r.privileges.findIndex((a)=>a.database===i.database&&a.table===i.table);if(s!==-1){let a=r.privileges[s];if(a.privileges=a.privileges.filter((c)=>!i.privileges.includes(c)),a.privileges.length===0)r.privileges.splice(s,1)}}return this.auditAccess({username:r.username,action:"REVOKE",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(e){let n=this.users.get(e);if(!n)return{success:!1};let r=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${n.username}-${Date.now()}`;return n.passwordSecretArn=r,n.lastRotated=new Date,console.log(`Password rotated for user: ${n.username}`),{success:!0,newSecretArn:r}}needsPasswordRotation(e){let n=this.users.get(e);if(!n||!n.rotationEnabled||!n.lastRotated||!n.rotationDays)return!1;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}auditAccess(e){let n=`audit-${Date.now()}-${this.auditCounter++}`,r={id:n,timestamp:new Date,...e};return this.audits.set(n,r),r}getUserAccessHistory(e,n=100){return Array.from(this.audits.values()).filter((r)=>r.username===e).sort((r,i)=>i.timestamp.getTime()-r.timestamp.getTime()).slice(0,n)}getFailedLoginAttempts(e,n=24){let r=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((i)=>i.username===e&&i.action==="LOGIN"&&!i.success&&i.timestamp.getTime()>r)}generateCreateUserSQL(e,n="postgres"){let r=[];if(n==="postgres"){r.push(`CREATE USER ${e.username} WITH PASSWORD '${e.passwordSecretArn}';`);for(let i of e.privileges)if(i.privileges.includes("ALL"))r.push(`GRANT ALL PRIVILEGES ON DATABASE ${i.database} TO ${e.username};`);else{let s=i.privileges.join(", ");if(i.table)r.push(`GRANT ${s} ON ${i.database}.${i.table} TO ${e.username};`);else r.push(`GRANT ${s} ON DATABASE ${i.database} TO ${e.username};`)}}else{r.push(`CREATE USER '${e.username}'@'%' IDENTIFIED BY '${e.passwordSecretArn}';`);for(let i of e.privileges){let s=i.privileges.includes("ALL")?"ALL PRIVILEGES":i.privileges.join(", "),a=i.table?`${i.database}.${i.table}`:`${i.database}.*`;r.push(`GRANT ${s} ON ${a} TO '${e.username}'@'%';`)}r.push("FLUSH PRIVILEGES;")}return r.join(`
3736
- `)}getUser(e){return this.users.get(e)}listUsers(){return Array.from(this.users.values())}getRole(e){return this.roles.get(e)}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 kf=new Pl;class Dl{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(e){let n=`rotation-${Date.now()}-${this.rotationCounter++}`,r={id:n,...e};return this.rotations.set(n,r),r}enableRDSRotation(e){let n=this.createRotation({secretId:e.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:e.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(e.engine)});return n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),n}enableAPIKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:e.rotationDays||90,rotationLambdaArn:e.rotationLambdaArn})}enableOAuthRotation(e){return this.createRotation({secretId:e.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:e.rotationDays||60,rotationLambdaArn:e.rotationLambdaArn})}enableSSHKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:e.rotationDays||180,rotationLambdaArn:e.rotationLambdaArn})}createSchedule(e){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,r={id:n,...e};return this.schedules.set(n,r),r}async executeRotation(e){let n=this.rotations.get(e);if(!n)throw Error(`Rotation not found: ${e}`);console.log(`
3735
+ ✓ Promotion completed successfully`),n.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(e){if(!this.replicas.get(e))throw Error(`Replica not found: ${e}`);return Math.floor(Math.random()*1000)}getReplica(e){return this.replicas.get(e)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(e){return this.replicationGroups.get(e)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(e){return this.proxies.get(e)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(e){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:e.sourceDatabase,DBInstanceIdentifier:e.name,DBInstanceClass:e.instanceClass,MultiAZ:e.multiAZ||!1,AutoMinorVersionUpgrade:e.autoMinorVersionUpgrade??!0,...e.backupRetentionPeriod&&{BackupRetentionPeriod:e.backupRetentionPeriod},...e.preferredBackupWindow&&{PreferredBackupWindow:e.preferredBackupWindow},...e.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:e.preferredMaintenanceWindow}}}}generateProxyCF(e){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:e.name,EngineFamily:e.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:e.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:e.vpcSubnetIds,VpcSecurityGroupIds:e.securityGroupIds,RequireTLS:e.requireTLS??!0,IdleClientTimeout:e.idleClientTimeout||1800,...e.maxConnectionsPercent&&{MaxConnectionsPercent:e.maxConnectionsPercent},...e.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:e.maxIdleConnectionsPercent},...e.connectionBorrowTimeout&&{ConnectionBorrowTimeout:e.connectionBorrowTimeout}}}}generateProxyTargetCF(e,n){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:n.name,TargetGroupName:"default",DBInstanceIdentifiers:[e.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 ap=new Ba;class Nl{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(e){let n=`pi-${Date.now()}-${this.insightsCounter++}`,r={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,retentionPeriod:e.retentionPeriod||7,kmsKeyId:e.kmsKeyId};return this.insights.set(n,r),r}enableSlowQueryLog(e){let n=`slow-query-${Date.now()}-${this.logCounter++}`,r={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,logDestination:e.logDestination,cloudwatchLogGroup:e.cloudwatchLogGroup,s3Bucket:e.s3Bucket,s3Prefix:e.s3Bucket?"slow-queries/":void 0,minExecutionTime:e.minExecutionTime||1000};return this.slowQueryLogs.set(n,r),r}recordQueryMetric(e){let n=`metric-${Date.now()}-${this.metricCounter++}`,r={id:n,timestamp:new Date,...e};return this.queryMetrics.set(n,r),r}generatePerformanceReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r={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)},i=Array.from(this.queryMetrics.values()),s=i.sort((d,m)=>m.executionCount-d.executionCount).slice(0,10),a=i.filter((d)=>d.avgExecutionTime>1000).sort((d,m)=>m.avgExecutionTime-d.avgExecutionTime).slice(0,10),c=this.generateRecommendations(r,a),u={id:n,name:e.name,databaseIdentifier:e.databaseIdentifier,reportType:e.reportType,metrics:r,topQueries:s,slowQueries:a,recommendations:c,generatedAt:new Date};return this.reports.set(n,u),u}generateRecommendations(e,n){let r=[];if(e.avgCPU>70)r.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${e.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(e.cacheHitRatio<95)r.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${e.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(e.deadlocks>0)r.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${e.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(n.length>0)r.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${n.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(e.avgReadLatency>10||e.avgWriteLatency>10)r.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 r}analyzeQuery(e){let n=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,r=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],i=[];if(e.toLowerCase().includes("select *"))i.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!e.toLowerCase().includes("where")&&e.toLowerCase().includes("select"))i.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:n,queryId:n,sql:e,executionPlan:r,bottlenecks:i,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:r[0].cost}}recommendIndex(e){let n=`index-rec-${Date.now()}-${this.recommendationCounter++}`,r=`idx_${e.tableName}_${e.columns.join("_")}`,i={id:n,tableName:e.tableName,columns:e.columns,reason:e.reason,estimatedImprovement:e.estimatedImprovement||50,estimatedSize:e.columns.length*10,createSQL:`CREATE INDEX ${r} ON ${e.tableName} (${e.columns.join(", ")});`};return this.indexRecommendations.set(n,i),i}getInsights(e){return this.insights.get(e)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(e){return this.slowQueryLogs.get(e)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(e){return this.reports.get(e)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(e){return{EnablePerformanceInsights:e.enabled,PerformanceInsightsRetentionPeriod:e.retentionPeriod,...e.kmsKeyId&&{PerformanceInsightsKMSKeyId:e.kmsKeyId}}}generateSlowQueryAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",...e.snsTopicArn&&{AlarmActions:[e.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 Of=new Nl;class xl{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(e){let n=`db-user-${Date.now()}-${this.userCounter++}`,r={id:n,createdAt:new Date,...e};return this.users.set(n,r),r}createReadOnlyUser(e){let n=e.tables?e.tables.map((r)=>({database:e.database,table:r,privileges:["SELECT"]})):[{database:e.database,privileges:["SELECT"]}];return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(e){let n=e.tables?e.tables.map((r)=>({database:e.database,table:r,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:e.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(e){return this.createUser({username:e.username,database:e.database,privileges:[{database:e.database,privileges:["ALL"]}],passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(e){let n=e.tables.map((r)=>({database:e.database,table:r.name,privileges:r.privileges}));return this.createUser({username:e.username,database:e.database,privileges:n,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(e){let n=`role-${Date.now()}-${this.roleCounter++}`,r={id:n,users:[],...e};return this.roles.set(n,r),r}assignUserToRole(e,n){let r=this.users.get(e),i=this.roles.get(n);if(!r)throw Error(`User not found: ${e}`);if(!i)throw Error(`Role not found: ${n}`);i.users.push(e);for(let s of i.privileges){let a=r.privileges.find((c)=>c.database===s.database&&c.table===s.table);if(a)a.privileges=Array.from(new Set([...a.privileges,...s.privileges]));else r.privileges.push({...s})}}grantPrivileges(e,n){let r=this.users.get(e);if(!r)return{success:!1,message:"User not found"};for(let i of n){let s=r.privileges.find((a)=>a.database===i.database&&a.table===i.table);if(s)s.privileges=Array.from(new Set([...s.privileges,...i.privileges]));else r.privileges.push(i)}return this.auditAccess({username:r.username,action:"GRANT",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(e,n){let r=this.users.get(e);if(!r)return{success:!1,message:"User not found"};for(let i of n){let s=r.privileges.findIndex((a)=>a.database===i.database&&a.table===i.table);if(s!==-1){let a=r.privileges[s];if(a.privileges=a.privileges.filter((c)=>!i.privileges.includes(c)),a.privileges.length===0)r.privileges.splice(s,1)}}return this.auditAccess({username:r.username,action:"REVOKE",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(e){let n=this.users.get(e);if(!n)return{success:!1};let r=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${n.username}-${Date.now()}`;return n.passwordSecretArn=r,n.lastRotated=new Date,console.log(`Password rotated for user: ${n.username}`),{success:!0,newSecretArn:r}}needsPasswordRotation(e){let n=this.users.get(e);if(!n||!n.rotationEnabled||!n.lastRotated||!n.rotationDays)return!1;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}auditAccess(e){let n=`audit-${Date.now()}-${this.auditCounter++}`,r={id:n,timestamp:new Date,...e};return this.audits.set(n,r),r}getUserAccessHistory(e,n=100){return Array.from(this.audits.values()).filter((r)=>r.username===e).sort((r,i)=>i.timestamp.getTime()-r.timestamp.getTime()).slice(0,n)}getFailedLoginAttempts(e,n=24){let r=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((i)=>i.username===e&&i.action==="LOGIN"&&!i.success&&i.timestamp.getTime()>r)}generateCreateUserSQL(e,n="postgres"){let r=[];if(n==="postgres"){r.push(`CREATE USER ${e.username} WITH PASSWORD '${e.passwordSecretArn}';`);for(let i of e.privileges)if(i.privileges.includes("ALL"))r.push(`GRANT ALL PRIVILEGES ON DATABASE ${i.database} TO ${e.username};`);else{let s=i.privileges.join(", ");if(i.table)r.push(`GRANT ${s} ON ${i.database}.${i.table} TO ${e.username};`);else r.push(`GRANT ${s} ON DATABASE ${i.database} TO ${e.username};`)}}else{r.push(`CREATE USER '${e.username}'@'%' IDENTIFIED BY '${e.passwordSecretArn}';`);for(let i of e.privileges){let s=i.privileges.includes("ALL")?"ALL PRIVILEGES":i.privileges.join(", "),a=i.table?`${i.database}.${i.table}`:`${i.database}.*`;r.push(`GRANT ${s} ON ${a} TO '${e.username}'@'%';`)}r.push("FLUSH PRIVILEGES;")}return r.join(`
3736
+ `)}getUser(e){return this.users.get(e)}listUsers(){return Array.from(this.users.values())}getRole(e){return this.roles.get(e)}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 $f=new xl;class _l{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(e){let n=`rotation-${Date.now()}-${this.rotationCounter++}`,r={id:n,...e};return this.rotations.set(n,r),r}enableRDSRotation(e){let n=this.createRotation({secretId:e.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:e.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(e.engine)});return n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),n}enableAPIKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:e.rotationDays||90,rotationLambdaArn:e.rotationLambdaArn})}enableOAuthRotation(e){return this.createRotation({secretId:e.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:e.rotationDays||60,rotationLambdaArn:e.rotationLambdaArn})}enableSSHKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:e.rotationDays||180,rotationLambdaArn:e.rotationLambdaArn})}createSchedule(e){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,r={id:n,...e};return this.schedules.set(n,r),r}async executeRotation(e){let n=this.rotations.get(e);if(!n)throw Error(`Rotation not found: ${e}`);console.log(`
3737
3737
  Executing rotation for secret: ${n.secretId}`),console.log(`Secret type: ${n.secretType}`),console.log(`Rotation interval: ${n.rotationDays} days`);try{console.log(`
3738
3738
  Rotation steps:`),console.log("1. Creating new secret version...");let r=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let i=n.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),n.lastRotated=new Date,n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),console.log(`
3739
3739
  ✓ Rotation completed successfully`),console.log(` New version: ${r}`),console.log(` Next rotation: ${n.nextRotation.toISOString()}`),{success:!0,secretId:n.secretId,oldVersion:i,newVersion:r,rotatedAt:new Date}}catch(r){return console.error(`
3740
- ✗ Rotation failed:`,r),{success:!1,secretId:n.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:r instanceof Error?r.message:String(r)}}}needsRotation(e){let n=this.rotations.get(e);if(!n||!n.rotationEnabled)return!1;if(!n.lastRotated)return!0;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((e)=>this.needsRotation(e.id))}generateRDSRotationLambdaArn(e){let n={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${n[e]||n.postgres}`}getRotation(e){return this.rotations.get(e)}listRotations(){return Array.from(this.rotations.values())}getSchedule(e){return this.schedules.get(e)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(e){return{RotationEnabled:e.rotationEnabled,RotationRules:{AutomaticallyAfterDays:e.rotationDays},...e.rotationLambdaArn&&{RotationLambdaARN:e.rotationLambdaArn}}}generateRotationLambdaCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.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"}},...e.vpcConfig&&{VpcConfig:{SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.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(e){return{Type:"AWS::Events::Rule",Properties:{Name:e.name,Description:`Rotation schedule for ${e.secrets.length} secrets`,ScheduleExpression:e.schedule,State:e.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:e.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var xf=new Dl;class La{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(e){let n=`version-${Date.now()}-${this.versionCounter++}`,r={id:n,...e};return this.versions.set(n,r),this.auditAction({secretId:e.secretId,action:"CREATE",actor:"system",versionId:e.versionId,success:!0}),r}getVersionByStage(e,n){return Array.from(this.versions.values()).find((r)=>r.secretId===e&&r.versionStages.includes(n))}listVersions(e){return Array.from(this.versions.values()).filter((n)=>n.secretId===e).sort((n,r)=>r.createdAt.getTime()-n.createdAt.getTime())}deprecateVersion(e){let n=Array.from(this.versions.values()).find((r)=>r.versionId===e);if(n)n.deprecatedAt=new Date,n.versionStages=n.versionStages.filter((r)=>r!=="AWSCURRENT"),this.auditAction({secretId:n.secretId,action:"UPDATE",actor:"system",versionId:e,success:!0})}restoreVersion(e){let n=Array.from(this.versions.values()).find((r)=>r.versionId===e);if(n)Array.from(this.versions.values()).filter((r)=>r.secretId===n.secretId&&r.versionId!==e).forEach((r)=>{r.versionStages=r.versionStages.filter((i)=>i!=="AWSCURRENT")}),n.versionStages.push("AWSCURRENT"),n.deprecatedAt=void 0,this.auditAction({secretId:n.secretId,action:"RESTORE",actor:"system",versionId:e,success:!0})}auditAction(e){let n=`audit-${Date.now()}-${this.auditCounter++}`,r={id:n,timestamp:new Date,...e};return this.audits.set(n,r),r}getAuditTrail(e,n=100){return Array.from(this.audits.values()).filter((r)=>r.secretId===e).sort((r,i)=>i.timestamp.getTime()-r.timestamp.getTime()).slice(0,n)}getFailedAccesses(e,n=24){let r=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((i)=>i.secretId===e&&!i.success&&i.timestamp.getTime()>r)}registerExternalManager(e){let n=`ext-manager-${Date.now()}-${this.managerCounter++}`,r={id:n,...e};return this.externalManagers.set(n,r),r}registerVault(e){return this.registerExternalManager({type:"vault",name:e.name,endpoint:e.endpoint,authentication:{type:e.token?"token":"iam",credentials:e.token?{token:e.token}:void 0,roleArn:e.roleArn},syncEnabled:e.syncEnabled||!1,syncInterval:60})}registerOnePassword(e){return this.registerExternalManager({type:"onepassword",name:e.name,endpoint:e.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:e.apiKey}},syncEnabled:e.syncEnabled||!1,syncInterval:30})}enableReplication(e){let n=`replication-${Date.now()}-${this.replicationCounter++}`,r={id:n,secretId:e.secretId,sourceRegion:e.sourceRegion,replicaRegions:e.replicaRegions,kmsKeyIds:e.kmsKeyIds,status:"replicating"};return this.replications.set(n,r),this.auditAction({secretId:e.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{r.status="completed"},100),r}createPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,secretId:e.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:e.allowedPrincipals},Action:e.allowedActions,Resource:"*"}]}};return this.policies.set(n,r),r}createCrossAccountPolicy(e){let n=e.roleNames.map((r)=>`arn:aws:iam::${e.accountId}:role/${r}`);return this.createPolicy({secretId:e.secretId,allowedPrincipals:n,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(e){return this.versions.get(e)}getExternalManager(e){return this.externalManagers.get(e)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(e){return this.replications.get(e)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(e){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:e.name,Description:e.description,...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId},...e.replicaRegions&&{ReplicaRegions:e.replicaRegions.map((n)=>({Region:n}))}}}}generateSecretPolicyCF(e){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:e.secretId,ResourcePolicy:e.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 ip=new La;class Nl{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(e){let n=`cert-${Date.now()}-${this.certificateCounter++}`,r=`arn:aws:acm:us-east-1:123456789012:certificate/${n}`,i={id:n,arn:r,domainName:e.domainName,subjectAlternativeNames:e.subjectAlternativeNames,validationMethod:e.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(n,i),this.createValidation(i),i}requestWildcardCertificate(e){let n=[];if(e.includeApex)n.push(e.domainName.replace("*.",""));return this.requestCertificate({domainName:e.domainName,subjectAlternativeNames:n.length>0?n:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(e){return this.requestCertificate({domainName:e.primaryDomain,subjectAlternativeNames:e.additionalDomains,validationMethod:e.validationMethod||"DNS"})}createValidation(e){let n={domainName:e.domainName,validationMethod:e.validationMethod,validationStatus:"PENDING"};if(e.validationMethod==="DNS")n.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${e.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else n.validationEmails=[`admin@${e.domainName}`,`administrator@${e.domainName}`,`hostmaster@${e.domainName}`];return this.validations.set(e.id,n),n}validateCertificate(e){let n=this.certificates.get(e),r=this.validations.get(e);if(!n||!r)return{success:!1,message:"Certificate or validation not found"};return r.validationStatus="SUCCESS",n.status="ISSUED",n.issuedAt=new Date,n.expiresAt=new Date(Date.now()+31536000000),n.renewalEligibility=!0,n.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(e){let n=`renewal-${Date.now()}-${this.renewalCounter++}`,r={id:n,certificateArn:e.certificateArn,autoRenew:!0,renewBeforeDays:e.renewBeforeDays||30};return this.renewals.set(n,r),r}async renewCertificate(e){let n=this.renewals.get(e);if(!n)return{success:!1,message:"Renewal configuration not found"};let r=Array.from(this.certificates.values()).find((i)=>i.arn===n.certificateArn);if(!r)return{success:!1,message:"Certificate not found"};console.log(`
3740
+ ✗ Rotation failed:`,r),{success:!1,secretId:n.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:r instanceof Error?r.message:String(r)}}}needsRotation(e){let n=this.rotations.get(e);if(!n||!n.rotationEnabled)return!1;if(!n.lastRotated)return!0;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((e)=>this.needsRotation(e.id))}generateRDSRotationLambdaArn(e){let n={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${n[e]||n.postgres}`}getRotation(e){return this.rotations.get(e)}listRotations(){return Array.from(this.rotations.values())}getSchedule(e){return this.schedules.get(e)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(e){return{RotationEnabled:e.rotationEnabled,RotationRules:{AutomaticallyAfterDays:e.rotationDays},...e.rotationLambdaArn&&{RotationLambdaARN:e.rotationLambdaArn}}}generateRotationLambdaCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.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"}},...e.vpcConfig&&{VpcConfig:{SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.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(e){return{Type:"AWS::Events::Rule",Properties:{Name:e.name,Description:`Rotation schedule for ${e.secrets.length} secrets`,ScheduleExpression:e.schedule,State:e.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:e.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var Lf=new _l;class Fa{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(e){let n=`version-${Date.now()}-${this.versionCounter++}`,r={id:n,...e};return this.versions.set(n,r),this.auditAction({secretId:e.secretId,action:"CREATE",actor:"system",versionId:e.versionId,success:!0}),r}getVersionByStage(e,n){return Array.from(this.versions.values()).find((r)=>r.secretId===e&&r.versionStages.includes(n))}listVersions(e){return Array.from(this.versions.values()).filter((n)=>n.secretId===e).sort((n,r)=>r.createdAt.getTime()-n.createdAt.getTime())}deprecateVersion(e){let n=Array.from(this.versions.values()).find((r)=>r.versionId===e);if(n)n.deprecatedAt=new Date,n.versionStages=n.versionStages.filter((r)=>r!=="AWSCURRENT"),this.auditAction({secretId:n.secretId,action:"UPDATE",actor:"system",versionId:e,success:!0})}restoreVersion(e){let n=Array.from(this.versions.values()).find((r)=>r.versionId===e);if(n)Array.from(this.versions.values()).filter((r)=>r.secretId===n.secretId&&r.versionId!==e).forEach((r)=>{r.versionStages=r.versionStages.filter((i)=>i!=="AWSCURRENT")}),n.versionStages.push("AWSCURRENT"),n.deprecatedAt=void 0,this.auditAction({secretId:n.secretId,action:"RESTORE",actor:"system",versionId:e,success:!0})}auditAction(e){let n=`audit-${Date.now()}-${this.auditCounter++}`,r={id:n,timestamp:new Date,...e};return this.audits.set(n,r),r}getAuditTrail(e,n=100){return Array.from(this.audits.values()).filter((r)=>r.secretId===e).sort((r,i)=>i.timestamp.getTime()-r.timestamp.getTime()).slice(0,n)}getFailedAccesses(e,n=24){let r=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((i)=>i.secretId===e&&!i.success&&i.timestamp.getTime()>r)}registerExternalManager(e){let n=`ext-manager-${Date.now()}-${this.managerCounter++}`,r={id:n,...e};return this.externalManagers.set(n,r),r}registerVault(e){return this.registerExternalManager({type:"vault",name:e.name,endpoint:e.endpoint,authentication:{type:e.token?"token":"iam",credentials:e.token?{token:e.token}:void 0,roleArn:e.roleArn},syncEnabled:e.syncEnabled||!1,syncInterval:60})}registerOnePassword(e){return this.registerExternalManager({type:"onepassword",name:e.name,endpoint:e.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:e.apiKey}},syncEnabled:e.syncEnabled||!1,syncInterval:30})}enableReplication(e){let n=`replication-${Date.now()}-${this.replicationCounter++}`,r={id:n,secretId:e.secretId,sourceRegion:e.sourceRegion,replicaRegions:e.replicaRegions,kmsKeyIds:e.kmsKeyIds,status:"replicating"};return this.replications.set(n,r),this.auditAction({secretId:e.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{r.status="completed"},100),r}createPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,secretId:e.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:e.allowedPrincipals},Action:e.allowedActions,Resource:"*"}]}};return this.policies.set(n,r),r}createCrossAccountPolicy(e){let n=e.roleNames.map((r)=>`arn:aws:iam::${e.accountId}:role/${r}`);return this.createPolicy({secretId:e.secretId,allowedPrincipals:n,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(e){return this.versions.get(e)}getExternalManager(e){return this.externalManagers.get(e)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(e){return this.replications.get(e)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(e){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:e.name,Description:e.description,...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId},...e.replicaRegions&&{ReplicaRegions:e.replicaRegions.map((n)=>({Region:n}))}}}}generateSecretPolicyCF(e){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:e.secretId,ResourcePolicy:e.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 cp=new Fa;class Ol{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(e){let n=`cert-${Date.now()}-${this.certificateCounter++}`,r=`arn:aws:acm:us-east-1:123456789012:certificate/${n}`,i={id:n,arn:r,domainName:e.domainName,subjectAlternativeNames:e.subjectAlternativeNames,validationMethod:e.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(n,i),this.createValidation(i),i}requestWildcardCertificate(e){let n=[];if(e.includeApex)n.push(e.domainName.replace("*.",""));return this.requestCertificate({domainName:e.domainName,subjectAlternativeNames:n.length>0?n:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(e){return this.requestCertificate({domainName:e.primaryDomain,subjectAlternativeNames:e.additionalDomains,validationMethod:e.validationMethod||"DNS"})}createValidation(e){let n={domainName:e.domainName,validationMethod:e.validationMethod,validationStatus:"PENDING"};if(e.validationMethod==="DNS")n.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${e.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else n.validationEmails=[`admin@${e.domainName}`,`administrator@${e.domainName}`,`hostmaster@${e.domainName}`];return this.validations.set(e.id,n),n}validateCertificate(e){let n=this.certificates.get(e),r=this.validations.get(e);if(!n||!r)return{success:!1,message:"Certificate or validation not found"};return r.validationStatus="SUCCESS",n.status="ISSUED",n.issuedAt=new Date,n.expiresAt=new Date(Date.now()+31536000000),n.renewalEligibility=!0,n.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(e){let n=`renewal-${Date.now()}-${this.renewalCounter++}`,r={id:n,certificateArn:e.certificateArn,autoRenew:!0,renewBeforeDays:e.renewBeforeDays||30};return this.renewals.set(n,r),r}async renewCertificate(e){let n=this.renewals.get(e);if(!n)return{success:!1,message:"Renewal configuration not found"};let r=Array.from(this.certificates.values()).find((i)=>i.arn===n.certificateArn);if(!r)return{success:!1,message:"Certificate not found"};console.log(`
3741
3741
  Renewing certificate: ${r.domainName}`),console.log(`Certificate ARN: ${r.arn}`);try{return console.log(`
3742
3742
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),r.issuedAt=new Date,r.expiresAt=new Date(Date.now()+31536000000),n.lastRenewal=new Date,n.renewalStatus="success",n.nextRenewal=new Date(r.expiresAt.getTime()-n.renewBeforeDays*24*60*60*1000),console.log(`
3743
- ✓ Certificate renewed successfully`),console.log(` New expiration: ${r.expiresAt.toISOString()}`),console.log(` Next renewal: ${n.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(i){return n.renewalStatus="failed",this.createAlert({certificateArn:r.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${i}`}),{success:!1,message:i instanceof Error?i.message:String(i)}}}createMonitor(e){let n=`monitor-${Date.now()}-${this.monitorCounter++}`,r={id:n,...e};return this.monitors.set(n,r),r}checkExpiration(){let e=[],n=Date.now();for(let r of this.certificates.values()){if(!r.expiresAt)continue;let i=(r.expiresAt.getTime()-n)/86400000;if(i<0)e.push(this.createAlert({certificateArn:r.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${r.domainName}`}));else if(i<30)e.push(this.createAlert({certificateArn:r.arn,alertType:"expiring_soon",severity:i<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(i)} days for ${r.domainName}`}))}return e}createAlert(e){let n=`alert-${Date.now()}-${this.alertCounter++}`,r={id:n,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(n,r),r}acknowledgeAlert(e){let n=this.alerts.get(e);if(n)n.acknowledged=!0}getCertificate(e){return this.certificates.get(e)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(e=30){let n=Date.now()+e*24*60*60*1000;return Array.from(this.certificates.values()).filter((r)=>r.expiresAt&&r.expiresAt.getTime()<n)}getValidation(e){return this.validations.get(e)}getRenewal(e){return this.renewals.get(e)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(e=!1){return Array.from(this.alerts.values()).filter((n)=>n.acknowledged===e)}generateCertificateCF(e){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:e.domainName,...e.subjectAlternativeNames&&{SubjectAlternativeNames:e.subjectAlternativeNames},ValidationMethod:e.validationMethod}}}generateExpirationAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`Certificate expiring in ${e.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:e.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:e.certificateArn}],...e.snsTopicArn&&{AlarmActions:[e.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 _f=new Nl;class kl{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(e){let n=`scan-${Date.now()}-${this.scanCounter++}`,r={id:n,status:"queued",findings:[],...e};return this.scans.set(n,r),r}createContainerScan(e){return this.createScan({name:e.name,scanType:"container_image",target:{type:"ecr_image",identifier:e.imageUri,region:e.region||"us-east-1"}})}createLambdaScan(e){return this.createScan({name:e.name,scanType:"vulnerability",target:{type:"lambda",identifier:e.functionName,region:e.region||"us-east-1"}})}createSecretsDetectionScan(e){return this.createScan({name:e.name,scanType:"secrets_detection",target:{type:"repository",identifier:e.repositoryUrl}})}async executeScan(e){let n=this.scans.get(e);if(!n)throw Error(`Scan not found: ${e}`);console.log(`
3743
+ ✓ Certificate renewed successfully`),console.log(` New expiration: ${r.expiresAt.toISOString()}`),console.log(` Next renewal: ${n.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(i){return n.renewalStatus="failed",this.createAlert({certificateArn:r.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${i}`}),{success:!1,message:i instanceof Error?i.message:String(i)}}}createMonitor(e){let n=`monitor-${Date.now()}-${this.monitorCounter++}`,r={id:n,...e};return this.monitors.set(n,r),r}checkExpiration(){let e=[],n=Date.now();for(let r of this.certificates.values()){if(!r.expiresAt)continue;let i=(r.expiresAt.getTime()-n)/86400000;if(i<0)e.push(this.createAlert({certificateArn:r.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${r.domainName}`}));else if(i<30)e.push(this.createAlert({certificateArn:r.arn,alertType:"expiring_soon",severity:i<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(i)} days for ${r.domainName}`}))}return e}createAlert(e){let n=`alert-${Date.now()}-${this.alertCounter++}`,r={id:n,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(n,r),r}acknowledgeAlert(e){let n=this.alerts.get(e);if(n)n.acknowledged=!0}getCertificate(e){return this.certificates.get(e)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(e=30){let n=Date.now()+e*24*60*60*1000;return Array.from(this.certificates.values()).filter((r)=>r.expiresAt&&r.expiresAt.getTime()<n)}getValidation(e){return this.validations.get(e)}getRenewal(e){return this.renewals.get(e)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(e=!1){return Array.from(this.alerts.values()).filter((n)=>n.acknowledged===e)}generateCertificateCF(e){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:e.domainName,...e.subjectAlternativeNames&&{SubjectAlternativeNames:e.subjectAlternativeNames},ValidationMethod:e.validationMethod}}}generateExpirationAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`Certificate expiring in ${e.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:e.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:e.certificateArn}],...e.snsTopicArn&&{AlarmActions:[e.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 Mf=new Ol;class $l{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(e){let n=`scan-${Date.now()}-${this.scanCounter++}`,r={id:n,status:"queued",findings:[],...e};return this.scans.set(n,r),r}createContainerScan(e){return this.createScan({name:e.name,scanType:"container_image",target:{type:"ecr_image",identifier:e.imageUri,region:e.region||"us-east-1"}})}createLambdaScan(e){return this.createScan({name:e.name,scanType:"vulnerability",target:{type:"lambda",identifier:e.functionName,region:e.region||"us-east-1"}})}createSecretsDetectionScan(e){return this.createScan({name:e.name,scanType:"secrets_detection",target:{type:"repository",identifier:e.repositoryUrl}})}async executeScan(e){let n=this.scans.get(e);if(!n)throw Error(`Scan not found: ${e}`);console.log(`
3744
3744
  Executing security scan: ${n.name}`),console.log(`Scan type: ${n.scanType}`),console.log(`Target: ${n.target.type} - ${n.target.identifier}`),n.status="running",n.startedAt=new Date;try{console.log(`
3745
3745
  Scanning...`);let r=this.simulateFindings(n);return n.findings=r,n.status="completed",n.completedAt=new Date,n.summary={totalFindings:r.length,criticalCount:r.filter((i)=>i.severity==="CRITICAL").length,highCount:r.filter((i)=>i.severity==="HIGH").length,mediumCount:r.filter((i)=>i.severity==="MEDIUM").length,lowCount:r.filter((i)=>i.severity==="LOW").length,infoCount:r.filter((i)=>i.severity==="INFO").length,executionTime:n.completedAt.getTime()-n.startedAt.getTime()},console.log(`
3746
- ✓ Scan completed`),console.log(` Findings: ${n.summary.totalFindings}`),console.log(` Critical: ${n.summary.criticalCount}`),console.log(` High: ${n.summary.highCount}`),console.log(` Medium: ${n.summary.mediumCount}`),console.log(` Low: ${n.summary.lowCount}`),n}catch(r){throw n.status="failed",n.completedAt=new Date,r}}simulateFindings(e){let n=[],r=new Date;if(e.scanType==="container_image")n.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:e.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:r,lastSeen:r})),n.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:e.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:r,lastSeen:r}));else if(e.scanType==="secrets_detection")n.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${e.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:r,lastSeen:r}));return n}createFinding(e){let n=`finding-${Date.now()}-${this.findingCounter++}`,r={id:n,...e};return this.findings.set(n,r),r}suppressFinding(e,n){let r=this.findings.get(e);if(r){if(r.status="SUPPRESSED",console.log(`Finding suppressed: ${r.title}`),n)console.log(`Reason: ${n}`)}}resolveFinding(e){let n=this.findings.get(e);if(n)n.status="RESOLVED",console.log(`Finding resolved: ${n.title}`)}generateReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r={id:n,scanId:e.scanId,reportType:e.reportType,format:e.format,generatedAt:new Date,s3Location:`s3://security-reports/${n}.${e.format}`};return this.reports.set(n,r),r}runComplianceCheck(e){let n=[];if(e.framework.includes("CIS"))n.push(this.createComplianceCheck({framework:e.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:e.resourceType,resourceId:e.resourceId})),n.push(this.createComplianceCheck({framework:e.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:e.resourceType,resourceId:e.resourceId,remediation:"Enable CloudTrail in all regions"}));return n}createComplianceCheck(e){let n=`check-${Date.now()}-${this.checkCounter++}`,r={id:n,...e};return this.complianceChecks.set(n,r),r}assessSecurityPosture(e){let n=`posture-${Date.now()}-${this.postureCounter++}`,r=Array.from(this.complianceChecks.values()),i=r.filter((d)=>d.status==="PASS").length,s=r.length,a=s>0?Math.round(i/s*100):0,c;if(a>=90)c="A";else if(a>=80)c="B";else if(a>=70)c="C";else if(a>=60)c="D";else c="F";let u={id:n,accountId:e.accountId,region:e.region,score:a,grade:c,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(n,u),u}getScan(e){return this.scans.get(e)}listScans(){return Array.from(this.scans.values())}getOpenFindings(e){return Array.from(this.findings.values()).filter((n)=>n.status==="OPEN"&&(!e||n.severity===e))}getComplianceChecksByStatus(e){return Array.from(this.complianceChecks.values()).filter((n)=>n.status===e)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e,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 Of=new kl;class xl{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(e){let n=`scan-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}configureTrivyScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"trivy",scanOnPush:e.scanOnPush??!0,ignoreUnfixed:e.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"snyk",scanOnPush:e.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(e){return this.configureScan({repository:e.repository,imageTag:"latest",scanner:"ecr",scanOnPush:e.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(e){let n=this.configs.get(e);if(!n)throw Error(`Scan config not found: ${e}`);let r=`${n.repository}:${n.imageTag}`;console.log(`
3746
+ ✓ Scan completed`),console.log(` Findings: ${n.summary.totalFindings}`),console.log(` Critical: ${n.summary.criticalCount}`),console.log(` High: ${n.summary.highCount}`),console.log(` Medium: ${n.summary.mediumCount}`),console.log(` Low: ${n.summary.lowCount}`),n}catch(r){throw n.status="failed",n.completedAt=new Date,r}}simulateFindings(e){let n=[],r=new Date;if(e.scanType==="container_image")n.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:e.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:r,lastSeen:r})),n.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:e.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:r,lastSeen:r}));else if(e.scanType==="secrets_detection")n.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${e.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:r,lastSeen:r}));return n}createFinding(e){let n=`finding-${Date.now()}-${this.findingCounter++}`,r={id:n,...e};return this.findings.set(n,r),r}suppressFinding(e,n){let r=this.findings.get(e);if(r){if(r.status="SUPPRESSED",console.log(`Finding suppressed: ${r.title}`),n)console.log(`Reason: ${n}`)}}resolveFinding(e){let n=this.findings.get(e);if(n)n.status="RESOLVED",console.log(`Finding resolved: ${n.title}`)}generateReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r={id:n,scanId:e.scanId,reportType:e.reportType,format:e.format,generatedAt:new Date,s3Location:`s3://security-reports/${n}.${e.format}`};return this.reports.set(n,r),r}runComplianceCheck(e){let n=[];if(e.framework.includes("CIS"))n.push(this.createComplianceCheck({framework:e.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:e.resourceType,resourceId:e.resourceId})),n.push(this.createComplianceCheck({framework:e.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:e.resourceType,resourceId:e.resourceId,remediation:"Enable CloudTrail in all regions"}));return n}createComplianceCheck(e){let n=`check-${Date.now()}-${this.checkCounter++}`,r={id:n,...e};return this.complianceChecks.set(n,r),r}assessSecurityPosture(e){let n=`posture-${Date.now()}-${this.postureCounter++}`,r=Array.from(this.complianceChecks.values()),i=r.filter((d)=>d.status==="PASS").length,s=r.length,a=s>0?Math.round(i/s*100):0,c;if(a>=90)c="A";else if(a>=80)c="B";else if(a>=70)c="C";else if(a>=60)c="D";else c="F";let u={id:n,accountId:e.accountId,region:e.region,score:a,grade:c,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(n,u),u}getScan(e){return this.scans.get(e)}listScans(){return Array.from(this.scans.values())}getOpenFindings(e){return Array.from(this.findings.values()).filter((n)=>n.status==="OPEN"&&(!e||n.severity===e))}getComplianceChecksByStatus(e){return Array.from(this.complianceChecks.values()).filter((n)=>n.status===e)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e,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 Uf=new $l;class Ll{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(e){let n=`scan-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}configureTrivyScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"trivy",scanOnPush:e.scanOnPush??!0,ignoreUnfixed:e.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"snyk",scanOnPush:e.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(e){return this.configureScan({repository:e.repository,imageTag:"latest",scanner:"ecr",scanOnPush:e.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(e){let n=this.configs.get(e);if(!n)throw Error(`Scan config not found: ${e}`);let r=`${n.repository}:${n.imageTag}`;console.log(`
3747
3747
  Scanning image: ${r}`),console.log(`Scanner: ${n.scanner}`);let i=`scan-result-${Date.now()}-${this.resultCounter++}`,s=this.simulateVulnerabilities(n),a={total:s.length,critical:s.filter((d)=>d.severity==="CRITICAL").length,high:s.filter((d)=>d.severity==="HIGH").length,medium:s.filter((d)=>d.severity==="MEDIUM").length,low:s.filter((d)=>d.severity==="LOW").length,unknown:s.filter((d)=>d.severity==="UNKNOWN").length},c=this.evaluateScanResult(n,a),u={id:i,imageUri:r,scannerType:n.scanner,scanDate:new Date,vulnerabilities:s,summary:a,passed:c};return this.results.set(i,u),console.log(`
3748
- Scan Results:`),console.log(` Total vulnerabilities: ${a.total}`),console.log(` Critical: ${a.critical}`),console.log(` High: ${a.high}`),console.log(` Medium: ${a.medium}`),console.log(` Low: ${a.low}`),console.log(` Status: ${c?"✓ PASSED":"✗ FAILED"}`),u}simulateVulnerabilities(e){let n=[];if(e.scanner==="trivy"||e.scanner==="ecr")n.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}),n.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 n}evaluateScanResult(e,n){if(!e.failOnSeverity)return!0;switch(e.failOnSeverity){case"CRITICAL":return n.critical===0;case"HIGH":return n.critical===0&&n.high===0;case"MEDIUM":return n.critical===0&&n.high===0&&n.medium===0;case"LOW":return n.total===0;default:return!0}}createPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,...e};return this.policies.set(n,r),r}createStrictPolicy(e){return this.createPolicy({name:e,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(e){return this.createPolicy({name:e,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getResult(e){return this.results.get(e)}listResults(){return Array.from(this.results.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.repository,ImageScanningConfiguration:{ScanOnPush:e.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 $f=new xl;class _l{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(e){let n=`build-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createOptimizedBuildConfig(e){let n={type:e.enableCache?"registry":"inline",cacheFrom:e.registry?[`${e.registry}/cache`]:void 0,cacheTo:e.registry?`${e.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:e.name,dockerfile:e.dockerfile,context:".",cacheStrategy:n,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(e){let n=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,r={id:n,...e};return this.multiStageConfigs.set(n,r),r}createNodeMultiStageBuild(e){let n=e.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:e.name,targetStage:e.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${n}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(e){let n=this.multiStageConfigs.get(e);if(!n)throw Error(`Multi-stage config not found: ${e}`);let r=[];for(let i of n.stages){if(r.push(`# Stage: ${i.name}`),r.push(`FROM ${i.baseImage} AS ${i.name}`),i.workdir)r.push(`WORKDIR ${i.workdir}`);if(i.env)for(let[s,a]of Object.entries(i.env))r.push(`ENV ${s}=${a}`);for(let s of i.commands)r.push(s);r.push("")}return r.join(`
3748
+ Scan Results:`),console.log(` Total vulnerabilities: ${a.total}`),console.log(` Critical: ${a.critical}`),console.log(` High: ${a.high}`),console.log(` Medium: ${a.medium}`),console.log(` Low: ${a.low}`),console.log(` Status: ${c?"✓ PASSED":"✗ FAILED"}`),u}simulateVulnerabilities(e){let n=[];if(e.scanner==="trivy"||e.scanner==="ecr")n.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}),n.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 n}evaluateScanResult(e,n){if(!e.failOnSeverity)return!0;switch(e.failOnSeverity){case"CRITICAL":return n.critical===0;case"HIGH":return n.critical===0&&n.high===0;case"MEDIUM":return n.critical===0&&n.high===0&&n.medium===0;case"LOW":return n.total===0;default:return!0}}createPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,...e};return this.policies.set(n,r),r}createStrictPolicy(e){return this.createPolicy({name:e,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(e){return this.createPolicy({name:e,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getResult(e){return this.results.get(e)}listResults(){return Array.from(this.results.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.repository,ImageScanningConfiguration:{ScanOnPush:e.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 Bf=new Ll;class Ml{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(e){let n=`build-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createOptimizedBuildConfig(e){let n={type:e.enableCache?"registry":"inline",cacheFrom:e.registry?[`${e.registry}/cache`]:void 0,cacheTo:e.registry?`${e.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:e.name,dockerfile:e.dockerfile,context:".",cacheStrategy:n,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(e){let n=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,r={id:n,...e};return this.multiStageConfigs.set(n,r),r}createNodeMultiStageBuild(e){let n=e.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:e.name,targetStage:e.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${n}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(e){let n=this.multiStageConfigs.get(e);if(!n)throw Error(`Multi-stage config not found: ${e}`);let r=[];for(let i of n.stages){if(r.push(`# Stage: ${i.name}`),r.push(`FROM ${i.baseImage} AS ${i.name}`),i.workdir)r.push(`WORKDIR ${i.workdir}`);if(i.env)for(let[s,a]of Object.entries(i.env))r.push(`ENV ${s}=${a}`);for(let s of i.commands)r.push(s);r.push("")}return r.join(`
3749
3749
  `)}analyzeImage(e,n){let r=`analysis-${Date.now()}-${this.analysisCounter++}`,i=n.map((u)=>({...u,cacheable:this.isLayerCacheable(u.command)})),s=i.reduce((u,d)=>u+d.size,0),a=i.filter((u)=>!u.cacheable&&u.size>100).length,c={id:r,imageId:e,layers:i,totalSize:s,unnecessaryLayers:a};return this.analyses.set(r,c),c}isLayerCacheable(e){let n=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],r=["CMD","ENTRYPOINT","LABEL"];for(let i of n)if(e.startsWith(i))return!0;for(let i of r)if(e.startsWith(i))return!1;return!1}generateOptimizations(e){let n=this.analyses.get(e);if(!n)throw Error(`Analysis not found: ${e}`);let r=`optimization-${Date.now()}-${this.optimizationCounter++}`,i=[],s=n.layers.filter((m)=>m.command.startsWith("RUN"));if(s.length>5)i.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${s.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 a=n.layers[0];if(a.command.includes("ubuntu")||a.command.includes("debian"))i.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 c=n.layers.filter((m)=>m.command.startsWith("COPY"));if(c.length>0&&c[0].index>3)i.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 ./
3750
3750
  RUN npm install
3751
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let u={sizeBefore:n.totalSize,sizeAfter:n.totalSize*0.6,timeBefore:300,timeAfter:120},d={id:r,name:`Optimization for ${n.imageId}`,recommendations:i,estimatedSavings:u};return this.optimizations.set(r,d),d}getBuildConfig(e){return this.configs.get(e)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(e){return this.multiStageConfigs.get(e)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(e){return this.optimizations.get(e)}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 Lf=new _l;class Ma{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(e){let n=`registry-${Date.now()}-${this.registryCounter++}`,r={id:n,...e};return this.registries.set(n,r),r}createECRRepository(e){return this.createRegistry({name:e.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${e.region||"us-east-1"}.amazonaws.com/${e.name}`,region:e.region||"us-east-1",encryption:{encryptionType:e.encryption||"AES256",kmsKeyId:e.kmsKeyId},scanning:{scanOnPush:e.scanOnPush??!0}})}createManagedRepository(e){let n=this.createECRRepository({name:e.name,region:e.region,scanOnPush:!0,encryption:"KMS"});return n.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},n}enableReplication(e,n){let r=this.registries.get(e);if(!r)throw Error(`Registry not found: ${e}`);return r.replication={enabled:!0,destinations:n},r}createCredentials(e){let n=`creds-${Date.now()}-${this.credentialsCounter++}`,r={id:n,...e};return this.credentials.set(n,r),r}getRegistry(e){return this.registries.get(e)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.name,ImageScanningConfiguration:{ScanOnPush:e.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:e.encryption?.encryptionType||"AES256",...e.encryption?.kmsKeyId&&{KmsKey:e.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...e.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:e.lifecycle.rules})}}}}}generateReplicationConfigCF(e){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:e.destinations.map((n)=>({Destinations:[{Region:n.region,...n.registryId&&{RegistryId:n.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var op=new Ma;class Ua{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(e){let n=`mesh-${Date.now()}-${this.meshCounter++}`,r={id:n,...e};return this.meshes.set(n,r),r}createAppMesh(e){return this.createMesh({name:e.name,meshType:"app_mesh",services:e.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(e){let n=`vnode-${Date.now()}-${this.nodeCounter++}`,r={id:n,...e};return this.virtualNodes.set(n,r),r}createHTTPVirtualNode(e){return this.createVirtualNode({name:e.name,serviceName:e.serviceName,listeners:[{port:e.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:e.namespace,serviceName:e.serviceName}})}createVirtualRouter(e){let n=`vrouter-${Date.now()}-${this.routerCounter++}`,r={id:n,...e};return this.virtualRouters.set(n,r),r}createCanaryRoute(e){return this.createVirtualRouter({name:e.name,listeners:[{port:e.port,protocol:e.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:e.stableTarget,weight:100-e.canaryWeight},{virtualNode:e.canaryTarget,weight:e.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(e){let n=`vgateway-${Date.now()}-${this.gatewayCounter++}`,r={id:n,...e};return this.virtualGateways.set(n,r),r}createIngressGateway(e){let n={port:e.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(e.enableTLS&&e.certificateArn)n.tls={mode:"STRICT",certificate:{acm:e.certificateArn}};return this.createVirtualGateway({name:e.name,listeners:[n],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(e){return this.meshes.get(e)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(e){return this.virtualNodes.get(e)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(e){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:e.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(e,n){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:n,VirtualNodeName:e.name,Spec:{Listeners:e.listeners.map((r)=>({PortMapping:{Port:r.port,Protocol:r.protocol},...r.healthCheck&&{HealthCheck:{Protocol:r.healthCheck.protocol,...r.healthCheck.path&&{Path:r.healthCheck.path},IntervalMillis:r.healthCheck.interval*1000,TimeoutMillis:r.healthCheck.timeout*1000,HealthyThreshold:r.healthCheck.healthyThreshold,UnhealthyThreshold:r.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:e.serviceDiscovery.namespace,ServiceName:e.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(e,n){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:n,VirtualRouterName:e.name,Spec:{Listeners:e.listeners.map((r)=>({PortMapping:{Port:r.port,Protocol:r.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 sp=new Ua;class Ol{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(e){let n=`layer-${Date.now()}-${this.layerCounter++}`,r=1,i={id:n,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:1`,version:1,...e};return this.layers.set(n,i),i}createNodeDependenciesLayer(e){return this.createLayer({layerName:e.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${e.nodeVersion}`],content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:5242880})}createUtilitiesLayer(e){return this.createLayer({layerName:e.layerName,description:"Shared utilities and helpers",compatibleRuntimes:e.runtimes,content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:1048576})}publishVersion(e){let n=this.layers.get(e);if(!n)throw Error(`Layer not found: ${e}`);let r=`version-${Date.now()}-${this.versionCounter++}`,i=n.version+1,s={id:r,layerName:n.layerName,version:i,createdAt:new Date,compatibleRuntimes:n.compatibleRuntimes,size:n.size,codeHash:this.generateHash()};return this.versions.set(r,s),n.version=i,n.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${i}`,s}addPermission(e){let n=`permission-${Date.now()}-${this.permissionCounter++}`,r={id:n,layerName:e.layerName,version:e.version,principal:e.principal,action:"lambda:GetLayerVersion",organizationId:e.organizationId};return this.permissions.set(n,r),r}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(e){return this.layers.get(e)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(e){return Array.from(this.versions.values()).filter((n)=>n.layerName===e)}generateLayerCF(e){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:e.layerName,Description:e.description,Content:e.content.type==="s3"?{S3Bucket:e.content.s3Bucket,S3Key:e.content.s3Key,...e.content.s3ObjectVersion&&{S3ObjectVersion:e.content.s3ObjectVersion}}:{ZipFile:e.content.zipFile},CompatibleRuntimes:e.compatibleRuntimes,...e.licenseInfo&&{LicenseInfo:e.licenseInfo}}}}generateLayerPermissionCF(e){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:${e.version}`,Action:e.action,Principal:e.principal,...e.organizationId&&{OrganizationId:e.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var Mf=new Ol;class $l{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(e){let n=`version-${Date.now()}-${this.versionCounter++}`,r=this.getNextVersionNumber(e.functionName),i={id:n,functionName:e.functionName,version:r.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${r}`,codeHash:this.generateHash(),description:e.description,runtime:e.runtime,memorySize:e.memorySize,timeout:e.timeout,publishedAt:new Date};return this.versions.set(n,i),i}getNextVersionNumber(e){let n=Array.from(this.versions.values()).filter((r)=>r.functionName===e).map((r)=>parseInt(r.version));return n.length>0?Math.max(...n)+1:1}createAlias(e){let n=`alias-${Date.now()}-${this.aliasCounter++}`,r={id:n,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${e.aliasName}`,revisionId:this.generateHash(),...e};return this.aliases.set(n,r),r}createProductionAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"production",functionVersion:e.version,description:"Production alias"})}createStagingAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"staging",functionVersion:e.version,description:"Staging alias"})}updateAlias(e,n){let r=this.aliases.get(e);if(!r)throw Error(`Alias not found: ${e}`);return r.functionVersion=n,r.revisionId=this.generateHash(),r}configureWeightedRouting(e,n){let r=this.aliases.get(e);if(!r)throw Error(`Alias not found: ${e}`);return r.routingConfig={additionalVersionWeights:n},r}createCanaryDeployment(e){let n=`deployment-${Date.now()}-${this.deploymentCounter++}`,r=Array.from(this.aliases.values()).find((s)=>s.functionName===e.functionName&&s.aliasName===e.aliasName);if(!r)r=this.createAlias({functionName:e.functionName,aliasName:e.aliasName,functionVersion:e.fromVersion});this.configureWeightedRouting(r.id,{[e.toVersion]:e.canaryWeight});let i={id:n,functionName:e.functionName,fromVersion:e.fromVersion,toVersion:e.toVersion,aliasName:e.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(n,i),i}completeDeployment(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r=Array.from(this.aliases.values()).find((i)=>i.functionName===n.functionName&&i.aliasName===n.aliasName);if(r)r.functionVersion=n.toVersion,r.routingConfig=void 0;return n.status="completed",n.completedAt=new Date,n}rollbackDeployment(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r=Array.from(this.aliases.values()).find((i)=>i.functionName===n.functionName&&i.aliasName===n.aliasName);if(r)r.functionVersion=n.fromVersion,r.routingConfig=void 0;return n.status="failed",n.completedAt=new Date,n}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(e){return this.versions.get(e)}listVersions(e){let n=Array.from(this.versions.values());return e?n.filter((r)=>r.functionName===e):n}getAlias(e){return this.aliases.get(e)}listAliases(e){let n=Array.from(this.aliases.values());return e?n.filter((r)=>r.functionName===e):n}generateVersionCF(e){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:e.functionName,Description:e.description}}}generateAliasCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.aliasName,FunctionVersion:e.functionVersion,Description:e.description,...e.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(e.routingConfig.additionalVersionWeights||{}).map(([n,r])=>({FunctionVersion:n,FunctionWeight:r}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var Uf=new $l;class Ll{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(e){let n=`concurrency-${Date.now()}-${this.configCounter++}`,r={id:n,functionName:e.functionName,reservedConcurrency:e.reservedConcurrency};return this.configs.set(n,r),r}setProvisionedConcurrency(e){let n=`provisioned-${Date.now()}-${this.provisionedCounter++}`,r={id:n,functionName:e.functionName,qualifier:e.qualifier,provisionedConcurrentExecutions:e.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(n,r),setTimeout(()=>{r.status="ready",r.allocatedConcurrency=e.provisionedConcurrentExecutions,r.availableConcurrency=e.provisionedConcurrentExecutions},100),r}configureWarmPool(e){return this.setProvisionedConcurrency({functionName:e.functionName,qualifier:e.alias,provisionedConcurrentExecutions:e.minInstances})}createSchedule(e){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,r={id:n,...e};return this.schedules.set(n,r),r}createBusinessHoursSchedule(e){return this.createSchedule({name:`${e.functionName}-business-hours`,functionName:e.functionName,qualifier:e.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:e.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:e.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:e.offHoursConcurrency}]})}configureAutoScaling(e){let n=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,r={id:n,...e};return this.autoScalingConfigs.set(n,r),r}configurePredictiveScaling(e){return this.configureAutoScaling({functionName:e.functionName,qualifier:e.qualifier,minCapacity:e.baselineCapacity,maxCapacity:e.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(e){return this.provisionedConfigs.get(e)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.functionName,ReservedConcurrentExecutions:e.reservedConcurrency}}}generateProvisionedConcurrencyCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:e.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${e.functionName}:${e.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:e.minCapacity,MaxCapacity:e.maxCapacity}}}generateAutoScalingPolicyCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${e.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:e.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:e.scaleInCooldown||300,ScaleOutCooldown:e.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 Ff=new Ll;class Ml{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(e){let n=`destination-${Date.now()}-${this.destinationCounter++}`,r={id:n,...e};return this.destinations.set(n,r),r}configureSQSDestination(e){let n={type:"sqs",arn:e.queueArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(e){let n={type:"sns",arn:e.topicArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(e){let n={type:"eventbridge",arn:e.eventBusArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(e){let n={type:"lambda",arn:e.destinationFunctionArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(e){return this.configureDestinations({functionName:e.functionName,failureDestination:{type:"sqs",arn:e.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(e){let n=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,r={id:n,functionName:e.functionName,eventBusArn:e.eventBusArn,detailType:e.detailType||"Lambda Function Invocation Result",source:e.source||`lambda.${e.functionName}`};return this.eventBridgeDestinations.set(n,r),r}sendToDestination(e){let n=Array.from(this.destinations.values()).find((a)=>a.functionName===e.functionName);if(!n)return null;let r=e.status==="success"?n.successDestination:n.failureDestination;if(!r)return null;let i=`record-${Date.now()}-${this.recordCounter++}`,s={id:i,timestamp:new Date,functionName:e.functionName,requestId:e.requestId,status:e.status,destinationType:r.type,destinationArn:r.arn,payload:e.payload,error:e.error};return this.records.set(i,s),s}getDestination(e){return this.destinations.get(e)}listDestinations(e){let n=Array.from(this.destinations.values());return e?n.filter((r)=>r.functionName===e):n}getDestinationRecords(e){let n=Array.from(this.records.values());return e?n.filter((r)=>r.functionName===e):n}generateEventInvokeConfigCF(e){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:e.functionName,Qualifier:e.qualifier||"$LATEST",MaximumEventAgeInSeconds:e.maxEventAge||21600,MaximumRetryAttempts:e.maxRetries??2,...e.successDestination&&{DestinationConfig:{OnSuccess:{Destination:e.successDestination.arn}}},...e.failureDestination&&{DestinationConfig:{OnFailure:{Destination:e.failureDestination.arn}}}}}}generateEventBridgeRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{EventBusName:e.eventBusArn.split("/").pop(),EventPattern:{source:[e.source],"detail-type":[e.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}`,Id:e.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var Bf=new Ml;class Ul{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(e){let n=`vpc-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};this.vpcConfigs.set(n,r);for(let i of e.subnetIds)this.createNetworkInterface({functionName:e.functionName,subnetId:i});return r}configurePrivateVPC(e){return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.privateSubnetIds,securityGroupIds:[e.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(e){if(e.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds})}createVPCEndpoint(e){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,r={id:n,...e};return this.endpoints.set(n,r),r}createS3Endpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(e){let n=`eni-${Date.now()}-${this.eniCounter++}`,r={id:n,functionName:e.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:e.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(n,r),setTimeout(()=>{r.status="available"},100),r}analyzeConnectivity(e){let n=`connectivity-${Date.now()}-${this.connectivityCounter++}`,r=Array.from(this.vpcConfigs.values()).find((d)=>d.functionName===e.functionName),i=Array.from(this.endpoints.values()).filter((d)=>d.vpcId===r?.vpcId).map((d)=>d.serviceName),s=[],a=e.hasNATGateway??!1,c=e.hasInternetGateway??!1;if(!a&&!c)s.push("Add NAT Gateway for internet access");if(!i.includes("com.amazonaws.us-east-1.s3"))s.push("Add S3 VPC endpoint to reduce NAT costs");if(!i.includes("com.amazonaws.us-east-1.dynamodb"))s.push("Add DynamoDB VPC endpoint for private access");let u={id:n,functionName:e.functionName,hasInternetAccess:a||c,hasNATGateway:a,hasVPCEndpoints:i.length>0,endpoints:i,recommendations:s};return this.connectivity.set(n,u),u}getVPCConfig(e){return this.vpcConfigs.get(e)}listVPCConfigs(e){let n=Array.from(this.vpcConfigs.values());return e?n.filter((r)=>r.functionName===e):n}getNetworkInterfaces(e){return Array.from(this.networkInterfaces.values()).filter((n)=>n.functionName===e)}listVPCEndpoints(e){let n=Array.from(this.endpoints.values());return e?n.filter((r)=>r.vpcId===e):n}generateVPCConfigCF(e){return{VpcConfig:{SubnetIds:e.subnetIds,SecurityGroupIds:e.securityGroupIds,...e.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(e){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:e.vpcId,ServiceName:e.serviceName,VpcEndpointType:e.endpointType,...e.subnetIds&&{SubnetIds:e.subnetIds},...e.securityGroupIds&&{SecurityGroupIds:e.securityGroupIds},...e.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:e.privateDnsEnabled}}}}generateSecurityGroupCF(e){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:e.groupName,GroupDescription:`Security group for Lambda ${e.groupName}`,VpcId:e.vpcId,...e.ingressRules&&{SecurityGroupIngress:e.ingressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,...n.cidrIp&&{CidrIp:n.cidrIp},...n.sourceSecurityGroupId&&{SourceSecurityGroupId:n.sourceSecurityGroupId}}))},...e.egressRules&&{SecurityGroupEgress:e.egressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,CidrIp:n.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 jf=new Ul;class Fl{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(e){let n=`dlq-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.dlqConfigs.set(n,r),r}configureSQSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.queueArn,targetType:"sqs",maxReceiveCount:e.maxReceiveCount||3,retentionPeriod:e.retentionPeriod||1209600})}configureSNSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.topicArn,targetType:"sns"})}configureDLQWithAlarm(e){let n=this.configureSQSDLQ({functionName:e.functionName,queueArn:e.queueArn});return this.createDLQAlarm({dlqConfigId:n.id,alarmName:`${e.functionName}-dlq-alarm`,threshold:e.alarmThreshold,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0}),n}sendToDLQ(e){let n=`message-${Date.now()}-${this.messageCounter++}`,r={id:n,timestamp:new Date,...e};return this.messages.set(n,r),r}createDLQAlarm(e){let n=`alarm-${Date.now()}-${this.alarmCounter++}`,r={id:n,...e};return this.alarms.set(n,r),r}createAgeAlarm(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:e.dlqConfigId,alarmName:`${n.functionName}-dlq-age-alarm`,threshold:e.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0})}async reprocessMessage(e){let n=this.messages.get(e);if(!n)throw Error(`Message not found: ${e}`);let r=Array.from(this.dlqConfigs.values()).find((a)=>a.functionName===n.functionName);if(!r)throw Error(`DLQ config not found for function: ${n.functionName}`);let i=`reprocess-${Date.now()}-${this.reprocessCounter++}`,s={id:i,dlqConfigId:r.id,messageId:e,status:"pending",startedAt:new Date};return this.reprocessing.set(i,s),setTimeout(()=>{s.status="processing",setTimeout(()=>{let a=Math.random()>0.3;if(s.status=a?"success":"failed",s.completedAt=new Date,!a)s.error="Reprocessing failed - same error occurred";else this.messages.delete(e)},100)},50),s}async batchReprocess(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);let i=Array.from(this.messages.values()).filter((s)=>s.functionName===n.functionName).slice(0,e.maxMessages||10).map((s)=>this.reprocessMessage(s.id));return Promise.all(i)}getDLQStats(e){let n=this.dlqConfigs.get(e);if(!n)throw Error(`DLQ config not found: ${e}`);let r=Array.from(this.messages.values()).filter((c)=>c.functionName===n.functionName),i={},s=0;for(let c of r)i[c.errorType]=(i[c.errorType]||0)+1,s+=c.attemptCount;let a=r.map((c)=>c.timestamp);return{totalMessages:r.length,oldestMessage:a.length>0?new Date(Math.min(...a.map((c)=>c.getTime()))):void 0,newestMessage:a.length>0?new Date(Math.max(...a.map((c)=>c.getTime()))):void 0,averageAttempts:r.length>0?s/r.length:0,errorTypes:i}}getDLQConfig(e){return this.dlqConfigs.get(e)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(e){let n=this.dlqConfigs.get(e);if(!n)return[];return Array.from(this.messages.values()).filter((r)=>r.functionName===n.functionName)}generateDLQCF(e){return{DeadLetterConfig:{TargetArn:e.targetArn}}}generateSQSDLQCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${e.functionName}-dlq`,MessageRetentionPeriod:e.retentionPeriod||1209600,...e.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:e.targetArn,maxReceiveCount:e.maxReceiveCount}}}}}generateDLQAlarmCF(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`DLQ alarm for ${n.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:e.evaluationPeriods,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.targetArn.split(":").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 Vf=new Fl;class Fa{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"weighted",...e};return this.policies.set(n,r),r}createLatencyPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"latency",...e};return this.policies.set(n,r),r}createFailoverPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"failover",...e};return this.policies.set(n,r),r}createGeolocationPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"geolocation",...e};return this.policies.set(n,r),r}createGeoproximityPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"geoproximity",...e};return this.policies.set(n,r),r}createHTTPHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:e.port===443?"https":"http",requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",port:e.port||(e.port===443?443:80),...e};return this.healthChecks.set(n,r),setTimeout(()=>{r.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),r}createTCPHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:"tcp",fullyQualifiedDomainName:e.ipAddress,requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(n,r),setTimeout(()=>{r.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),r}createCalculatedHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(n,r),setTimeout(()=>{let s=e.childHealthChecks.filter((a)=>this.healthChecks.get(a)?.healthCheckStatus==="Healthy").length;r.healthCheckStatus=s>=e.healthThreshold?"Healthy":"Unhealthy"},150),r}createTrafficPolicy(e){let n=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,r={id:n,version:1,...e};return this.trafficPolicies.set(n,r),r}createFailoverTrafficPolicy(e){return this.createTrafficPolicy({name:e.name,document:{recordType:e.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:e.primaryEndpoint},secondary:{type:"value",value:e.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(e){let n={},r=[];return e.locations.forEach((i,s)=>{let a=`endpoint${s}`;n[a]={type:"value",value:i.endpoint},r.push({endpointReference:a,region:i.region,latitude:i.latitude,longitude:i.longitude,bias:i.bias})}),this.createTrafficPolicy({name:e.name,document:{recordType:"A",startRule:"geoproximity",endpoints:n,rules:{geoproximity:{ruleType:"geoproximity",locations:r}}}})}getPolicy(e){return this.policies.get(e)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(e){return this.healthChecks.get(e)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(e){return this.healthChecks.get(e)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(e){let n={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:e.type.toUpperCase(),RequestInterval:e.requestInterval,FailureThreshold:e.failureThreshold,...e.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:e.name}]}};if(e.type==="calculated"){let r=e;n.Properties.HealthCheckConfig.ChildHealthChecks=r.childHealthChecks,n.Properties.HealthCheckConfig.HealthThreshold=r.healthThreshold}else{if(e.ipAddress)n.Properties.HealthCheckConfig.IPAddress=e.ipAddress;if(e.fullyQualifiedDomainName)n.Properties.HealthCheckConfig.FullyQualifiedDomainName=e.fullyQualifiedDomainName;if(e.port)n.Properties.HealthCheckConfig.Port=e.port;if(e.resourcePath)n.Properties.HealthCheckConfig.ResourcePath=e.resourcePath;if(e.enableSNI)n.Properties.HealthCheckConfig.EnableSNI=!0}return n}generateWeightedRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Weight:e.weight,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}generateFailoverRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Failover:e.failover,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var ap=new Fa;class Bl{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(e){let n=`dnssec-${Date.now()}-${this.configCounter++}`,r={id:n,hostedZoneId:e.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(n,r),e.kmsKeyArn)this.createKSK({name:`ksk-${e.hostedZoneId}`,hostedZoneId:e.hostedZoneId,kmsKeyArn:e.kmsKeyArn});return setTimeout(()=>{r.status="SIGNED",r.signingStatus="DNSSEC signing complete"},100),r}disableDNSSEC(e){let n=this.configs.get(e);if(!n)throw Error(`DNSSEC config not found: ${e}`);return n.status="DELETING",n.signingStatus="Removing DNSSEC signing",setTimeout(()=>{n.status="NOT_SIGNING",n.signingStatus="DNSSEC signing removed"},100),n}createKSK(e){let n=`ksk-${Date.now()}-${this.kskCounter++}`,r={id:n,status:"ACTIVE",flag:257,keyManagementServiceArn:e.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...e};r.dnskeyRecord=`${r.flag} 3 8 ${r.publicKey}`;let i=this.generateDigest(r.dnskeyRecord);return r.digestValue=i,r.dsRecord=`${r.keyTag} 8 ${r.digestAlgorithm} ${i}`,this.ksks.set(n,r),r}deactivateKSK(e){let n=this.ksks.get(e);if(!n)throw Error(`KSK not found: ${e}`);return n.status="INACTIVE",n}validateDNSSEC(e){let n=`validation-${Date.now()}-${this.validationCounter++}`,r=e.checkDNSKEY!==!1?Math.random()>0.1:!1,i=e.checkRRSIG!==!1?Math.random()>0.1:!1,s=r&&i,a=[];if(!r)a.push("DNSKEY record not found");if(!i)a.push("RRSIG record not found");let c;if(!r&&!i)c="INSECURE";else if(r&&i&&s)c="VALID";else if(r||i)c="BOGUS",a.push("Invalid signature or incomplete DNSSEC chain");else c="INVALID";let u={id:n,domain:e.domain,validationStatus:c,dnskeyPresent:r,rrsigPresent:i,validSignature:s,errors:a};return this.validations.set(n,u),u}getDNSSECConfig(e){return this.configs.get(e)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(e){return this.ksks.get(e)}listKSKs(e){let n=Array.from(this.ksks.values());return e?n.filter((r)=>r.hostedZoneId===e):n}getDSRecord(e){let n=this.ksks.get(e);if(!n||!n.dsRecord)throw Error("DS record not available");return n.dsRecord}generatePublicKey(){let n="";for(let r=0;r<256;r++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(e){let r="";for(let i=0;i<64;i++)r+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return r}generateDNSSECCF(e){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:e.hostedZoneId}}}generateKSKCF(e){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:e.name,HostedZoneId:e.hostedZoneId,KeyManagementServiceArn:e.keyManagementServiceArn,Status:e.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var zf=new Bl;class jl{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(e){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,r={id:n,status:"CREATING",...e};return this.endpoints.set(n,r),setTimeout(()=>{r.status="OPERATIONAL",r.ipAddresses.forEach((i)=>{if(!i.ip)i.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),r}createInboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"INBOUND",ipAddresses:e.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:e.securityGroupIds})}createOutboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"OUTBOUND",ipAddresses:e.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:e.securityGroupIds})}createResolverRule(e){let n=`rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,status:"CREATING",...e};return this.rules.set(n,r),setTimeout(()=>{r.status="COMPLETE"},100),r}createForwardRule(e){return this.createResolverRule({name:e.name,ruleType:"FORWARD",domainName:e.domainName,targetIps:e.targetIps,resolverEndpointId:e.resolverEndpointId})}createSystemRule(e){return this.createResolverRule({name:e.name,ruleType:"SYSTEM",domainName:e.domainName})}createFirewallDomainList(e){let n=`domain-list-${Date.now()}-${this.domainListCounter++}`,r={id:n,status:"CREATING",...e};return this.domainLists.set(n,r),setTimeout(()=>{r.status="COMPLETE"},100),r}createFirewallRuleGroup(e){let n=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,r={id:n,name:e.name,rules:e.rules.map((i,s)=>({id:`rule-${n}-${s}`,...i})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(n,r),r}createBlockRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"BLOCK",blockResponse:e.blockResponse||"NODATA",blockOverrideDomain:e.blockOverrideDomain,firewallDomainListId:e.domainListId}]})}createAllowRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"ALLOW",firewallDomainListId:e.domainListId}]})}createDNSFirewall(e){let n=`firewall-${Date.now()}-${this.firewallCounter++}`,r={id:n,name:e.name,firewallRuleGroupAssociations:e.ruleGroupAssociations.map((i,s)=>({id:`assoc-${n}-${s}`,vpcId:e.vpcId,firewallRuleGroupId:i.firewallRuleGroupId,priority:i.priority,mutationProtection:i.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(n,r),r}createMalwareProtectionFirewall(e){let n=this.createFirewallDomainList({name:`${e.name}-malware-domains`,domains:e.maliciousDomains}),r=this.createBlockRule({name:`${e.name}-block-malware`,priority:100,domainListId:n.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:e.name,vpcId:e.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:r.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(e){return this.endpoints.get(e)}listEndpoints(e){let n=Array.from(this.endpoints.values());return e?n.filter((r)=>r.direction===e):n}getRule(e){return this.rules.get(e)}listRules(){return Array.from(this.rules.values())}getFirewall(e){return this.firewalls.get(e)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(e){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:e.name,Direction:e.direction,IpAddresses:e.ipAddresses.map((n)=>({SubnetId:n.subnetId,...n.ip&&{Ip:n.ip}})),SecurityGroupIds:e.securityGroupIds}}}generateResolverRuleCF(e){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:e.name,RuleType:e.ruleType,DomainName:e.domainName,...e.targetIps&&{TargetIps:e.targetIps.map((n)=>({Ip:n.ip,Port:n.port||53}))},...e.resolverEndpointId&&{ResolverEndpointId:e.resolverEndpointId}}}}generateFirewallRuleGroupCF(e){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:e.name,FirewallRules:e.rules.map((n)=>({Name:n.name,Priority:n.priority,Action:n.action,FirewallDomainListId:n.firewallDomainListId,...n.blockResponse&&{BlockResponse:n.blockResponse},...n.blockOverrideDomain&&{BlockOverrideDomain:n.blockOverrideDomain},...n.blockOverrideTTL&&{BlockOverrideTtl:n.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 Hf=new jl;class Vl{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(e){let n=`bounce-${Date.now()}-${this.bounceCounter++}`,r={id:n,...e};if(this.bounces.set(n,r),e.bounceType==="Permanent")this.addToSuppressionList({emailAddress:e.recipient,reason:"BOUNCE"});return r}recordComplaint(e){let n=`complaint-${Date.now()}-${this.complaintCounter++}`,r={id:n,...e};this.complaints.set(n,r);for(let i of e.recipients)this.addToSuppressionList({emailAddress:i,reason:"COMPLAINT"});return r}createBounceHandler(e){let n=`handler-${Date.now()}-${this.handlerCounter++}`,r={id:n,...e};return this.handlers.set(n,r),r}createAutomaticBounceHandler(e){return this.createBounceHandler({name:e.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:e.notificationTopicArn})}addToSuppressionList(e){let n=`suppression-${Date.now()}-${this.suppressionCounter++}`,r=e.expirationDays?new Date(Date.now()+e.expirationDays*24*60*60*1000):void 0,i={id:n,emailAddress:e.emailAddress,reason:e.reason,suppressedAt:new Date,expiresAt:r,bounceCount:e.reason==="BOUNCE"?1:0,complaintCount:e.reason==="COMPLAINT"?1:0};return this.suppressionList.set(e.emailAddress,i),i}removeFromSuppressionList(e){return this.suppressionList.delete(e)}isSuppressed(e){let n=this.suppressionList.get(e);if(!n)return!1;if(n.expiresAt&&n.expiresAt<new Date)return this.suppressionList.delete(e),!1;return!0}getBounceStatistics(e,n){let r=Array.from(this.bounces.values()).filter((p)=>p.timestamp>=e&&p.timestamp<=n),i=r.length,s=r.filter((p)=>p.bounceType==="Permanent").length,a=r.filter((p)=>p.bounceType==="Transient").length,c=i*10,u=i/c*100,d=new Map;for(let p of r)d.set(p.recipient,(d.get(p.recipient)||0)+1);let m=Array.from(d.entries()).map(([p,g])=>({email:p,count:g})).sort((p,g)=>g.count-p.count).slice(0,10);return{totalBounces:i,permanentBounces:s,transientBounces:a,bounceRate:u,topRecipients:m}}getComplaintStatistics(e,n){let r=Array.from(this.complaints.values()).filter((d)=>d.timestamp>=e&&d.timestamp<=n),i=r.length,s=new Set;for(let d of r)for(let m of d.recipients)s.add(m);let a=s.size,c=i*1000,u=i/c*100;return{totalComplaints:i,uniqueComplainters:a,complaintRate:u}}calculateReputationMetrics(){let e=`metrics-${Date.now()}-${this.metricsCounter++}`,n=new Date,r=new Date(n.getTime()-86400000),i=this.getBounceStatistics(r,n),s=this.getComplaintStatistics(r,n),a;if(i.bounceRate>10||s.complaintRate>0.5)a="Shutdown";else if(i.bounceRate>5||s.complaintRate>0.1)a="Probation";else if(i.bounceRate>2||s.complaintRate>0.05)a="Warning";else a="Good";let c={id:e,timestamp:n,bounceRate:i.bounceRate,complaintRate:s.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:i.totalBounces*10,reputationStatus:a};return this.metrics.set(e,c),c}getBounces(e){let n=Array.from(this.bounces.values());return e?n.filter((r)=>r.messageId===e):n}getComplaints(e){let n=Array.from(this.complaints.values());return e?n.filter((r)=>r.messageId===e):n}listSuppressionList(e){let n=Array.from(this.suppressionList.values());return e?n.filter((r)=>r.reason===e):n}generateSNSSubscriptionCF(e){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:e.topicArn,Endpoint:e.endpoint,Protocol:e.protocol}}}generateEventDestinationCF(e){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:e.configurationSetName,EventDestination:{Name:e.eventDestinationName,Enabled:!0,MatchingEventTypes:e.eventTypes,...e.snsTopicArn&&{SnsDestination:{TopicARN:e.snsTopicArn}},...e.cloudWatchDestination&&{CloudWatchDestination:e.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 Gf=new Vl;class zl{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(e){let n=`event-${Date.now()}-${this.eventCounter++}`,r={id:n,...e};if(this.events.set(n,r),e.tags?.campaignId)this.updateCampaignStats(e.tags.campaignId,e.eventType);return r}trackOpen(e){return this.trackEvent({...e,eventType:"open",timestamp:new Date})}trackClick(e){return this.trackEvent({...e,eventType:"click",timestamp:new Date})}createCampaign(e){let n=`campaign-${Date.now()}-${this.campaignCounter++}`,r={id:n,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...e};return this.campaigns.set(n,r),r}updateCampaignStats(e,n){let r=this.campaigns.get(e);if(!r)return;switch(n){case"send":r.sentCount++;break;case"delivery":r.deliveredCount++;break;case"open":r.openCount++;break;case"click":r.clickCount++;break;case"bounce":r.bounceCount++;break;case"complaint":r.complaintCount++;break}}generateReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r=Array.from(this.events.values()).filter((v)=>{let I=v.timestamp>=e.startDate&&v.timestamp<=e.endDate,D=!e.campaignId||v.tags?.campaignId===e.campaignId;return I&&D}),i=r.filter((v)=>v.eventType==="send").length,s=r.filter((v)=>v.eventType==="delivery").length,a=r.filter((v)=>v.eventType==="open").length,c=r.filter((v)=>v.eventType==="click").length,u=r.filter((v)=>v.eventType==="bounce").length,d=r.filter((v)=>v.eventType==="complaint").length,m=i>0?s/i*100:0,p=s>0?a/s*100:0,g=s>0?c/s*100:0,y=a>0?c/a*100:0,h=i>0?u/i*100:0,f=s>0?d/s*100:0,S=new Map;for(let v of r)if(v.eventType==="click"){let I=v;S.set(I.link,(S.get(I.link)||0)+1)}let C=Array.from(S.entries()).map(([v,I])=>({link:v,clicks:I})).sort((v,I)=>I.clicks-v.clicks).slice(0,10),P={desktop:0,mobile:0,tablet:0,unknown:0};for(let v of r)if(v.eventType==="open"||v.eventType==="click"){let I=v.userAgent.toLowerCase();if(I.includes("mobile"))P.mobile++;else if(I.includes("tablet"))P.tablet++;else if(I.includes("mozilla"))P.desktop++;else P.unknown++}let E={id:n,campaignId:e.campaignId,startDate:e.startDate,endDate:e.endDate,totalSent:i,totalDelivered:s,totalOpened:a,totalClicked:c,totalBounced:u,totalComplaints:d,deliveryRate:m,openRate:p,clickRate:g,clickToOpenRate:y,bounceRate:h,complaintRate:f,topLinks:C,deviceBreakdown:P,locationBreakdown:{}};return this.reports.set(n,E),E}createABTest(e){let n=`abtest-${Date.now()}-${this.abTestCounter++}`,r={id:n,name:e.name,variants:e.variants.map((i,s)=>({id:`variant-${n}-${s}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...i})),status:"draft"};return this.abTests.set(n,r),r}startABTest(e){let n=this.abTests.get(e);if(!n)throw Error(`A/B test not found: ${e}`);return n.status="running",n.startedAt=new Date,n}completeABTest(e){let n=this.abTests.get(e);if(!n)throw Error(`A/B test not found: ${e}`);let r=n.variants[0],i=0;for(let s of n.variants){let a=s.sentCount>0?s.openCount/s.sentCount:0;if(a>i)i=a,r=s}return n.status="completed",n.completedAt=new Date,n.winner=r.id,n}getCampaign(e){return this.campaigns.get(e)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(e){let n=Array.from(this.events.values());if(e?.messageId)n=n.filter((r)=>r.messageId===e.messageId);if(e?.eventType)n=n.filter((r)=>r.eventType===e.eventType);if(e?.startDate)n=n.filter((r)=>r.timestamp>=e.startDate);if(e?.endDate)n=n.filter((r)=>r.timestamp<=e.endDate);return n}generateTrackingConfigurationCF(e){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:e.configurationSetName,...e.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 qf=new zl;class Hl{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let e=`dashboard-${Date.now()}-${this.dashboardCounter++}`,n=Math.random()*5,r=Math.random()*0.5,i=Math.floor(Math.random()*10),s=Math.max(0,100-n*10-r*100-i*2),a=[];if(n>2)a.push("Reduce bounce rate by cleaning email list");if(r>0.1)a.push("Review email content and unsubscribe process");if(i>5)a.push("Improve email relevance and targeting");let c={id:e,timestamp:new Date,overallScore:s,bounceRate:n,complaintRate:r,spamReports:i,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:a};return this.dashboards.set(e,c),c}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(e){let n=`warmup-${Date.now()}-${this.warmupCounter++}`,r=[],i=(e.targetDailyLimit-e.initialDailyLimit)/e.durationDays;for(let a=0;a<e.durationDays;a++)r.push(Math.floor(e.initialDailyLimit+i*a));let s={id:n,name:e.name,startDate:new Date,currentDay:1,totalDays:e.durationDays,dailyLimits:r,currentLimit:r[0],status:"active"};return this.warmupPlans.set(n,s),s}createAggressiveWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(e){let n=this.warmupPlans.get(e);if(!n)throw Error(`Warmup plan not found: ${e}`);if(n.currentDay<n.totalDays)n.currentDay++,n.currentLimit=n.dailyLimits[n.currentDay-1];if(n.currentDay>=n.totalDays)n.status="completed";return n}trackDomainReputation(e){let n=`domain-${Date.now()}-${this.domainCounter++}`,r=e.delivered/e.totalSent*100,i=e.delivered>0?e.opened/e.delivered*100:0,s=e.delivered>0?e.clicked/e.delivered*100:0,a=e.bounced/e.totalSent*100,c=e.delivered>0?e.complained/e.delivered*100:0,u=i*0.4+s*0.6,d=Math.max(0,100-a*10-c*100+u*0.2),m={id:n,domain:e.domain,reputationScore:d,totalSent:e.totalSent,deliveryRate:r,openRate:i,clickRate:s,bounceRate:a,complaintRate:c,engagementScore:u};return this.domainReputations.set(e.domain,m),m}getDomainReputation(e){return this.domainReputations.get(e)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(e){return this.warmupPlans.get(e)}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 Wf=new Hl;class Gl{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(e){let n=`template-${Date.now()}-${this.templateCounter++}`,r=this.extractVariables(e.subject+e.htmlPart+e.textPart),i={id:n,variables:r,createdAt:new Date,updatedAt:new Date,version:1,...e};return this.templates.set(n,i),this.addVersion({templateId:n,version:1,subject:e.subject,htmlPart:e.htmlPart,textPart:e.textPart,createdBy:"system"}),i}createWelcomeTemplate(e){return this.createTemplate({name:e.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3751
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let u={sizeBefore:n.totalSize,sizeAfter:n.totalSize*0.6,timeBefore:300,timeAfter:120},d={id:r,name:`Optimization for ${n.imageId}`,recommendations:i,estimatedSavings:u};return this.optimizations.set(r,d),d}getBuildConfig(e){return this.configs.get(e)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(e){return this.multiStageConfigs.get(e)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(e){return this.optimizations.get(e)}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 Ff=new Ml;class ja{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(e){let n=`registry-${Date.now()}-${this.registryCounter++}`,r={id:n,...e};return this.registries.set(n,r),r}createECRRepository(e){return this.createRegistry({name:e.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${e.region||"us-east-1"}.amazonaws.com/${e.name}`,region:e.region||"us-east-1",encryption:{encryptionType:e.encryption||"AES256",kmsKeyId:e.kmsKeyId},scanning:{scanOnPush:e.scanOnPush??!0}})}createManagedRepository(e){let n=this.createECRRepository({name:e.name,region:e.region,scanOnPush:!0,encryption:"KMS"});return n.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},n}enableReplication(e,n){let r=this.registries.get(e);if(!r)throw Error(`Registry not found: ${e}`);return r.replication={enabled:!0,destinations:n},r}createCredentials(e){let n=`creds-${Date.now()}-${this.credentialsCounter++}`,r={id:n,...e};return this.credentials.set(n,r),r}getRegistry(e){return this.registries.get(e)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.name,ImageScanningConfiguration:{ScanOnPush:e.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:e.encryption?.encryptionType||"AES256",...e.encryption?.kmsKeyId&&{KmsKey:e.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...e.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:e.lifecycle.rules})}}}}}generateReplicationConfigCF(e){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:e.destinations.map((n)=>({Destinations:[{Region:n.region,...n.registryId&&{RegistryId:n.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var lp=new ja;class Va{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(e){let n=`mesh-${Date.now()}-${this.meshCounter++}`,r={id:n,...e};return this.meshes.set(n,r),r}createAppMesh(e){return this.createMesh({name:e.name,meshType:"app_mesh",services:e.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(e){let n=`vnode-${Date.now()}-${this.nodeCounter++}`,r={id:n,...e};return this.virtualNodes.set(n,r),r}createHTTPVirtualNode(e){return this.createVirtualNode({name:e.name,serviceName:e.serviceName,listeners:[{port:e.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:e.namespace,serviceName:e.serviceName}})}createVirtualRouter(e){let n=`vrouter-${Date.now()}-${this.routerCounter++}`,r={id:n,...e};return this.virtualRouters.set(n,r),r}createCanaryRoute(e){return this.createVirtualRouter({name:e.name,listeners:[{port:e.port,protocol:e.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:e.stableTarget,weight:100-e.canaryWeight},{virtualNode:e.canaryTarget,weight:e.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(e){let n=`vgateway-${Date.now()}-${this.gatewayCounter++}`,r={id:n,...e};return this.virtualGateways.set(n,r),r}createIngressGateway(e){let n={port:e.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(e.enableTLS&&e.certificateArn)n.tls={mode:"STRICT",certificate:{acm:e.certificateArn}};return this.createVirtualGateway({name:e.name,listeners:[n],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(e){return this.meshes.get(e)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(e){return this.virtualNodes.get(e)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(e){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:e.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(e,n){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:n,VirtualNodeName:e.name,Spec:{Listeners:e.listeners.map((r)=>({PortMapping:{Port:r.port,Protocol:r.protocol},...r.healthCheck&&{HealthCheck:{Protocol:r.healthCheck.protocol,...r.healthCheck.path&&{Path:r.healthCheck.path},IntervalMillis:r.healthCheck.interval*1000,TimeoutMillis:r.healthCheck.timeout*1000,HealthyThreshold:r.healthCheck.healthyThreshold,UnhealthyThreshold:r.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:e.serviceDiscovery.namespace,ServiceName:e.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(e,n){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:n,VirtualRouterName:e.name,Spec:{Listeners:e.listeners.map((r)=>({PortMapping:{Port:r.port,Protocol:r.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 dp=new Va;class Ul{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(e){let n=`layer-${Date.now()}-${this.layerCounter++}`,r=1,i={id:n,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:1`,version:1,...e};return this.layers.set(n,i),i}createNodeDependenciesLayer(e){return this.createLayer({layerName:e.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${e.nodeVersion}`],content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:5242880})}createUtilitiesLayer(e){return this.createLayer({layerName:e.layerName,description:"Shared utilities and helpers",compatibleRuntimes:e.runtimes,content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:1048576})}publishVersion(e){let n=this.layers.get(e);if(!n)throw Error(`Layer not found: ${e}`);let r=`version-${Date.now()}-${this.versionCounter++}`,i=n.version+1,s={id:r,layerName:n.layerName,version:i,createdAt:new Date,compatibleRuntimes:n.compatibleRuntimes,size:n.size,codeHash:this.generateHash()};return this.versions.set(r,s),n.version=i,n.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${i}`,s}addPermission(e){let n=`permission-${Date.now()}-${this.permissionCounter++}`,r={id:n,layerName:e.layerName,version:e.version,principal:e.principal,action:"lambda:GetLayerVersion",organizationId:e.organizationId};return this.permissions.set(n,r),r}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(e){return this.layers.get(e)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(e){return Array.from(this.versions.values()).filter((n)=>n.layerName===e)}generateLayerCF(e){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:e.layerName,Description:e.description,Content:e.content.type==="s3"?{S3Bucket:e.content.s3Bucket,S3Key:e.content.s3Key,...e.content.s3ObjectVersion&&{S3ObjectVersion:e.content.s3ObjectVersion}}:{ZipFile:e.content.zipFile},CompatibleRuntimes:e.compatibleRuntimes,...e.licenseInfo&&{LicenseInfo:e.licenseInfo}}}}generateLayerPermissionCF(e){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:${e.version}`,Action:e.action,Principal:e.principal,...e.organizationId&&{OrganizationId:e.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var jf=new Ul;class Bl{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(e){let n=`version-${Date.now()}-${this.versionCounter++}`,r=this.getNextVersionNumber(e.functionName),i={id:n,functionName:e.functionName,version:r.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${r}`,codeHash:this.generateHash(),description:e.description,runtime:e.runtime,memorySize:e.memorySize,timeout:e.timeout,publishedAt:new Date};return this.versions.set(n,i),i}getNextVersionNumber(e){let n=Array.from(this.versions.values()).filter((r)=>r.functionName===e).map((r)=>parseInt(r.version));return n.length>0?Math.max(...n)+1:1}createAlias(e){let n=`alias-${Date.now()}-${this.aliasCounter++}`,r={id:n,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${e.aliasName}`,revisionId:this.generateHash(),...e};return this.aliases.set(n,r),r}createProductionAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"production",functionVersion:e.version,description:"Production alias"})}createStagingAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"staging",functionVersion:e.version,description:"Staging alias"})}updateAlias(e,n){let r=this.aliases.get(e);if(!r)throw Error(`Alias not found: ${e}`);return r.functionVersion=n,r.revisionId=this.generateHash(),r}configureWeightedRouting(e,n){let r=this.aliases.get(e);if(!r)throw Error(`Alias not found: ${e}`);return r.routingConfig={additionalVersionWeights:n},r}createCanaryDeployment(e){let n=`deployment-${Date.now()}-${this.deploymentCounter++}`,r=Array.from(this.aliases.values()).find((s)=>s.functionName===e.functionName&&s.aliasName===e.aliasName);if(!r)r=this.createAlias({functionName:e.functionName,aliasName:e.aliasName,functionVersion:e.fromVersion});this.configureWeightedRouting(r.id,{[e.toVersion]:e.canaryWeight});let i={id:n,functionName:e.functionName,fromVersion:e.fromVersion,toVersion:e.toVersion,aliasName:e.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(n,i),i}completeDeployment(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r=Array.from(this.aliases.values()).find((i)=>i.functionName===n.functionName&&i.aliasName===n.aliasName);if(r)r.functionVersion=n.toVersion,r.routingConfig=void 0;return n.status="completed",n.completedAt=new Date,n}rollbackDeployment(e){let n=this.deployments.get(e);if(!n)throw Error(`Deployment not found: ${e}`);let r=Array.from(this.aliases.values()).find((i)=>i.functionName===n.functionName&&i.aliasName===n.aliasName);if(r)r.functionVersion=n.fromVersion,r.routingConfig=void 0;return n.status="failed",n.completedAt=new Date,n}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(e){return this.versions.get(e)}listVersions(e){let n=Array.from(this.versions.values());return e?n.filter((r)=>r.functionName===e):n}getAlias(e){return this.aliases.get(e)}listAliases(e){let n=Array.from(this.aliases.values());return e?n.filter((r)=>r.functionName===e):n}generateVersionCF(e){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:e.functionName,Description:e.description}}}generateAliasCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.aliasName,FunctionVersion:e.functionVersion,Description:e.description,...e.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(e.routingConfig.additionalVersionWeights||{}).map(([n,r])=>({FunctionVersion:n,FunctionWeight:r}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var Vf=new Bl;class Fl{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(e){let n=`concurrency-${Date.now()}-${this.configCounter++}`,r={id:n,functionName:e.functionName,reservedConcurrency:e.reservedConcurrency};return this.configs.set(n,r),r}setProvisionedConcurrency(e){let n=`provisioned-${Date.now()}-${this.provisionedCounter++}`,r={id:n,functionName:e.functionName,qualifier:e.qualifier,provisionedConcurrentExecutions:e.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(n,r),setTimeout(()=>{r.status="ready",r.allocatedConcurrency=e.provisionedConcurrentExecutions,r.availableConcurrency=e.provisionedConcurrentExecutions},100),r}configureWarmPool(e){return this.setProvisionedConcurrency({functionName:e.functionName,qualifier:e.alias,provisionedConcurrentExecutions:e.minInstances})}createSchedule(e){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,r={id:n,...e};return this.schedules.set(n,r),r}createBusinessHoursSchedule(e){return this.createSchedule({name:`${e.functionName}-business-hours`,functionName:e.functionName,qualifier:e.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:e.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:e.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:e.offHoursConcurrency}]})}configureAutoScaling(e){let n=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,r={id:n,...e};return this.autoScalingConfigs.set(n,r),r}configurePredictiveScaling(e){return this.configureAutoScaling({functionName:e.functionName,qualifier:e.qualifier,minCapacity:e.baselineCapacity,maxCapacity:e.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(e){return this.provisionedConfigs.get(e)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.functionName,ReservedConcurrentExecutions:e.reservedConcurrency}}}generateProvisionedConcurrencyCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:e.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${e.functionName}:${e.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:e.minCapacity,MaxCapacity:e.maxCapacity}}}generateAutoScalingPolicyCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${e.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:e.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:e.scaleInCooldown||300,ScaleOutCooldown:e.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 zf=new Fl;class jl{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(e){let n=`destination-${Date.now()}-${this.destinationCounter++}`,r={id:n,...e};return this.destinations.set(n,r),r}configureSQSDestination(e){let n={type:"sqs",arn:e.queueArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(e){let n={type:"sns",arn:e.topicArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(e){let n={type:"eventbridge",arn:e.eventBusArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(e){let n={type:"lambda",arn:e.destinationFunctionArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?n:void 0,failureDestination:e.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(e){return this.configureDestinations({functionName:e.functionName,failureDestination:{type:"sqs",arn:e.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(e){let n=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,r={id:n,functionName:e.functionName,eventBusArn:e.eventBusArn,detailType:e.detailType||"Lambda Function Invocation Result",source:e.source||`lambda.${e.functionName}`};return this.eventBridgeDestinations.set(n,r),r}sendToDestination(e){let n=Array.from(this.destinations.values()).find((a)=>a.functionName===e.functionName);if(!n)return null;let r=e.status==="success"?n.successDestination:n.failureDestination;if(!r)return null;let i=`record-${Date.now()}-${this.recordCounter++}`,s={id:i,timestamp:new Date,functionName:e.functionName,requestId:e.requestId,status:e.status,destinationType:r.type,destinationArn:r.arn,payload:e.payload,error:e.error};return this.records.set(i,s),s}getDestination(e){return this.destinations.get(e)}listDestinations(e){let n=Array.from(this.destinations.values());return e?n.filter((r)=>r.functionName===e):n}getDestinationRecords(e){let n=Array.from(this.records.values());return e?n.filter((r)=>r.functionName===e):n}generateEventInvokeConfigCF(e){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:e.functionName,Qualifier:e.qualifier||"$LATEST",MaximumEventAgeInSeconds:e.maxEventAge||21600,MaximumRetryAttempts:e.maxRetries??2,...e.successDestination&&{DestinationConfig:{OnSuccess:{Destination:e.successDestination.arn}}},...e.failureDestination&&{DestinationConfig:{OnFailure:{Destination:e.failureDestination.arn}}}}}}generateEventBridgeRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{EventBusName:e.eventBusArn.split("/").pop(),EventPattern:{source:[e.source],"detail-type":[e.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}`,Id:e.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var Hf=new jl;class Vl{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(e){let n=`vpc-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};this.vpcConfigs.set(n,r);for(let i of e.subnetIds)this.createNetworkInterface({functionName:e.functionName,subnetId:i});return r}configurePrivateVPC(e){return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.privateSubnetIds,securityGroupIds:[e.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(e){if(e.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds})}createVPCEndpoint(e){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,r={id:n,...e};return this.endpoints.set(n,r),r}createS3Endpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(e){let n=`eni-${Date.now()}-${this.eniCounter++}`,r={id:n,functionName:e.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:e.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(n,r),setTimeout(()=>{r.status="available"},100),r}analyzeConnectivity(e){let n=`connectivity-${Date.now()}-${this.connectivityCounter++}`,r=Array.from(this.vpcConfigs.values()).find((d)=>d.functionName===e.functionName),i=Array.from(this.endpoints.values()).filter((d)=>d.vpcId===r?.vpcId).map((d)=>d.serviceName),s=[],a=e.hasNATGateway??!1,c=e.hasInternetGateway??!1;if(!a&&!c)s.push("Add NAT Gateway for internet access");if(!i.includes("com.amazonaws.us-east-1.s3"))s.push("Add S3 VPC endpoint to reduce NAT costs");if(!i.includes("com.amazonaws.us-east-1.dynamodb"))s.push("Add DynamoDB VPC endpoint for private access");let u={id:n,functionName:e.functionName,hasInternetAccess:a||c,hasNATGateway:a,hasVPCEndpoints:i.length>0,endpoints:i,recommendations:s};return this.connectivity.set(n,u),u}getVPCConfig(e){return this.vpcConfigs.get(e)}listVPCConfigs(e){let n=Array.from(this.vpcConfigs.values());return e?n.filter((r)=>r.functionName===e):n}getNetworkInterfaces(e){return Array.from(this.networkInterfaces.values()).filter((n)=>n.functionName===e)}listVPCEndpoints(e){let n=Array.from(this.endpoints.values());return e?n.filter((r)=>r.vpcId===e):n}generateVPCConfigCF(e){return{VpcConfig:{SubnetIds:e.subnetIds,SecurityGroupIds:e.securityGroupIds,...e.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(e){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:e.vpcId,ServiceName:e.serviceName,VpcEndpointType:e.endpointType,...e.subnetIds&&{SubnetIds:e.subnetIds},...e.securityGroupIds&&{SecurityGroupIds:e.securityGroupIds},...e.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:e.privateDnsEnabled}}}}generateSecurityGroupCF(e){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:e.groupName,GroupDescription:`Security group for Lambda ${e.groupName}`,VpcId:e.vpcId,...e.ingressRules&&{SecurityGroupIngress:e.ingressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,...n.cidrIp&&{CidrIp:n.cidrIp},...n.sourceSecurityGroupId&&{SourceSecurityGroupId:n.sourceSecurityGroupId}}))},...e.egressRules&&{SecurityGroupEgress:e.egressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,CidrIp:n.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 Gf=new Vl;class zl{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(e){let n=`dlq-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.dlqConfigs.set(n,r),r}configureSQSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.queueArn,targetType:"sqs",maxReceiveCount:e.maxReceiveCount||3,retentionPeriod:e.retentionPeriod||1209600})}configureSNSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.topicArn,targetType:"sns"})}configureDLQWithAlarm(e){let n=this.configureSQSDLQ({functionName:e.functionName,queueArn:e.queueArn});return this.createDLQAlarm({dlqConfigId:n.id,alarmName:`${e.functionName}-dlq-alarm`,threshold:e.alarmThreshold,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0}),n}sendToDLQ(e){let n=`message-${Date.now()}-${this.messageCounter++}`,r={id:n,timestamp:new Date,...e};return this.messages.set(n,r),r}createDLQAlarm(e){let n=`alarm-${Date.now()}-${this.alarmCounter++}`,r={id:n,...e};return this.alarms.set(n,r),r}createAgeAlarm(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:e.dlqConfigId,alarmName:`${n.functionName}-dlq-age-alarm`,threshold:e.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0})}async reprocessMessage(e){let n=this.messages.get(e);if(!n)throw Error(`Message not found: ${e}`);let r=Array.from(this.dlqConfigs.values()).find((a)=>a.functionName===n.functionName);if(!r)throw Error(`DLQ config not found for function: ${n.functionName}`);let i=`reprocess-${Date.now()}-${this.reprocessCounter++}`,s={id:i,dlqConfigId:r.id,messageId:e,status:"pending",startedAt:new Date};return this.reprocessing.set(i,s),setTimeout(()=>{s.status="processing",setTimeout(()=>{let a=Math.random()>0.3;if(s.status=a?"success":"failed",s.completedAt=new Date,!a)s.error="Reprocessing failed - same error occurred";else this.messages.delete(e)},100)},50),s}async batchReprocess(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);let i=Array.from(this.messages.values()).filter((s)=>s.functionName===n.functionName).slice(0,e.maxMessages||10).map((s)=>this.reprocessMessage(s.id));return Promise.all(i)}getDLQStats(e){let n=this.dlqConfigs.get(e);if(!n)throw Error(`DLQ config not found: ${e}`);let r=Array.from(this.messages.values()).filter((c)=>c.functionName===n.functionName),i={},s=0;for(let c of r)i[c.errorType]=(i[c.errorType]||0)+1,s+=c.attemptCount;let a=r.map((c)=>c.timestamp);return{totalMessages:r.length,oldestMessage:a.length>0?new Date(Math.min(...a.map((c)=>c.getTime()))):void 0,newestMessage:a.length>0?new Date(Math.max(...a.map((c)=>c.getTime()))):void 0,averageAttempts:r.length>0?s/r.length:0,errorTypes:i}}getDLQConfig(e){return this.dlqConfigs.get(e)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(e){let n=this.dlqConfigs.get(e);if(!n)return[];return Array.from(this.messages.values()).filter((r)=>r.functionName===n.functionName)}generateDLQCF(e){return{DeadLetterConfig:{TargetArn:e.targetArn}}}generateSQSDLQCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${e.functionName}-dlq`,MessageRetentionPeriod:e.retentionPeriod||1209600,...e.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:e.targetArn,maxReceiveCount:e.maxReceiveCount}}}}}generateDLQAlarmCF(e){let n=this.dlqConfigs.get(e.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`DLQ alarm for ${n.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:e.evaluationPeriods,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.targetArn.split(":").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 qf=new zl;class za{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"weighted",...e};return this.policies.set(n,r),r}createLatencyPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"latency",...e};return this.policies.set(n,r),r}createFailoverPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"failover",...e};return this.policies.set(n,r),r}createGeolocationPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"geolocation",...e};return this.policies.set(n,r),r}createGeoproximityPolicy(e){let n=`policy-${Date.now()}-${this.policyCounter++}`,r={id:n,type:"geoproximity",...e};return this.policies.set(n,r),r}createHTTPHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:e.port===443?"https":"http",requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",port:e.port||(e.port===443?443:80),...e};return this.healthChecks.set(n,r),setTimeout(()=>{r.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),r}createTCPHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:"tcp",fullyQualifiedDomainName:e.ipAddress,requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(n,r),setTimeout(()=>{r.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),r}createCalculatedHealthCheck(e){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,r={id:n,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(n,r),setTimeout(()=>{let s=e.childHealthChecks.filter((a)=>this.healthChecks.get(a)?.healthCheckStatus==="Healthy").length;r.healthCheckStatus=s>=e.healthThreshold?"Healthy":"Unhealthy"},150),r}createTrafficPolicy(e){let n=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,r={id:n,version:1,...e};return this.trafficPolicies.set(n,r),r}createFailoverTrafficPolicy(e){return this.createTrafficPolicy({name:e.name,document:{recordType:e.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:e.primaryEndpoint},secondary:{type:"value",value:e.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(e){let n={},r=[];return e.locations.forEach((i,s)=>{let a=`endpoint${s}`;n[a]={type:"value",value:i.endpoint},r.push({endpointReference:a,region:i.region,latitude:i.latitude,longitude:i.longitude,bias:i.bias})}),this.createTrafficPolicy({name:e.name,document:{recordType:"A",startRule:"geoproximity",endpoints:n,rules:{geoproximity:{ruleType:"geoproximity",locations:r}}}})}getPolicy(e){return this.policies.get(e)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(e){return this.healthChecks.get(e)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(e){return this.healthChecks.get(e)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(e){let n={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:e.type.toUpperCase(),RequestInterval:e.requestInterval,FailureThreshold:e.failureThreshold,...e.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:e.name}]}};if(e.type==="calculated"){let r=e;n.Properties.HealthCheckConfig.ChildHealthChecks=r.childHealthChecks,n.Properties.HealthCheckConfig.HealthThreshold=r.healthThreshold}else{if(e.ipAddress)n.Properties.HealthCheckConfig.IPAddress=e.ipAddress;if(e.fullyQualifiedDomainName)n.Properties.HealthCheckConfig.FullyQualifiedDomainName=e.fullyQualifiedDomainName;if(e.port)n.Properties.HealthCheckConfig.Port=e.port;if(e.resourcePath)n.Properties.HealthCheckConfig.ResourcePath=e.resourcePath;if(e.enableSNI)n.Properties.HealthCheckConfig.EnableSNI=!0}return n}generateWeightedRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Weight:e.weight,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}generateFailoverRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Failover:e.failover,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var up=new za;class Hl{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(e){let n=`dnssec-${Date.now()}-${this.configCounter++}`,r={id:n,hostedZoneId:e.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(n,r),e.kmsKeyArn)this.createKSK({name:`ksk-${e.hostedZoneId}`,hostedZoneId:e.hostedZoneId,kmsKeyArn:e.kmsKeyArn});return setTimeout(()=>{r.status="SIGNED",r.signingStatus="DNSSEC signing complete"},100),r}disableDNSSEC(e){let n=this.configs.get(e);if(!n)throw Error(`DNSSEC config not found: ${e}`);return n.status="DELETING",n.signingStatus="Removing DNSSEC signing",setTimeout(()=>{n.status="NOT_SIGNING",n.signingStatus="DNSSEC signing removed"},100),n}createKSK(e){let n=`ksk-${Date.now()}-${this.kskCounter++}`,r={id:n,status:"ACTIVE",flag:257,keyManagementServiceArn:e.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...e};r.dnskeyRecord=`${r.flag} 3 8 ${r.publicKey}`;let i=this.generateDigest(r.dnskeyRecord);return r.digestValue=i,r.dsRecord=`${r.keyTag} 8 ${r.digestAlgorithm} ${i}`,this.ksks.set(n,r),r}deactivateKSK(e){let n=this.ksks.get(e);if(!n)throw Error(`KSK not found: ${e}`);return n.status="INACTIVE",n}validateDNSSEC(e){let n=`validation-${Date.now()}-${this.validationCounter++}`,r=e.checkDNSKEY!==!1?Math.random()>0.1:!1,i=e.checkRRSIG!==!1?Math.random()>0.1:!1,s=r&&i,a=[];if(!r)a.push("DNSKEY record not found");if(!i)a.push("RRSIG record not found");let c;if(!r&&!i)c="INSECURE";else if(r&&i&&s)c="VALID";else if(r||i)c="BOGUS",a.push("Invalid signature or incomplete DNSSEC chain");else c="INVALID";let u={id:n,domain:e.domain,validationStatus:c,dnskeyPresent:r,rrsigPresent:i,validSignature:s,errors:a};return this.validations.set(n,u),u}getDNSSECConfig(e){return this.configs.get(e)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(e){return this.ksks.get(e)}listKSKs(e){let n=Array.from(this.ksks.values());return e?n.filter((r)=>r.hostedZoneId===e):n}getDSRecord(e){let n=this.ksks.get(e);if(!n||!n.dsRecord)throw Error("DS record not available");return n.dsRecord}generatePublicKey(){let n="";for(let r=0;r<256;r++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(e){let r="";for(let i=0;i<64;i++)r+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return r}generateDNSSECCF(e){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:e.hostedZoneId}}}generateKSKCF(e){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:e.name,HostedZoneId:e.hostedZoneId,KeyManagementServiceArn:e.keyManagementServiceArn,Status:e.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var Wf=new Hl;class Gl{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(e){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,r={id:n,status:"CREATING",...e};return this.endpoints.set(n,r),setTimeout(()=>{r.status="OPERATIONAL",r.ipAddresses.forEach((i)=>{if(!i.ip)i.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),r}createInboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"INBOUND",ipAddresses:e.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:e.securityGroupIds})}createOutboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"OUTBOUND",ipAddresses:e.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:e.securityGroupIds})}createResolverRule(e){let n=`rule-${Date.now()}-${this.ruleCounter++}`,r={id:n,status:"CREATING",...e};return this.rules.set(n,r),setTimeout(()=>{r.status="COMPLETE"},100),r}createForwardRule(e){return this.createResolverRule({name:e.name,ruleType:"FORWARD",domainName:e.domainName,targetIps:e.targetIps,resolverEndpointId:e.resolverEndpointId})}createSystemRule(e){return this.createResolverRule({name:e.name,ruleType:"SYSTEM",domainName:e.domainName})}createFirewallDomainList(e){let n=`domain-list-${Date.now()}-${this.domainListCounter++}`,r={id:n,status:"CREATING",...e};return this.domainLists.set(n,r),setTimeout(()=>{r.status="COMPLETE"},100),r}createFirewallRuleGroup(e){let n=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,r={id:n,name:e.name,rules:e.rules.map((i,s)=>({id:`rule-${n}-${s}`,...i})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(n,r),r}createBlockRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"BLOCK",blockResponse:e.blockResponse||"NODATA",blockOverrideDomain:e.blockOverrideDomain,firewallDomainListId:e.domainListId}]})}createAllowRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"ALLOW",firewallDomainListId:e.domainListId}]})}createDNSFirewall(e){let n=`firewall-${Date.now()}-${this.firewallCounter++}`,r={id:n,name:e.name,firewallRuleGroupAssociations:e.ruleGroupAssociations.map((i,s)=>({id:`assoc-${n}-${s}`,vpcId:e.vpcId,firewallRuleGroupId:i.firewallRuleGroupId,priority:i.priority,mutationProtection:i.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(n,r),r}createMalwareProtectionFirewall(e){let n=this.createFirewallDomainList({name:`${e.name}-malware-domains`,domains:e.maliciousDomains}),r=this.createBlockRule({name:`${e.name}-block-malware`,priority:100,domainListId:n.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:e.name,vpcId:e.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:r.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(e){return this.endpoints.get(e)}listEndpoints(e){let n=Array.from(this.endpoints.values());return e?n.filter((r)=>r.direction===e):n}getRule(e){return this.rules.get(e)}listRules(){return Array.from(this.rules.values())}getFirewall(e){return this.firewalls.get(e)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(e){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:e.name,Direction:e.direction,IpAddresses:e.ipAddresses.map((n)=>({SubnetId:n.subnetId,...n.ip&&{Ip:n.ip}})),SecurityGroupIds:e.securityGroupIds}}}generateResolverRuleCF(e){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:e.name,RuleType:e.ruleType,DomainName:e.domainName,...e.targetIps&&{TargetIps:e.targetIps.map((n)=>({Ip:n.ip,Port:n.port||53}))},...e.resolverEndpointId&&{ResolverEndpointId:e.resolverEndpointId}}}}generateFirewallRuleGroupCF(e){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:e.name,FirewallRules:e.rules.map((n)=>({Name:n.name,Priority:n.priority,Action:n.action,FirewallDomainListId:n.firewallDomainListId,...n.blockResponse&&{BlockResponse:n.blockResponse},...n.blockOverrideDomain&&{BlockOverrideDomain:n.blockOverrideDomain},...n.blockOverrideTTL&&{BlockOverrideTtl:n.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 Kf=new Gl;class ql{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(e){let n=`bounce-${Date.now()}-${this.bounceCounter++}`,r={id:n,...e};if(this.bounces.set(n,r),e.bounceType==="Permanent")this.addToSuppressionList({emailAddress:e.recipient,reason:"BOUNCE"});return r}recordComplaint(e){let n=`complaint-${Date.now()}-${this.complaintCounter++}`,r={id:n,...e};this.complaints.set(n,r);for(let i of e.recipients)this.addToSuppressionList({emailAddress:i,reason:"COMPLAINT"});return r}createBounceHandler(e){let n=`handler-${Date.now()}-${this.handlerCounter++}`,r={id:n,...e};return this.handlers.set(n,r),r}createAutomaticBounceHandler(e){return this.createBounceHandler({name:e.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:e.notificationTopicArn})}addToSuppressionList(e){let n=`suppression-${Date.now()}-${this.suppressionCounter++}`,r=e.expirationDays?new Date(Date.now()+e.expirationDays*24*60*60*1000):void 0,i={id:n,emailAddress:e.emailAddress,reason:e.reason,suppressedAt:new Date,expiresAt:r,bounceCount:e.reason==="BOUNCE"?1:0,complaintCount:e.reason==="COMPLAINT"?1:0};return this.suppressionList.set(e.emailAddress,i),i}removeFromSuppressionList(e){return this.suppressionList.delete(e)}isSuppressed(e){let n=this.suppressionList.get(e);if(!n)return!1;if(n.expiresAt&&n.expiresAt<new Date)return this.suppressionList.delete(e),!1;return!0}getBounceStatistics(e,n){let r=Array.from(this.bounces.values()).filter((p)=>p.timestamp>=e&&p.timestamp<=n),i=r.length,s=r.filter((p)=>p.bounceType==="Permanent").length,a=r.filter((p)=>p.bounceType==="Transient").length,c=i*10,u=i/c*100,d=new Map;for(let p of r)d.set(p.recipient,(d.get(p.recipient)||0)+1);let m=Array.from(d.entries()).map(([p,g])=>({email:p,count:g})).sort((p,g)=>g.count-p.count).slice(0,10);return{totalBounces:i,permanentBounces:s,transientBounces:a,bounceRate:u,topRecipients:m}}getComplaintStatistics(e,n){let r=Array.from(this.complaints.values()).filter((d)=>d.timestamp>=e&&d.timestamp<=n),i=r.length,s=new Set;for(let d of r)for(let m of d.recipients)s.add(m);let a=s.size,c=i*1000,u=i/c*100;return{totalComplaints:i,uniqueComplainters:a,complaintRate:u}}calculateReputationMetrics(){let e=`metrics-${Date.now()}-${this.metricsCounter++}`,n=new Date,r=new Date(n.getTime()-86400000),i=this.getBounceStatistics(r,n),s=this.getComplaintStatistics(r,n),a;if(i.bounceRate>10||s.complaintRate>0.5)a="Shutdown";else if(i.bounceRate>5||s.complaintRate>0.1)a="Probation";else if(i.bounceRate>2||s.complaintRate>0.05)a="Warning";else a="Good";let c={id:e,timestamp:n,bounceRate:i.bounceRate,complaintRate:s.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:i.totalBounces*10,reputationStatus:a};return this.metrics.set(e,c),c}getBounces(e){let n=Array.from(this.bounces.values());return e?n.filter((r)=>r.messageId===e):n}getComplaints(e){let n=Array.from(this.complaints.values());return e?n.filter((r)=>r.messageId===e):n}listSuppressionList(e){let n=Array.from(this.suppressionList.values());return e?n.filter((r)=>r.reason===e):n}generateSNSSubscriptionCF(e){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:e.topicArn,Endpoint:e.endpoint,Protocol:e.protocol}}}generateEventDestinationCF(e){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:e.configurationSetName,EventDestination:{Name:e.eventDestinationName,Enabled:!0,MatchingEventTypes:e.eventTypes,...e.snsTopicArn&&{SnsDestination:{TopicARN:e.snsTopicArn}},...e.cloudWatchDestination&&{CloudWatchDestination:e.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 Jf=new ql;class Wl{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(e){let n=`event-${Date.now()}-${this.eventCounter++}`,r={id:n,...e};if(this.events.set(n,r),e.tags?.campaignId)this.updateCampaignStats(e.tags.campaignId,e.eventType);return r}trackOpen(e){return this.trackEvent({...e,eventType:"open",timestamp:new Date})}trackClick(e){return this.trackEvent({...e,eventType:"click",timestamp:new Date})}createCampaign(e){let n=`campaign-${Date.now()}-${this.campaignCounter++}`,r={id:n,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...e};return this.campaigns.set(n,r),r}updateCampaignStats(e,n){let r=this.campaigns.get(e);if(!r)return;switch(n){case"send":r.sentCount++;break;case"delivery":r.deliveredCount++;break;case"open":r.openCount++;break;case"click":r.clickCount++;break;case"bounce":r.bounceCount++;break;case"complaint":r.complaintCount++;break}}generateReport(e){let n=`report-${Date.now()}-${this.reportCounter++}`,r=Array.from(this.events.values()).filter((v)=>{let I=v.timestamp>=e.startDate&&v.timestamp<=e.endDate,D=!e.campaignId||v.tags?.campaignId===e.campaignId;return I&&D}),i=r.filter((v)=>v.eventType==="send").length,s=r.filter((v)=>v.eventType==="delivery").length,a=r.filter((v)=>v.eventType==="open").length,c=r.filter((v)=>v.eventType==="click").length,u=r.filter((v)=>v.eventType==="bounce").length,d=r.filter((v)=>v.eventType==="complaint").length,m=i>0?s/i*100:0,p=s>0?a/s*100:0,g=s>0?c/s*100:0,y=a>0?c/a*100:0,h=i>0?u/i*100:0,f=s>0?d/s*100:0,S=new Map;for(let v of r)if(v.eventType==="click"){let I=v;S.set(I.link,(S.get(I.link)||0)+1)}let C=Array.from(S.entries()).map(([v,I])=>({link:v,clicks:I})).sort((v,I)=>I.clicks-v.clicks).slice(0,10),P={desktop:0,mobile:0,tablet:0,unknown:0};for(let v of r)if(v.eventType==="open"||v.eventType==="click"){let I=v.userAgent.toLowerCase();if(I.includes("mobile"))P.mobile++;else if(I.includes("tablet"))P.tablet++;else if(I.includes("mozilla"))P.desktop++;else P.unknown++}let E={id:n,campaignId:e.campaignId,startDate:e.startDate,endDate:e.endDate,totalSent:i,totalDelivered:s,totalOpened:a,totalClicked:c,totalBounced:u,totalComplaints:d,deliveryRate:m,openRate:p,clickRate:g,clickToOpenRate:y,bounceRate:h,complaintRate:f,topLinks:C,deviceBreakdown:P,locationBreakdown:{}};return this.reports.set(n,E),E}createABTest(e){let n=`abtest-${Date.now()}-${this.abTestCounter++}`,r={id:n,name:e.name,variants:e.variants.map((i,s)=>({id:`variant-${n}-${s}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...i})),status:"draft"};return this.abTests.set(n,r),r}startABTest(e){let n=this.abTests.get(e);if(!n)throw Error(`A/B test not found: ${e}`);return n.status="running",n.startedAt=new Date,n}completeABTest(e){let n=this.abTests.get(e);if(!n)throw Error(`A/B test not found: ${e}`);let r=n.variants[0],i=0;for(let s of n.variants){let a=s.sentCount>0?s.openCount/s.sentCount:0;if(a>i)i=a,r=s}return n.status="completed",n.completedAt=new Date,n.winner=r.id,n}getCampaign(e){return this.campaigns.get(e)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(e){let n=Array.from(this.events.values());if(e?.messageId)n=n.filter((r)=>r.messageId===e.messageId);if(e?.eventType)n=n.filter((r)=>r.eventType===e.eventType);if(e?.startDate)n=n.filter((r)=>r.timestamp>=e.startDate);if(e?.endDate)n=n.filter((r)=>r.timestamp<=e.endDate);return n}generateTrackingConfigurationCF(e){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:e.configurationSetName,...e.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 Xf=new Wl;class Kl{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let e=`dashboard-${Date.now()}-${this.dashboardCounter++}`,n=Math.random()*5,r=Math.random()*0.5,i=Math.floor(Math.random()*10),s=Math.max(0,100-n*10-r*100-i*2),a=[];if(n>2)a.push("Reduce bounce rate by cleaning email list");if(r>0.1)a.push("Review email content and unsubscribe process");if(i>5)a.push("Improve email relevance and targeting");let c={id:e,timestamp:new Date,overallScore:s,bounceRate:n,complaintRate:r,spamReports:i,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:a};return this.dashboards.set(e,c),c}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(e){let n=`warmup-${Date.now()}-${this.warmupCounter++}`,r=[],i=(e.targetDailyLimit-e.initialDailyLimit)/e.durationDays;for(let a=0;a<e.durationDays;a++)r.push(Math.floor(e.initialDailyLimit+i*a));let s={id:n,name:e.name,startDate:new Date,currentDay:1,totalDays:e.durationDays,dailyLimits:r,currentLimit:r[0],status:"active"};return this.warmupPlans.set(n,s),s}createAggressiveWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(e){let n=this.warmupPlans.get(e);if(!n)throw Error(`Warmup plan not found: ${e}`);if(n.currentDay<n.totalDays)n.currentDay++,n.currentLimit=n.dailyLimits[n.currentDay-1];if(n.currentDay>=n.totalDays)n.status="completed";return n}trackDomainReputation(e){let n=`domain-${Date.now()}-${this.domainCounter++}`,r=e.delivered/e.totalSent*100,i=e.delivered>0?e.opened/e.delivered*100:0,s=e.delivered>0?e.clicked/e.delivered*100:0,a=e.bounced/e.totalSent*100,c=e.delivered>0?e.complained/e.delivered*100:0,u=i*0.4+s*0.6,d=Math.max(0,100-a*10-c*100+u*0.2),m={id:n,domain:e.domain,reputationScore:d,totalSent:e.totalSent,deliveryRate:r,openRate:i,clickRate:s,bounceRate:a,complaintRate:c,engagementScore:u};return this.domainReputations.set(e.domain,m),m}getDomainReputation(e){return this.domainReputations.get(e)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(e){return this.warmupPlans.get(e)}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 Qf=new Kl;class Jl{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(e){let n=`template-${Date.now()}-${this.templateCounter++}`,r=this.extractVariables(e.subject+e.htmlPart+e.textPart),i={id:n,variables:r,createdAt:new Date,updatedAt:new Date,version:1,...e};return this.templates.set(n,i),this.addVersion({templateId:n,version:1,subject:e.subject,htmlPart:e.htmlPart,textPart:e.textPart,createdBy:"system"}),i}createWelcomeTemplate(e){return this.createTemplate({name:e.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3752
3752
  <html>
3753
3753
  <body>
3754
3754
  <h1>Welcome, {{userName}}!</h1>
@@ -3768,7 +3768,7 @@ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let u={si
3768
3768
  <p>If you didn't request this, please ignore this email.</p>
3769
3769
  </body>
3770
3770
  </html>
3771
- `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(e,n,r){let i=this.templates.get(e);if(!i)throw Error(`Template not found: ${e}`);if(n.subject)i.subject=n.subject;if(n.htmlPart)i.htmlPart=n.htmlPart;if(n.textPart)i.textPart=n.textPart;return i.version++,i.updatedAt=new Date,i.variables=this.extractVariables(i.subject+i.htmlPart+i.textPart),this.addVersion({templateId:e,version:i.version,subject:i.subject,htmlPart:i.htmlPart,textPart:i.textPart,createdBy:"system",changelog:r}),i}addVersion(e){let r={id:`version-${e.templateId}-${e.version}`,createdAt:new Date,...e},i=this.versions.get(e.templateId)||[];return i.push(r),this.versions.set(e.templateId,i),r}extractVariables(e){let n=/\{\{([^}]+)\}\}/g,r=new Set,i;while((i=n.exec(e))!==null)r.add(i[1].trim());return Array.from(r)}renderTemplate(e,n){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);let i=(s)=>s.replace(/\{\{([^}]+)\}\}/g,(a,c)=>{let u=c.trim();return n[u]!==void 0?String(n[u]):a});return{subject:i(r.subject),html:i(r.htmlPart),text:i(r.textPart)}}testTemplate(e,n){let r=`test-${Date.now()}-${this.testCounter++}`,i=this.renderTemplate(e,n),s={id:r,templateId:e,testData:n,renderedSubject:i.subject,renderedHtml:i.html,renderedText:i.text,timestamp:new Date};return this.tests.set(r,s),s}getTemplate(e){return this.templates.get(e)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(e){return this.versions.get(e)||[]}revertToVersion(e,n){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);let s=(this.versions.get(e)||[]).find((a)=>a.version===n);if(!s)throw Error(`Version ${n} not found for template ${e}`);return r.subject=s.subject,r.htmlPart=s.htmlPart,r.textPart=s.textPart,r.version++,r.updatedAt=new Date,this.addVersion({templateId:e,version:r.version,subject:r.subject,htmlPart:r.htmlPart,textPart:r.textPart,createdBy:"system",changelog:`Reverted to version ${n}`}),r}generateTemplateCF(e){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:e.name,SubjectPart:e.subject,HtmlPart:e.htmlPart,TextPart:e.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var Kf=new Gl;var ql={};Xt(ql,{EmailAnalyticsModule:()=>He,EmailRules:()=>Bt,EmailScheduling:()=>Ot,EmailSearch:()=>Mt,EmailTemplates:()=>me,EmailThreading:()=>Lt,SharedMailboxes:()=>$t});class Mt{static createSearchDomain(e){let{slug:n,environment:r,domainName:i,instanceType:s="t3.small.search",instanceCount:a=1,ebsVolumeSize:c=10,masterUserName:u="admin",masterUserPassword:d}=e,m=i||`${n}-${r}-email-search`;return{[`${n}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:m,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:s,InstanceCount:a,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:c},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:u,MasterUserPassword:d||`${n}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${m}/*`}]}}}}}static createIndexerLambda(e){return{[`${e.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Mt.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:e.searchDomainEndpoint,EMAIL_BUCKET:e.emailBucket}}}}}}static IndexerLambdaCode=`
3771
+ `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(e,n,r){let i=this.templates.get(e);if(!i)throw Error(`Template not found: ${e}`);if(n.subject)i.subject=n.subject;if(n.htmlPart)i.htmlPart=n.htmlPart;if(n.textPart)i.textPart=n.textPart;return i.version++,i.updatedAt=new Date,i.variables=this.extractVariables(i.subject+i.htmlPart+i.textPart),this.addVersion({templateId:e,version:i.version,subject:i.subject,htmlPart:i.htmlPart,textPart:i.textPart,createdBy:"system",changelog:r}),i}addVersion(e){let r={id:`version-${e.templateId}-${e.version}`,createdAt:new Date,...e},i=this.versions.get(e.templateId)||[];return i.push(r),this.versions.set(e.templateId,i),r}extractVariables(e){let n=/\{\{([^}]+)\}\}/g,r=new Set,i;while((i=n.exec(e))!==null)r.add(i[1].trim());return Array.from(r)}renderTemplate(e,n){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);let i=(s)=>s.replace(/\{\{([^}]+)\}\}/g,(a,c)=>{let u=c.trim();return n[u]!==void 0?String(n[u]):a});return{subject:i(r.subject),html:i(r.htmlPart),text:i(r.textPart)}}testTemplate(e,n){let r=`test-${Date.now()}-${this.testCounter++}`,i=this.renderTemplate(e,n),s={id:r,templateId:e,testData:n,renderedSubject:i.subject,renderedHtml:i.html,renderedText:i.text,timestamp:new Date};return this.tests.set(r,s),s}getTemplate(e){return this.templates.get(e)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(e){return this.versions.get(e)||[]}revertToVersion(e,n){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);let s=(this.versions.get(e)||[]).find((a)=>a.version===n);if(!s)throw Error(`Version ${n} not found for template ${e}`);return r.subject=s.subject,r.htmlPart=s.htmlPart,r.textPart=s.textPart,r.version++,r.updatedAt=new Date,this.addVersion({templateId:e,version:r.version,subject:r.subject,htmlPart:r.htmlPart,textPart:r.textPart,createdBy:"system",changelog:`Reverted to version ${n}`}),r}generateTemplateCF(e){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:e.name,SubjectPart:e.subject,HtmlPart:e.htmlPart,TextPart:e.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var Yf=new Jl;var Xl={};Xt(Xl,{EmailAnalyticsModule:()=>He,EmailRules:()=>Bt,EmailScheduling:()=>Ot,EmailSearch:()=>Mt,EmailTemplates:()=>me,EmailThreading:()=>Lt,SharedMailboxes:()=>$t});class Mt{static createSearchDomain(e){let{slug:n,environment:r,domainName:i,instanceType:s="t3.small.search",instanceCount:a=1,ebsVolumeSize:c=10,masterUserName:u="admin",masterUserPassword:d}=e,m=i||`${n}-${r}-email-search`;return{[`${n}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:m,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:s,InstanceCount:a,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:c},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:u,MasterUserPassword:d||`${n}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${m}/*`}]}}}}}static createIndexerLambda(e){return{[`${e.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Mt.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:e.searchDomainEndpoint,EMAIL_BUCKET:e.emailBucket}}}}}}static IndexerLambdaCode=`
3772
3772
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3773
3773
  const https = require('https');
3774
3774
 
@@ -5139,7 +5139,7 @@ async function invokeLambda(functionName, metadata) {
5139
5139
  Payload: JSON.stringify(metadata),
5140
5140
  }));
5141
5141
  }
5142
- `;static createRulesTable(e){return{[`${e.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.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(e){return{[`${e.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Bt.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,RULES_TABLE:e.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 Wl={};Xt(Wl,{default:()=>ts,handler:()=>es});var es=`
5142
+ `;static createRulesTable(e){return{[`${e.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.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(e){return{[`${e.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Bt.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,RULES_TABLE:e.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 Ql={};Xt(Ql,{default:()=>ts,handler:()=>es});var es=`
5143
5143
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5144
5144
  const s3 = new S3Client({});
5145
5145
 
@@ -5455,7 +5455,7 @@ catch (error) {
5455
5455
 
5456
5456
  return { statusCode: 200, body: 'OK' };
5457
5457
  };
5458
- `;var Kl={};Xt(Kl,{CallAnalytics:()=>_t,CallRecording:()=>Ft,Callbacks:()=>Xe,IVRBuilder:()=>be});class Ft{static RecordingProcessorCode=`
5458
+ `;var Yl={};Xt(Yl,{CallAnalytics:()=>_t,CallRecording:()=>Ft,Callbacks:()=>Xe,IVRBuilder:()=>be});class Ft{static RecordingProcessorCode=`
5459
5459
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
5460
5460
  const { TranscribeClient, StartTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
5461
5461
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -6136,7 +6136,7 @@ catch (error) {
6136
6136
  return { statusCode: 500, error: error.message };
6137
6137
  }
6138
6138
  };
6139
- `;static createCallbacksTable(e){return{[`${e.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(e){return{[`${e.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Xe.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(e){return{[`${e.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:Xe.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,CONNECT_INSTANCE_ID:e.connectInstanceId,CONTACT_FLOW_ID:e.contactFlowId,SOURCE_PHONE_NUMBER:e.sourcePhoneNumber,QUEUE_ID:e.queueId||""}}}}}}}var Jl={};Xt(Jl,{AbTesting:()=>oe,LinkTracking:()=>Qt,MmsSupport:()=>jt,SmsAnalytics:()=>Ut,SmsCampaigns:()=>Vt,SmsChatbot:()=>zt});class Vt{static CampaignManagerCode=`
6139
+ `;static createCallbacksTable(e){return{[`${e.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(e){return{[`${e.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Xe.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(e){return{[`${e.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:Xe.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,CONNECT_INSTANCE_ID:e.connectInstanceId,CONTACT_FLOW_ID:e.contactFlowId,SOURCE_PHONE_NUMBER:e.sourcePhoneNumber,QUEUE_ID:e.queueId||""}}}}}}}var Zl={};Xt(Zl,{AbTesting:()=>oe,LinkTracking:()=>Qt,MmsSupport:()=>jt,SmsAnalytics:()=>Ut,SmsCampaigns:()=>Vt,SmsChatbot:()=>zt});class Vt{static CampaignManagerCode=`
6140
6140
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6141
6141
 
6142
6142
  const dynamodb = new DynamoDBClient({});
@@ -7236,7 +7236,7 @@ function unmarshallTest(item) {
7236
7236
 
7237
7237
  return test;
7238
7238
  }
7239
- `;static createAbTestsTable(e){return{[`${e.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(e){return{[`${e.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:oe.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:e.abTestsTable}}}}}}static selectVariant(e,n){let i=oe.hashString(n+e.id)%100,s=0;for(let a=0;a<e.variants.length;a++)if(s+=e.trafficSplit[a],i<s)return e.variants[a];return e.variants[e.variants.length-1]}static determineWinner(e){if(e.variants.length===0)return null;let n=e.winningCriteria,r=e.variants[0],i=oe.getMetricValue(r,n);for(let s of e.variants.slice(1)){let a=oe.getMetricValue(s,n);if(a>i)i=a,r=s}return r}static calculateSignificance(e,n,r){let i=e.stats.sent,s=n.stats.sent;if(i<30||s<30)return 0;let a=oe.getMetricValue(e,r)/100,c=oe.getMetricValue(n,r)/100,u=(a*i+c*s)/(i+s),d=Math.sqrt(u*(1-u)*(1/i+1/s));if(d===0)return 0;let m=Math.abs(a-c)/d;if(m>=2.576)return 99;if(m>=1.96)return 95;if(m>=1.645)return 90;if(m>=1.28)return 80;return Math.round(m*30)}static getMetricValue(e,n){switch(n){case"delivery_rate":return e.stats.deliveryRate;case"click_rate":return e.stats.clickRate;case"reply_rate":return e.stats.replyRate;case"conversion_rate":return e.stats.conversionRate;default:return e.stats.deliveryRate}}static hashString(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return Math.abs(n)}}class Xl{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(e){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,r=e.name.endsWith(".fifo")?e.name:`${e.name}.fifo`,{name:i,...s}=e,a={id:n,name:r,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${r}`,...s};return this.queues.set(n,a),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:e.contentBasedDeduplication,deduplicationInterval:300}),a}createHighThroughputFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(e){let r={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...e};return this.deduplicationConfigs.set(e.queueId,r),r}sendMessage(e){let n=this.queues.get(e.queueId);if(!n)throw Error(`Queue not found: ${e.queueId}`);let r=this.deduplicationConfigs.get(e.queueId);if(r){let c=e.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(e.messageBody):void 0);if(c&&this.isDuplicate(r,c))return null;if(c)r.deduplicationHashes.set(c,new Date)}let i=`msg-${Date.now()}-${this.messageCounter++}`,s=this.generateSequenceNumber(),a={id:i,messageId:i,messageGroupId:e.messageGroupId,messageDeduplicationId:e.messageDeduplicationId,body:e.messageBody,attributes:e.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:s};return this.messages.set(i,a),this.updateMessageGroup(e.queueId,e.messageGroupId),a}isDuplicate(e,n){let r=e.deduplicationHashes.get(n);if(!r)return!1;if((Date.now()-r.getTime())/1000>e.deduplicationInterval)return e.deduplicationHashes.delete(n),!1;return!0}generateHash(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(e,n){let r=`${e}-${n}`,i=this.messageGroups.get(r);if(!i)i={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:e,messagesInFlight:0},this.messageGroups.set(r,i);i.messagesInFlight++,i.lastMessageTimestamp=new Date}getMessageGroups(e){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===e)}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getMessages(e,n){let r=Array.from(this.messages.values());if(n)r=r.filter((i)=>i.messageGroupId===n);return r.sort((i,s)=>i.sequenceNumber.localeCompare(s.sequenceNumber))}generateFIFOQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.name,FifoQueue:!0,ContentBasedDeduplication:e.contentBasedDeduplication,DeduplicationScope:e.deduplicationScope,FifoThroughputLimit:e.fifoThroughputLimit,MessageRetentionPeriod:e.messageRetentionPeriod,VisibilityTimeout:e.visibilityTimeout,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime,...e.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:e.deadLetterTargetArn,maxReceiveCount:e.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 Jf=new Xl;class Ql{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(e){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,r={id:n,...e};return this.monitors.set(n,r),r}createAutomatedMonitor(e){return this.createDLQMonitor({name:e.name,queueUrl:e.queueUrl,sourceQueues:e.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:e.notificationTopicArn})}collectMetrics(e){let r={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},i=this.metrics.get(e)||[];return i.push(r),this.metrics.set(e,i),this.checkForAlerts(e,r),r}checkForAlerts(e,n){let r=Array.from(this.monitors.values()).find((s)=>s.queueUrl===e);if(!r)return;if(n.approximateNumberOfMessages>=r.alarmThreshold)this.createAlert({monitorId:r.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${r.name} has ${n.approximateNumberOfMessages} messages (threshold: ${r.alarmThreshold})`});let i=3600;if(n.approximateAgeOfOldestMessage>i)this.createAlert({monitorId:r.id,alertType:"old_message",severity:"medium",message:`DLQ ${r.name} has messages older than ${i} seconds`})}createAlert(e){let n=`alert-${Date.now()}-${this.alertCounter++}`,r={id:n,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(n,r),r}acknowledgeAlert(e){let n=this.alerts.get(e);if(!n)throw Error(`Alert not found: ${e}`);return n.acknowledged=!0,n}createReprocessJob(e){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,r={id:n,queueUrl:e.queueUrl,messageId:e.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,r),r}async executeReprocessJob(e){let n=this.reprocessJobs.get(e);if(!n)throw Error(`Reprocess job not found: ${e}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((i)=>setTimeout(i,100));let r=Math.random()>0.3;if(n.status=r?"success":"failed",n.completedAt=new Date,!r)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(e){let n=[];for(let r=0;r<e.maxMessages;r++){let i=this.createReprocessJob({queueUrl:e.queueUrl,messageId:`msg-${r}`});await this.executeReprocessJob(i.id),n.push(i)}return n}getDLQStatistics(e,n=24){let r=new Date(Date.now()-n*60*60*1000),i=(this.metrics.get(e)||[]).filter((p)=>p.timestamp>=r);if(i.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let s=i[i.length-1],a=i.reduce((p,g)=>p+g.messagesReceived,0),c=i.reduce((p,g)=>p+g.messagesDeleted,0),u=i.reduce((p,g)=>p+g.messagesReprocessed,0),d=i.reduce((p,g)=>p+g.approximateAgeOfOldestMessage,0)/i.length,m=u>0?c/u*100:0;return{totalMessages:s.approximateNumberOfMessages,avgAge:d,messagesReceived:a,messagesDeleted:c,messagesReprocessed:u,successRate:m}}getMonitor(e){return this.monitors.get(e)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(e,n){let r=Array.from(this.alerts.values());if(e)r=r.filter((i)=>i.monitorId===e);if(n!==void 0)r=r.filter((i)=>i.acknowledged===n);return r.sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime())}getReprocessJobs(e){let n=Array.from(this.reprocessJobs.values());if(e)n=n.filter((r)=>r.queueUrl===e);return n}generateDLQAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${e.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:e.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:e.queueUrl.split("/").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 Xf=new Ql;class Yl{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(e){let n=`batch-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createHighThroughputConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(e){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(e.configId))throw Error(`Batch config not found: ${e.configId}`);let i=[];for(let a=0;a<e.messageCount;a++)i.push({id:`msg-${n}-${a}`,messageId:`${n}-${a}`,body:`Message ${a}`,receiptHandle:`receipt-${n}-${a}`,attributes:{},status:"pending"});let s={id:n,configId:e.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(e){let n=this.jobs.get(e);if(!n)throw Error(`Batch job not found: ${e}`);let r=this.configs.get(n.configId);if(!r)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let i=this.chunkArray(n.messages,r.batchSize);for(let s of i)await this.processBatch(s,r);return n.processedCount=n.messages.filter((s)=>s.status==="success").length,n.failedCount=n.messages.filter((s)=>s.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(r.id,n),n}async processBatch(e,n){let r=e.map((i)=>this.processMessage(i,n));await Promise.all(r)}async processMessage(e,n){e.status="processing";let r=Date.now();await new Promise((a)=>setTimeout(a,Math.random()*100));let i=Date.now()-r;if(e.processingTime=i,Math.random()>0.1)e.status="success";else e.status="failed",e.error="Processing error"}chunkArray(e,n){let r=[];for(let i=0;i<e.length;i+=n)r.push(e.slice(i,i+n));return r}collectProcessorMetrics(e,n){let r=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((g)=>g.status==="success").map((g)=>g.processingTime||0).filter((g)=>g>0),a=s.length>0?s.reduce((g,y)=>g+y,0)/s.length:0,c=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/c,d=n.messages.length>0?n.failedCount/n.messages.length*100:0,m={id:r,configId:e,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:a,throughput:u,errorRate:d},p=this.metrics.get(e)||[];p.push(m),this.metrics.set(e,p)}getBatchStatistics(e){let n=this.metrics.get(e)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let r=n.reduce((c,u)=>c+u.messagesProcessed,0),i=n.reduce((c,u)=>c+u.throughput,0)/n.length,s=n.reduce((c,u)=>c+u.errorRate,0)/n.length,a=n.reduce((c,u)=>c+u.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:r,averageThroughput:i,averageErrorRate:s,averageProcessingTime:a}}optimizeBatchConfig(e){let n=this.configs.get(e);if(!n)throw Error(`Batch config not found: ${e}`);let r=this.getBatchStatistics(e);if(r.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(r.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(r.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getJob(e){return this.jobs.get(e)}listJobs(e){let n=Array.from(this.jobs.values());if(e)n=n.filter((r)=>r.configId===e);return n}generateBatchProcessorCF(e){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${e.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:e.batchSize,MaximumBatchingWindowInSeconds:e.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var Qf=new Yl;class Zl{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(e){let n=`queue-${Date.now()}-${this.queueCounter++}`,r={id:n,purgeInProgress:!1,...e};return this.queues.set(n,r),r}createStandardQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:(e.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:e.waitTimeSeconds||20})}createRetentionPolicy(e){let n=`retention-${Date.now()}-${this.retentionCounter++}`,r={id:n,...e};this.retentionPolicies.set(n,r);let i=this.queues.get(e.queueId);if(i)i.messageRetentionPeriod=e.retentionPeriod;return r}createShortRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:e.s3Bucket})}createDelayQueue(e){let n=`delay-${Date.now()}-${this.delayCounter++}`,r={id:n,...e};this.delayQueues.set(n,r);let i=Array.from(this.queues.values()).find((s)=>s.queueUrl===e.queueUrl);if(i)i.delaySeconds=e.defaultDelay;return r}createScheduledDelayQueue(e){return this.createDelayQueue({queueUrl:e.queueUrl,defaultDelay:e.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(e){let n=this.queues.get(e);if(!n)throw Error(`Queue not found: ${e}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let r=`purge-${Date.now()}-${this.purgeCounter++}`,i={id:r,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(r,i),n.purgeInProgress=!0,setTimeout(()=>{i.status="completed",i.completedAt=new Date,i.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),i}collectQueueMetrics(e){let r={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},i=this.metrics.get(e)||[];return i.push(r),this.metrics.set(e,i),r}getQueueHealth(e){let n=this.metrics.get(e)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let r=n[n.length-1],i=[],s=[],a="healthy";if(r.approximateNumberOfMessages>1e4)a="critical",i.push("Large message backlog detected"),s.push("Increase consumer capacity");else if(r.approximateNumberOfMessages>1000)a="warning",i.push("Growing message backlog"),s.push("Monitor consumer performance");if(r.oldestMessageAge&&r.oldestMessageAge>3600){if(a!=="critical")a="warning";i.push("Old messages in queue"),s.push("Review message processing")}if(r.approximateNumberOfMessagesDelayed>100){if(a!=="critical")a="warning";i.push("High number of delayed messages")}return{status:a,issues:i,recommendations:s}}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(e){return this.retentionPolicies.get(e)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(e){let n=Array.from(this.purgeOperations.values());if(e)n=n.filter((r)=>r.queueUrl===e);return n}generateQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.queueName,MessageRetentionPeriod:e.messageRetentionPeriod,DelaySeconds:e.delaySeconds,MaximumMessageSize:e.maximumMessageSize,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime}}}generateCleanupRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{Name:`${e.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:e.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:e.id,Input:JSON.stringify({queueId:e.queueId,archiveBucket:e.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 Yf=new Zl;import{deflateRawSync as ns}from"node:zlib";var rs=(()=>{let e=[];for(let n=0;n<256;n++){let r=n;for(let i=0;i<8;i++)r=r&1?3988292384^r>>>1:r>>>1;e[n]=r>>>0}return e})();function is(e){let n=4294967295;for(let r=0;r<e.length;r++)n=rs[(n^e[r])&255]^n>>>8;return(n^4294967295)>>>0}function ss(e){if(typeof e==="string")return Buffer.from(e,"utf-8");if(Buffer.isBuffer(e))return e;return Buffer.from(e)}function as(e){let n=Math.max(1980,e.getFullYear()),r=(e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1)&65535,i=(n-1980<<9|e.getMonth()+1<<5|e.getDate())&65535;return{time:r,date:i}}function It(e){let n=[],r=[],i=0;for(let c of e){let u=ss(c.data),d=ns(u),m=is(u),p=Buffer.from(c.name.replace(/\\/g,"/"),"utf-8"),{time:g,date:y}=as(c.date??new Date(0)),h=c.mode??420,f=Buffer.alloc(30+p.length);f.writeUInt32LE(67324752,0),f.writeUInt16LE(20,4),f.writeUInt16LE(0,6),f.writeUInt16LE(8,8),f.writeUInt16LE(g,10),f.writeUInt16LE(y,12),f.writeUInt32LE(m,14),f.writeUInt32LE(d.length,18),f.writeUInt32LE(u.length,22),f.writeUInt16LE(p.length,26),f.writeUInt16LE(0,28),p.copy(f,30);let S=Buffer.alloc(46+p.length);S.writeUInt32LE(33639248,0),S.writeUInt16LE(798,4),S.writeUInt16LE(20,6),S.writeUInt16LE(0,8),S.writeUInt16LE(8,10),S.writeUInt16LE(g,12),S.writeUInt16LE(y,14),S.writeUInt32LE(m,16),S.writeUInt32LE(d.length,20),S.writeUInt32LE(u.length,24),S.writeUInt16LE(p.length,28),S.writeUInt16LE(0,30),S.writeUInt16LE(0,32),S.writeUInt16LE(0,34),S.writeUInt16LE(0,36),S.writeUInt32LE((h&65535)<<16,38),S.writeUInt32LE(i,42),p.copy(S,46),n.push(f,d),r.push(S),i+=f.length+d.length}let s=Buffer.concat(r),a=Buffer.alloc(22);return a.writeUInt32LE(101010256,0),a.writeUInt16LE(0,4),a.writeUInt16LE(0,6),a.writeUInt16LE(e.length,8),a.writeUInt16LE(e.length,10),a.writeUInt32LE(s.length,12),a.writeUInt32LE(i,16),a.writeUInt16LE(0,20),Buffer.concat([...n,s,a])}function ed(e){let n=e.adapterImport??"./adapter",r=e.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7239
+ `;static createAbTestsTable(e){return{[`${e.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(e){return{[`${e.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:oe.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:e.abTestsTable}}}}}}static selectVariant(e,n){let i=oe.hashString(n+e.id)%100,s=0;for(let a=0;a<e.variants.length;a++)if(s+=e.trafficSplit[a],i<s)return e.variants[a];return e.variants[e.variants.length-1]}static determineWinner(e){if(e.variants.length===0)return null;let n=e.winningCriteria,r=e.variants[0],i=oe.getMetricValue(r,n);for(let s of e.variants.slice(1)){let a=oe.getMetricValue(s,n);if(a>i)i=a,r=s}return r}static calculateSignificance(e,n,r){let i=e.stats.sent,s=n.stats.sent;if(i<30||s<30)return 0;let a=oe.getMetricValue(e,r)/100,c=oe.getMetricValue(n,r)/100,u=(a*i+c*s)/(i+s),d=Math.sqrt(u*(1-u)*(1/i+1/s));if(d===0)return 0;let m=Math.abs(a-c)/d;if(m>=2.576)return 99;if(m>=1.96)return 95;if(m>=1.645)return 90;if(m>=1.28)return 80;return Math.round(m*30)}static getMetricValue(e,n){switch(n){case"delivery_rate":return e.stats.deliveryRate;case"click_rate":return e.stats.clickRate;case"reply_rate":return e.stats.replyRate;case"conversion_rate":return e.stats.conversionRate;default:return e.stats.deliveryRate}}static hashString(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return Math.abs(n)}}class ed{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(e){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,r=e.name.endsWith(".fifo")?e.name:`${e.name}.fifo`,{name:i,...s}=e,a={id:n,name:r,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${r}`,...s};return this.queues.set(n,a),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:e.contentBasedDeduplication,deduplicationInterval:300}),a}createHighThroughputFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(e){let r={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...e};return this.deduplicationConfigs.set(e.queueId,r),r}sendMessage(e){let n=this.queues.get(e.queueId);if(!n)throw Error(`Queue not found: ${e.queueId}`);let r=this.deduplicationConfigs.get(e.queueId);if(r){let c=e.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(e.messageBody):void 0);if(c&&this.isDuplicate(r,c))return null;if(c)r.deduplicationHashes.set(c,new Date)}let i=`msg-${Date.now()}-${this.messageCounter++}`,s=this.generateSequenceNumber(),a={id:i,messageId:i,messageGroupId:e.messageGroupId,messageDeduplicationId:e.messageDeduplicationId,body:e.messageBody,attributes:e.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:s};return this.messages.set(i,a),this.updateMessageGroup(e.queueId,e.messageGroupId),a}isDuplicate(e,n){let r=e.deduplicationHashes.get(n);if(!r)return!1;if((Date.now()-r.getTime())/1000>e.deduplicationInterval)return e.deduplicationHashes.delete(n),!1;return!0}generateHash(e){let n=0;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);n=(n<<5)-n+i,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(e,n){let r=`${e}-${n}`,i=this.messageGroups.get(r);if(!i)i={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:e,messagesInFlight:0},this.messageGroups.set(r,i);i.messagesInFlight++,i.lastMessageTimestamp=new Date}getMessageGroups(e){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===e)}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getMessages(e,n){let r=Array.from(this.messages.values());if(n)r=r.filter((i)=>i.messageGroupId===n);return r.sort((i,s)=>i.sequenceNumber.localeCompare(s.sequenceNumber))}generateFIFOQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.name,FifoQueue:!0,ContentBasedDeduplication:e.contentBasedDeduplication,DeduplicationScope:e.deduplicationScope,FifoThroughputLimit:e.fifoThroughputLimit,MessageRetentionPeriod:e.messageRetentionPeriod,VisibilityTimeout:e.visibilityTimeout,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime,...e.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:e.deadLetterTargetArn,maxReceiveCount:e.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 Zf=new ed;class td{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(e){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,r={id:n,...e};return this.monitors.set(n,r),r}createAutomatedMonitor(e){return this.createDLQMonitor({name:e.name,queueUrl:e.queueUrl,sourceQueues:e.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:e.notificationTopicArn})}collectMetrics(e){let r={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},i=this.metrics.get(e)||[];return i.push(r),this.metrics.set(e,i),this.checkForAlerts(e,r),r}checkForAlerts(e,n){let r=Array.from(this.monitors.values()).find((s)=>s.queueUrl===e);if(!r)return;if(n.approximateNumberOfMessages>=r.alarmThreshold)this.createAlert({monitorId:r.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${r.name} has ${n.approximateNumberOfMessages} messages (threshold: ${r.alarmThreshold})`});let i=3600;if(n.approximateAgeOfOldestMessage>i)this.createAlert({monitorId:r.id,alertType:"old_message",severity:"medium",message:`DLQ ${r.name} has messages older than ${i} seconds`})}createAlert(e){let n=`alert-${Date.now()}-${this.alertCounter++}`,r={id:n,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(n,r),r}acknowledgeAlert(e){let n=this.alerts.get(e);if(!n)throw Error(`Alert not found: ${e}`);return n.acknowledged=!0,n}createReprocessJob(e){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,r={id:n,queueUrl:e.queueUrl,messageId:e.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,r),r}async executeReprocessJob(e){let n=this.reprocessJobs.get(e);if(!n)throw Error(`Reprocess job not found: ${e}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((i)=>setTimeout(i,100));let r=Math.random()>0.3;if(n.status=r?"success":"failed",n.completedAt=new Date,!r)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(e){let n=[];for(let r=0;r<e.maxMessages;r++){let i=this.createReprocessJob({queueUrl:e.queueUrl,messageId:`msg-${r}`});await this.executeReprocessJob(i.id),n.push(i)}return n}getDLQStatistics(e,n=24){let r=new Date(Date.now()-n*60*60*1000),i=(this.metrics.get(e)||[]).filter((p)=>p.timestamp>=r);if(i.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let s=i[i.length-1],a=i.reduce((p,g)=>p+g.messagesReceived,0),c=i.reduce((p,g)=>p+g.messagesDeleted,0),u=i.reduce((p,g)=>p+g.messagesReprocessed,0),d=i.reduce((p,g)=>p+g.approximateAgeOfOldestMessage,0)/i.length,m=u>0?c/u*100:0;return{totalMessages:s.approximateNumberOfMessages,avgAge:d,messagesReceived:a,messagesDeleted:c,messagesReprocessed:u,successRate:m}}getMonitor(e){return this.monitors.get(e)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(e,n){let r=Array.from(this.alerts.values());if(e)r=r.filter((i)=>i.monitorId===e);if(n!==void 0)r=r.filter((i)=>i.acknowledged===n);return r.sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime())}getReprocessJobs(e){let n=Array.from(this.reprocessJobs.values());if(e)n=n.filter((r)=>r.queueUrl===e);return n}generateDLQAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${e.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:e.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:e.queueUrl.split("/").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 eh=new td;class rd{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(e){let n=`batch-config-${Date.now()}-${this.configCounter++}`,r={id:n,...e};return this.configs.set(n,r),r}createHighThroughputConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(e){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(e.configId))throw Error(`Batch config not found: ${e.configId}`);let i=[];for(let a=0;a<e.messageCount;a++)i.push({id:`msg-${n}-${a}`,messageId:`${n}-${a}`,body:`Message ${a}`,receiptHandle:`receipt-${n}-${a}`,attributes:{},status:"pending"});let s={id:n,configId:e.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(e){let n=this.jobs.get(e);if(!n)throw Error(`Batch job not found: ${e}`);let r=this.configs.get(n.configId);if(!r)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let i=this.chunkArray(n.messages,r.batchSize);for(let s of i)await this.processBatch(s,r);return n.processedCount=n.messages.filter((s)=>s.status==="success").length,n.failedCount=n.messages.filter((s)=>s.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(r.id,n),n}async processBatch(e,n){let r=e.map((i)=>this.processMessage(i,n));await Promise.all(r)}async processMessage(e,n){e.status="processing";let r=Date.now();await new Promise((a)=>setTimeout(a,Math.random()*100));let i=Date.now()-r;if(e.processingTime=i,Math.random()>0.1)e.status="success";else e.status="failed",e.error="Processing error"}chunkArray(e,n){let r=[];for(let i=0;i<e.length;i+=n)r.push(e.slice(i,i+n));return r}collectProcessorMetrics(e,n){let r=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((g)=>g.status==="success").map((g)=>g.processingTime||0).filter((g)=>g>0),a=s.length>0?s.reduce((g,y)=>g+y,0)/s.length:0,c=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/c,d=n.messages.length>0?n.failedCount/n.messages.length*100:0,m={id:r,configId:e,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:a,throughput:u,errorRate:d},p=this.metrics.get(e)||[];p.push(m),this.metrics.set(e,p)}getBatchStatistics(e){let n=this.metrics.get(e)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let r=n.reduce((c,u)=>c+u.messagesProcessed,0),i=n.reduce((c,u)=>c+u.throughput,0)/n.length,s=n.reduce((c,u)=>c+u.errorRate,0)/n.length,a=n.reduce((c,u)=>c+u.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:r,averageThroughput:i,averageErrorRate:s,averageProcessingTime:a}}optimizeBatchConfig(e){let n=this.configs.get(e);if(!n)throw Error(`Batch config not found: ${e}`);let r=this.getBatchStatistics(e);if(r.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(r.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(r.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getJob(e){return this.jobs.get(e)}listJobs(e){let n=Array.from(this.jobs.values());if(e)n=n.filter((r)=>r.configId===e);return n}generateBatchProcessorCF(e){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${e.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:e.batchSize,MaximumBatchingWindowInSeconds:e.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var th=new rd;class nd{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(e){let n=`queue-${Date.now()}-${this.queueCounter++}`,r={id:n,purgeInProgress:!1,...e};return this.queues.set(n,r),r}createStandardQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:(e.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:e.waitTimeSeconds||20})}createRetentionPolicy(e){let n=`retention-${Date.now()}-${this.retentionCounter++}`,r={id:n,...e};this.retentionPolicies.set(n,r);let i=this.queues.get(e.queueId);if(i)i.messageRetentionPeriod=e.retentionPeriod;return r}createShortRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:e.s3Bucket})}createDelayQueue(e){let n=`delay-${Date.now()}-${this.delayCounter++}`,r={id:n,...e};this.delayQueues.set(n,r);let i=Array.from(this.queues.values()).find((s)=>s.queueUrl===e.queueUrl);if(i)i.delaySeconds=e.defaultDelay;return r}createScheduledDelayQueue(e){return this.createDelayQueue({queueUrl:e.queueUrl,defaultDelay:e.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(e){let n=this.queues.get(e);if(!n)throw Error(`Queue not found: ${e}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let r=`purge-${Date.now()}-${this.purgeCounter++}`,i={id:r,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(r,i),n.purgeInProgress=!0,setTimeout(()=>{i.status="completed",i.completedAt=new Date,i.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),i}collectQueueMetrics(e){let r={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},i=this.metrics.get(e)||[];return i.push(r),this.metrics.set(e,i),r}getQueueHealth(e){let n=this.metrics.get(e)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let r=n[n.length-1],i=[],s=[],a="healthy";if(r.approximateNumberOfMessages>1e4)a="critical",i.push("Large message backlog detected"),s.push("Increase consumer capacity");else if(r.approximateNumberOfMessages>1000)a="warning",i.push("Growing message backlog"),s.push("Monitor consumer performance");if(r.oldestMessageAge&&r.oldestMessageAge>3600){if(a!=="critical")a="warning";i.push("Old messages in queue"),s.push("Review message processing")}if(r.approximateNumberOfMessagesDelayed>100){if(a!=="critical")a="warning";i.push("High number of delayed messages")}return{status:a,issues:i,recommendations:s}}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(e){return this.retentionPolicies.get(e)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(e){let n=Array.from(this.purgeOperations.values());if(e)n=n.filter((r)=>r.queueUrl===e);return n}generateQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.queueName,MessageRetentionPeriod:e.messageRetentionPeriod,DelaySeconds:e.delaySeconds,MaximumMessageSize:e.maximumMessageSize,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime}}}generateCleanupRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{Name:`${e.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:e.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:e.id,Input:JSON.stringify({queueId:e.queueId,archiveBucket:e.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 rh=new nd;import{deflateRawSync as ns}from"node:zlib";var rs=(()=>{let e=[];for(let n=0;n<256;n++){let r=n;for(let i=0;i<8;i++)r=r&1?3988292384^r>>>1:r>>>1;e[n]=r>>>0}return e})();function is(e){let n=4294967295;for(let r=0;r<e.length;r++)n=rs[(n^e[r])&255]^n>>>8;return(n^4294967295)>>>0}function ss(e){if(typeof e==="string")return Buffer.from(e,"utf-8");if(Buffer.isBuffer(e))return e;return Buffer.from(e)}function as(e){let n=Math.max(1980,e.getFullYear()),r=(e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1)&65535,i=(n-1980<<9|e.getMonth()+1<<5|e.getDate())&65535;return{time:r,date:i}}function It(e){let n=[],r=[],i=0;for(let c of e){let u=ss(c.data),d=ns(u),m=is(u),p=Buffer.from(c.name.replace(/\\/g,"/"),"utf-8"),{time:g,date:y}=as(c.date??new Date(0)),h=c.mode??420,f=Buffer.alloc(30+p.length);f.writeUInt32LE(67324752,0),f.writeUInt16LE(20,4),f.writeUInt16LE(0,6),f.writeUInt16LE(8,8),f.writeUInt16LE(g,10),f.writeUInt16LE(y,12),f.writeUInt32LE(m,14),f.writeUInt32LE(d.length,18),f.writeUInt32LE(u.length,22),f.writeUInt16LE(p.length,26),f.writeUInt16LE(0,28),p.copy(f,30);let S=Buffer.alloc(46+p.length);S.writeUInt32LE(33639248,0),S.writeUInt16LE(798,4),S.writeUInt16LE(20,6),S.writeUInt16LE(0,8),S.writeUInt16LE(8,10),S.writeUInt16LE(g,12),S.writeUInt16LE(y,14),S.writeUInt32LE(m,16),S.writeUInt32LE(d.length,20),S.writeUInt32LE(u.length,24),S.writeUInt16LE(p.length,28),S.writeUInt16LE(0,30),S.writeUInt16LE(0,32),S.writeUInt16LE(0,34),S.writeUInt16LE(0,36),S.writeUInt32LE((h&65535)<<16,38),S.writeUInt32LE(i,42),p.copy(S,46),n.push(f,d),r.push(S),i+=f.length+d.length}let s=Buffer.concat(r),a=Buffer.alloc(22);return a.writeUInt32LE(101010256,0),a.writeUInt16LE(0,4),a.writeUInt16LE(0,6),a.writeUInt16LE(e.length,8),a.writeUInt16LE(e.length,10),a.writeUInt32LE(s.length,12),a.writeUInt32LE(i,16),a.writeUInt16LE(0,20),Buffer.concat([...n,s,a])}function id(e){let n=e.adapterImport??"./adapter",r=e.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7240
7240
  import * as __userModule from ${JSON.stringify(r)}
7241
7241
  import { resolveApp, createHandlers } from ${JSON.stringify(n)}
7242
7242
 
@@ -7246,9 +7246,9 @@ const __handlers = createHandlers(__app)
7246
7246
  export const http = __handlers.http
7247
7247
  export const queue = __handlers.queue
7248
7248
  export const cli = __handlers.cli
7249
- `}import{execSync as os}from"node:child_process";import{createHash as cs}from"node:crypto";import{cpSync as ls,mkdtempSync as us,rmSync as ds,writeFileSync as ms}from"node:fs";import{tmpdir as ps}from"node:os";import{dirname as gs,isAbsolute as ys,join as Se,resolve as hs}from"node:path";import{fileURLToPath as fs}from"node:url";var bs=["adapter.ts","recursion.ts","auto-recursion.ts"];function Ss(){return Se(gs(fs(import.meta.url)),"runtime")}function cp(e,n,r){for(let i of e??[])r?.(`build: ${i}`),os(i,{stdio:"inherit",cwd:n})}function Ho(e){return cs("sha256").update(e).digest("hex")}function Ba(e,n,r){return`deployments/${e}/${n}/${r}.zip`}async function vn(e){let n=hs(e.projectRoot??process.cwd()),{app:r}=e;if(!e.skipBuild)cp(r.build,n,e.onStep);let i=r.entry;if(!i)throw Error("serverless app: `entry` is required to package a Node/Bun application");let s=ys(i)?i:Se(n,i),a=us(Se(ps(),"tscloud-pkg-"));try{for(let y of bs)ls(Se(Ss(),y),Se(a,y));let c=Se(a,"bootstrap.ts");ms(c,ed({entryImport:s,adapterImport:"./adapter"})),e.onStep?.("bundling application");let u=await Bun.build({entrypoints:[c],target:r.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!u.success){let y=u.logs.map((h)=>String(h)).join(`
7249
+ `}import{execSync as os}from"node:child_process";import{createHash as cs}from"node:crypto";import{cpSync as ls,mkdtempSync as us,rmSync as ds,writeFileSync as ms}from"node:fs";import{tmpdir as ps}from"node:os";import{dirname as gs,isAbsolute as ys,join as Se,resolve as hs}from"node:path";import{fileURLToPath as fs}from"node:url";var bs=["adapter.ts","recursion.ts","auto-recursion.ts"];function Ss(){return Se(gs(fs(import.meta.url)),"runtime")}function pp(e,n,r){for(let i of e??[])r?.(`build: ${i}`),os(i,{stdio:"inherit",cwd:n})}function Ko(e){return cs("sha256").update(e).digest("hex")}function Ha(e,n,r){return`deployments/${e}/${n}/${r}.zip`}async function En(e){let n=hs(e.projectRoot??process.cwd()),{app:r}=e;if(!e.skipBuild)pp(r.build,n,e.onStep);let i=r.entry;if(!i)throw Error("serverless app: `entry` is required to package a Node/Bun application");let s=ys(i)?i:Se(n,i),a=us(Se(ps(),"tscloud-pkg-"));try{for(let y of bs)ls(Se(Ss(),y),Se(a,y));let c=Se(a,"bootstrap.ts");ms(c,id({entryImport:s,adapterImport:"./adapter"})),e.onStep?.("bundling application");let u=await Bun.build({entrypoints:[c],target:r.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!u.success){let y=u.logs.map((h)=>String(h)).join(`
7250
7250
  `);throw Error(`serverless app bundle failed:
7251
- ${y}`)}let d=u.outputs[0],m=Buffer.from(await d.arrayBuffer()),p="index",g=It([{name:`${p}.mjs`,data:m}]);return{zip:g,bundle:m,sha256:Ho(g),handlerFile:p,handlers:{http:r.handlers?.http??`${p}.http`,queue:r.handlers?.queue??`${p}.queue`,cli:r.handlers?.cli??`${p}.cli`},bundleBytes:m.length}}finally{ds(a,{recursive:!0,force:!0})}}var lp=["18","20","22"];function As(e){if(!e)return"22";let n=String(e).match(/(\d+)/);return n?n[1]:"22"}function Li(e){let n=e.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:e.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:e.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let r=As(e.runtimeVersion);if(e.runtime!=="provided.al2023"&&lp.includes(r))return{lambdaRuntime:e.runtime&&e.runtime.startsWith("nodejs")?e.runtime:`nodejs${r}.x`,kind:"node",version:r,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:r,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Jt(e,n,r){if(e.queues===!1)return[];if(e.queues===void 0||e.queues===!0)return[{name:`${n}-${r}-default`}];return e.queues.map((i)=>{if(typeof i==="string")return{name:`${n}-${r}-${i}`};let[s,a]=Object.entries(i)[0];return{name:`${n}-${r}-${s}`,concurrency:a}})}function ja(e,n,r){return Jt(e,n,r).map((i)=>i.name)}function Va(e){let{app:n,environment:r,handlers:i}=e,s=e.config.project.slug,a=Li(n).lambdaRuntime,c=n.architecture??"x86_64",u=e.config.project.region,d={http:`${s}-${r}-http`,queue:`${s}-${r}-queue`,cli:`${s}-${r}-cli`};if(n.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 m=Jt(n,s,r),p=m.map((k)=>k.name),g=p.length>0,y=n.logRetention??14,h=n.packaging==="image";if(h&&n.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 f=(n.scheduler??"on")!=="off",S=(n.cache?.driver??"dynamodb")==="dynamodb",C=Boolean(n.assets),P=Ii(s,r),E=n.tmpStorage??512,v={},I={},D=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:t.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:t.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${s}-${r}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[t.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${s}/${r}/*`),t.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${s}/${r}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[t.sub(`arn:aws:s3:::${P}`),t.sub(`arn:aws:s3:::${P}/*`),...n.storage?.bucket?[t.sub(`arn:aws:s3:::${n.storage.bucket}`),t.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(g)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:t.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${s}-${r}-*`)});if(S)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s}-${r}-cache*`)});let x=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)x.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)x.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");v.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${s}-${r}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:x,Policies:D}};let F=(k)=>({TSCLOUD_LAMBDA_MODE:k,TSCLOUD_ENV:r,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...S?{TSCLOUD_CACHE_TABLE:`${s}-${r}-cache`}:{},...g?{TSCLOUD_QUEUE:p[0]}:{},...n.env??{}}),M=Boolean(n.efs),O=typeof n.efs==="object"?n.efs:{},G=O.mountPath??"/mnt/local",U=M&&!O.accessPointArn,ve=O.accessPointArn??(U?t.getAtt("EfsAccessPoint","Arn"):void 0),z=n.vpc?.subnets??[],le=z.length>0,K=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||M;if(K&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let ot=le?{VpcConfig:{SubnetIds:z,SecurityGroupIds:[...n.vpc?.securityGroups??[],...K?[t.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},ct=U?z.map((k,_)=>`EfsMountTarget${_}`):[],lt=M?{FileSystemConfigs:[{Arn:ve,LocalMountPath:G}]}:{};if(M)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function Z(k,_,V,W,J,ut,Ne,de=E){v[`${k}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${_}`,RetentionInDays:y}};let Me=[...e.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],tn=h?{PackageType:"Image",Code:{ImageUri:t.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[V]}}}:{Runtime:a,Handler:V,Code:{S3Bucket:t.ref("ArtifactBucket"),S3Key:t.ref("ArtifactKey")},...Me.length?{Layers:[...new Set(Me)]}:{}};v[k]={Type:"AWS::Lambda::Function",DependsOn:[`${k}LogGroup`,...ct],Properties:{FunctionName:_,Architectures:[c],MemorySize:J,Timeout:ut,Role:t.getAtt("AppRole","Arn"),Environment:{Variables:F(W)},EphemeralStorage:{Size:de},...tn,...Ne!==void 0?{ReservedConcurrentExecutions:Ne}:{},...ot,...lt}}}if(Z("HttpFunction",d.http,i.http,"http",n.memory??1024,n.timeout??28,n.concurrency,E),Z("CliFunction",d.cli,i.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??E),g)Z("QueueFunction",d.queue,i.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??E);let Q=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ee=["HttpFunction","CliFunction",...g?["QueueFunction"]:[]];if(Q)for(let k of ee)v[`${k}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:t.ref(k)}},v[`${k}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:t.ref(k),Name:"live",FunctionVersion:t.getAtt(`${k}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:Q}}};let ue=(k)=>Q?t.ref(`${k}Alias`):t.getAtt(k,"Arn"),te=(k)=>Q?t.ref(`${k}Alias`):t.ref(k);v.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${s}-${r}`,ProtocolType:"HTTP"}},v.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:t.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:ue("HttpFunction"),PayloadFormatVersion:"2.0"}},v.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:t.ref("HttpApi"),RouteKey:"$default",Target:t.join("/",["integrations",t.ref("HttpIntegration")])}},v.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:t.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},v.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:te("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:t.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},I.HttpApiEndpoint={Description:"HTTP API endpoint",Value:t.getAtt("HttpApi","ApiEndpoint")},I.HttpApiId={Description:"HTTP API id",Value:t.ref("HttpApi")};let se=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(se.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let k=n.certificateArn;if(!k)v.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:se[0],...se.length>1?{SubjectAlternativeNames:se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:se.map((_)=>({DomainName:_,HostedZoneId:n.hostedZoneId}))}},k=t.ref("HttpCertificate");se.forEach((_,V)=>{let W=`HttpDomain${V}`;if(v[W]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:_,DomainNameConfigurations:[{CertificateArn:k,EndpointType:"REGIONAL"}]}},v[`HttpApiMapping${V}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:t.ref("HttpApi"),DomainName:t.ref(W),Stage:"$default"}},n.hostedZoneId)v[`HttpDomainRecord${V}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:_,Type:"A",AliasTarget:{DNSName:t.getAtt(W,"RegionalDomainName"),HostedZoneId:t.getAtt(W,"RegionalHostedZoneId")}}};I[`CustomDomain${V}`]={Description:`Custom domain ${_}`,Value:_},I[`CustomDomainTarget${V}`]={Description:`Point ${_} (CNAME/alias) at this APIGW regional domain`,Value:t.getAtt(W,"RegionalDomainName")}})}if(g)v.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${s}-${r}-dlq`,MessageRetentionPeriod:1209600}},m.forEach((k,_)=>{let V=`AppQueue${_}`,W=n.queueTimeout??120;v[V]={Type:"AWS::SQS::Queue",Properties:{QueueName:k.name,VisibilityTimeout:Math.min(43200,W*6),RedrivePolicy:{deadLetterTargetArn:t.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let J=k.concurrency??n.queueConcurrency;v[`${V}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:t.getAtt(V,"Arn"),FunctionName:te("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...J?{ScalingConfig:{MaximumConcurrency:Math.max(2,J)}}:{}}},I[`QueueUrl${_}`]={Description:`Queue URL: ${k.name}`,Value:t.ref(V)}});if(f)v.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${s}-${r}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:ue("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},v.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:te("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let _={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},V=(n.warmFunctions??["http"]).filter((W)=>W!=="queue"||g);for(let W of V){let J=W.charAt(0).toUpperCase()+W.slice(1),ut=Math.ceil(n.warm/5),Ne=0;for(let de=0;de<ut;de++){let Me=Math.min(5,n.warm-Ne);v[`Warmer${J}Rule${de}`]={Type:"AWS::Events::Rule",Properties:{Name:`${s}-${r}-warmer-${W}-${de}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Me},(tn,or)=>({Id:`warm-${W}-${de}-${or}`,Arn:t.getAtt(_[W],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Ne+=Me}v[`Warmer${J}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:t.ref(_[W]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${s}-${r}-warmer-${W}-*`)}}}}if(S)v.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-${r}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},I.CacheTableName={Description:"DynamoDB cache table",Value:t.ref("CacheTable")};if(C){if(v.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:P,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},v.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${s}-${r}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},v.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:t.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:t.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??t.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.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(u!=="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 ${u}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);v.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)v.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:t.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};I.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}v.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:t.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:t.sub(`arn:aws:s3:::${P}/*`),Condition:{StringEquals:{"AWS:SourceArn":t.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},I.AssetsBucketName={Description:"Assets bucket",Value:t.ref("AssetsBucket")},I.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:t.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let k=[],_=0;if(n.firewall.rateLimit)k.push({Name:"rate-limit",Priority:_++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-rate`}});let V={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let W of n.firewall.rules??[]){let J=V[W];if(!J)continue;k.push({Name:`managed-${W}`,Priority:_++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:J}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-${W}`}})}v.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${s}-${r}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:k,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-waf`}}},I.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:t.getAtt("WebAcl","Arn")}}if(le&&K){if(!n.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.");v.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${s}-${r} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(U)v.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${s}-${r}-efs`}]}},z.forEach((k,_)=>{v[`EfsMountTarget${_}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:t.ref("EfsFileSystem"),SubnetId:k,SecurityGroups:[t.getAtt("DataSecurityGroup","GroupId")]}}}),v.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:t.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},I.EfsFileSystemId={Description:"EFS file system id",Value:t.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")v.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${s}-${r} cache subnets`,SubnetIds:z}},v.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${s}-${r}-cache`,ReplicationGroupDescription:`${s}-${r} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),SecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},I.CacheEndpoint={Description:"Redis primary endpoint",Value:t.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")v.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${s}-${r} db subnets`,SubnetIds:z}},v.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${s}/${r}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},v.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${s}-${r}-db`,DatabaseName:"app",MasterUsername:t.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:t.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:t.ref("DbSubnetGroup"),VpcSecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")]}},v.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:t.ref("DbCluster")}},I.DbEndpoint={Description:"Aurora cluster endpoint",Value:t.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")v.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:t.ref("DbSecret")}]}}]}},v.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${s}-${r}-proxy`,EngineFamily:"MYSQL",RoleArn:t.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:t.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:z,VpcSecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},v.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:t.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[t.ref("DbCluster")]}},I.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:t.getAtt("DbProxy","Endpoint")};if(I.HttpFunctionName={Description:"HTTP function name",Value:t.ref("HttpFunction")},I.CliFunctionName={Description:"CLI function name",Value:t.ref("CliFunction")},g)I.QueueFunctionName={Description:"Queue function name",Value:t.ref("QueueFunction")};let ye={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${e.config.project.name} (${s}-${r})`,Parameters:h?{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:v,Outputs:I},De={};for(let k of Object.values(v))De[k.Type]=(De[k.Type]??0)+1;return{template:ye,functionNames:d,queueNames:p,resourceSummary:De}}var dp=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function up(e){let n=`php${e.replace(".","")}`;return dp.map((r)=>`${n}-php-${r}`)}function za(e,n){let r=`php${e.replace(".","")}`,i=up(e).join(" \\\n "),s=`/opt/remi/${r}/root`,a=`/etc/opt/remi/${r}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
7251
+ ${y}`)}let d=u.outputs[0],m=Buffer.from(await d.arrayBuffer()),p="index",g=It([{name:`${p}.mjs`,data:m}]);return{zip:g,bundle:m,sha256:Ko(g),handlerFile:p,handlers:{http:r.handlers?.http??`${p}.http`,queue:r.handlers?.queue??`${p}.queue`,cli:r.handlers?.cli??`${p}.cli`},bundleBytes:m.length}}finally{ds(a,{recursive:!0,force:!0})}}var mp=["18","20","22"];function As(e){if(!e)return"22";let n=String(e).match(/(\d+)/);return n?n[1]:"22"}function Fi(e){let n=e.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:e.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:e.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let r=As(e.runtimeVersion);if(e.runtime!=="provided.al2023"&&mp.includes(r))return{lambdaRuntime:e.runtime&&e.runtime.startsWith("nodejs")?e.runtime:`nodejs${r}.x`,kind:"node",version:r,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:r,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Jt(e,n,r){if(e.queues===!1)return[];if(e.queues===void 0||e.queues===!0)return[{name:`${n}-${r}-default`}];return e.queues.map((i)=>{if(typeof i==="string")return{name:`${n}-${r}-${i}`};let[s,a]=Object.entries(i)[0];return{name:`${n}-${r}-${s}`,concurrency:a}})}function Ga(e,n,r){return Jt(e,n,r).map((i)=>i.name)}function qa(e){let{app:n,environment:r,handlers:i}=e,s=e.config.project.slug,a=Fi(n).lambdaRuntime,c=n.architecture??"x86_64",u=e.config.project.region,d={http:`${s}-${r}-http`,queue:`${s}-${r}-queue`,cli:`${s}-${r}-cli`};if(n.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 m=Jt(n,s,r),p=m.map((x)=>x.name),g=p.length>0,y=n.logRetention??14,h=n.packaging==="image";if(h&&n.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 f=(n.scheduler??"on")!=="off",S=(n.cache?.driver??"dynamodb")==="dynamodb",C=Boolean(n.assets),P=Ni(s,r),E=n.tmpStorage??512,v={},I={},D=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:t.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:t.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${s}-${r}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[t.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${s}/${r}/*`),t.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${s}/${r}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[t.sub(`arn:aws:s3:::${P}`),t.sub(`arn:aws:s3:::${P}/*`),...n.storage?.bucket?[t.sub(`arn:aws:s3:::${n.storage.bucket}`),t.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(g)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:t.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${s}-${r}-*`)});if(S)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:t.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s}-${r}-cache*`)});let N=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)N.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)N.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");v.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${s}-${r}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:N,Policies:D}};let B=(x)=>({TSCLOUD_LAMBDA_MODE:x,TSCLOUD_ENV:r,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...S?{TSCLOUD_CACHE_TABLE:`${s}-${r}-cache`}:{},...g?{TSCLOUD_QUEUE:p[0]}:{},...n.env??{}}),M=Boolean(n.efs),O=typeof n.efs==="object"?n.efs:{},G=O.mountPath??"/mnt/local",U=M&&!O.accessPointArn,ve=O.accessPointArn??(U?t.getAtt("EfsAccessPoint","Arn"):void 0),z=n.vpc?.subnets??[],le=z.length>0,K=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||M;if(K&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let ot=le?{VpcConfig:{SubnetIds:z,SecurityGroupIds:[...n.vpc?.securityGroups??[],...K?[t.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},ct=U?z.map((x,_)=>`EfsMountTarget${_}`):[],lt=M?{FileSystemConfigs:[{Arn:ve,LocalMountPath:G}]}:{};if(M)D[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function Z(x,_,V,W,J,ut,Ne,de=E){v[`${x}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${_}`,RetentionInDays:y}};let ke=[...e.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],tn=h?{PackageType:"Image",Code:{ImageUri:t.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[V]}}}:{Runtime:a,Handler:V,Code:{S3Bucket:t.ref("ArtifactBucket"),S3Key:t.ref("ArtifactKey")},...ke.length?{Layers:[...new Set(ke)]}:{}};v[x]={Type:"AWS::Lambda::Function",DependsOn:[`${x}LogGroup`,...ct],Properties:{FunctionName:_,Architectures:[c],MemorySize:J,Timeout:ut,Role:t.getAtt("AppRole","Arn"),Environment:{Variables:B(W)},EphemeralStorage:{Size:de},...tn,...Ne!==void 0?{ReservedConcurrentExecutions:Ne}:{},...ot,...lt}}}if(Z("HttpFunction",d.http,i.http,"http",n.memory??1024,n.timeout??28,n.concurrency,E),Z("CliFunction",d.cli,i.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??E),g)Z("QueueFunction",d.queue,i.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??E);let Q=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ee=["HttpFunction","CliFunction",...g?["QueueFunction"]:[]];if(Q)for(let x of ee)v[`${x}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:t.ref(x)}},v[`${x}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:t.ref(x),Name:"live",FunctionVersion:t.getAtt(`${x}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:Q}}};let ue=(x)=>Q?t.ref(`${x}Alias`):t.getAtt(x,"Arn"),te=(x)=>Q?t.ref(`${x}Alias`):t.ref(x);v.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${s}-${r}`,ProtocolType:"HTTP"}},v.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:t.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:ue("HttpFunction"),PayloadFormatVersion:"2.0"}},v.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:t.ref("HttpApi"),RouteKey:"$default",Target:t.join("/",["integrations",t.ref("HttpIntegration")])}},v.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:t.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},v.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:te("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:t.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},I.HttpApiEndpoint={Description:"HTTP API endpoint",Value:t.getAtt("HttpApi","ApiEndpoint")},I.HttpApiId={Description:"HTTP API id",Value:t.ref("HttpApi")};let se=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(se.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let x=n.certificateArn;if(!x)v.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:se[0],...se.length>1?{SubjectAlternativeNames:se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:se.map((_)=>({DomainName:_,HostedZoneId:n.hostedZoneId}))}},x=t.ref("HttpCertificate");se.forEach((_,V)=>{let W=`HttpDomain${V}`;if(v[W]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:_,DomainNameConfigurations:[{CertificateArn:x,EndpointType:"REGIONAL"}]}},v[`HttpApiMapping${V}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:t.ref("HttpApi"),DomainName:t.ref(W),Stage:"$default"}},n.hostedZoneId)v[`HttpDomainRecord${V}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:_,Type:"A",AliasTarget:{DNSName:t.getAtt(W,"RegionalDomainName"),HostedZoneId:t.getAtt(W,"RegionalHostedZoneId")}}};I[`CustomDomain${V}`]={Description:`Custom domain ${_}`,Value:_},I[`CustomDomainTarget${V}`]={Description:`Point ${_} (CNAME/alias) at this APIGW regional domain`,Value:t.getAtt(W,"RegionalDomainName")}})}if(g)v.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${s}-${r}-dlq`,MessageRetentionPeriod:1209600}},m.forEach((x,_)=>{let V=`AppQueue${_}`,W=n.queueTimeout??120;v[V]={Type:"AWS::SQS::Queue",Properties:{QueueName:x.name,VisibilityTimeout:Math.min(43200,W*6),RedrivePolicy:{deadLetterTargetArn:t.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let J=x.concurrency??n.queueConcurrency;v[`${V}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:t.getAtt(V,"Arn"),FunctionName:te("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...J?{ScalingConfig:{MaximumConcurrency:Math.max(2,J)}}:{}}},I[`QueueUrl${_}`]={Description:`Queue URL: ${x.name}`,Value:t.ref(V)}});if(f)v.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${s}-${r}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:ue("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},v.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:te("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let _={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},V=(n.warmFunctions??["http"]).filter((W)=>W!=="queue"||g);for(let W of V){let J=W.charAt(0).toUpperCase()+W.slice(1),ut=Math.ceil(n.warm/5),Ne=0;for(let de=0;de<ut;de++){let ke=Math.min(5,n.warm-Ne);v[`Warmer${J}Rule${de}`]={Type:"AWS::Events::Rule",Properties:{Name:`${s}-${r}-warmer-${W}-${de}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:ke},(tn,or)=>({Id:`warm-${W}-${de}-${or}`,Arn:t.getAtt(_[W],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Ne+=ke}v[`Warmer${J}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:t.ref(_[W]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:t.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${s}-${r}-warmer-${W}-*`)}}}}if(S)v.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-${r}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},I.CacheTableName={Description:"DynamoDB cache table",Value:t.ref("CacheTable")};if(C){if(v.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:P,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},v.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${s}-${r}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},v.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:t.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:t.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??t.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.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(u!=="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 ${u}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);v.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)v.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:t.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};I.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}v.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:t.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:t.sub(`arn:aws:s3:::${P}/*`),Condition:{StringEquals:{"AWS:SourceArn":t.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},I.AssetsBucketName={Description:"Assets bucket",Value:t.ref("AssetsBucket")},I.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:t.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let x=[],_=0;if(n.firewall.rateLimit)x.push({Name:"rate-limit",Priority:_++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-rate`}});let V={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let W of n.firewall.rules??[]){let J=V[W];if(!J)continue;x.push({Name:`managed-${W}`,Priority:_++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:J}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-${W}`}})}v.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${s}-${r}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:x,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${s}-${r}-waf`}}},I.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:t.getAtt("WebAcl","Arn")}}if(le&&K){if(!n.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.");v.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${s}-${r} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(U)v.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${s}-${r}-efs`}]}},z.forEach((x,_)=>{v[`EfsMountTarget${_}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:t.ref("EfsFileSystem"),SubnetId:x,SecurityGroups:[t.getAtt("DataSecurityGroup","GroupId")]}}}),v.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:t.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},I.EfsFileSystemId={Description:"EFS file system id",Value:t.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")v.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${s}-${r} cache subnets`,SubnetIds:z}},v.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${s}-${r}-cache`,ReplicationGroupDescription:`${s}-${r} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:t.ref("CacheSubnetGroup"),SecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},I.CacheEndpoint={Description:"Redis primary endpoint",Value:t.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")v.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${s}-${r} db subnets`,SubnetIds:z}},v.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${s}/${r}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},v.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${s}-${r}-db`,DatabaseName:"app",MasterUsername:t.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:t.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:t.ref("DbSubnetGroup"),VpcSecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")]}},v.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:t.ref("DbCluster")}},I.DbEndpoint={Description:"Aurora cluster endpoint",Value:t.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")v.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:t.ref("DbSecret")}]}}]}},v.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${s}-${r}-proxy`,EngineFamily:"MYSQL",RoleArn:t.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:t.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:z,VpcSecurityGroupIds:[t.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},v.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:t.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[t.ref("DbCluster")]}},I.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:t.getAtt("DbProxy","Endpoint")};if(I.HttpFunctionName={Description:"HTTP function name",Value:t.ref("HttpFunction")},I.CliFunctionName={Description:"CLI function name",Value:t.ref("CliFunction")},g)I.QueueFunctionName={Description:"Queue function name",Value:t.ref("QueueFunction")};let ye={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${e.config.project.name} (${s}-${r})`,Parameters:h?{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:v,Outputs:I},De={};for(let x of Object.values(v))De[x.Type]=(De[x.Type]??0)+1;return{template:ye,functionNames:d,queueNames:p,resourceSummary:De}}var gp=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function fp(e){let n=`php${e.replace(".","")}`;return gp.map((r)=>`${n}-php-${r}`)}function Wa(e,n){let r=`php${e.replace(".","")}`,i=fp(e).join(" \\\n "),s=`/opt/remi/${r}/root`,a=`/etc/opt/remi/${r}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
7252
7252
 
7253
7253
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7254
7254
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7288,9 +7288,9 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7288
7288
  # Runtime assets (bootstrap, runtime loops, fpm config) are added by the build
7289
7289
  # orchestrator after the image is produced. Export /opt as the layer payload.
7290
7290
  CMD ["true"]
7291
- `}function td(e={}){let n=e.phpVersion??"8.3";return`# ts-cloud PHP ${n} runtime layer (generated) — AWS Lambda provided.al2023.
7292
- ${za(n)}`}function Ha(e){if(e.kind==="php"){let r=e.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7293
- ${za(r,"phpbuild")}
7291
+ `}function od(e={}){let n=e.phpVersion??"8.3";return`# ts-cloud PHP ${n} runtime layer (generated) — AWS Lambda provided.al2023.
7292
+ ${Wa(n)}`}function Ka(e){if(e.kind==="php"){let r=e.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7293
+ ${Wa(r,"phpbuild")}
7294
7294
 
7295
7295
  FROM public.ecr.aws/lambda/provided:al2023
7296
7296
  # Bake the relocated PHP runtime from the build stage.
@@ -7309,7 +7309,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7309
7309
 
7310
7310
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7311
7311
  CMD [ "index.http" ]
7312
- `}import{execFileSync as et}from"node:child_process";import{mkdtempSync as qn,readFileSync as it,rmSync as zn}from"node:fs";import{tmpdir as Qn}from"node:os";import{dirname as Cs,join as ce}from"node:path";import{fileURLToPath as vs}from"node:url";function Jn(){return Cs(vs(import.meta.url))}function rd(){return it(ce(Jn(),"runtime.mjs"),"utf-8")}function Yn(e){return it(ce(Jn(),`${e}-bootstrap`),"utf-8")}function Zf(e){let n=e.architecture??"x86_64",r=n==="arm64"?"arm64":"x64",i=e.version.replace(/^v/,""),s=e.onStep??(()=>{}),a=qn(ce(Qn(),"tscloud-node-layer-"));try{let c=i.includes(".")?i:Ts(i),u=`node-v${c}-linux-${r}`,d=`https://nodejs.org/dist/v${c}/${u}.tar.xz`;s(`downloading Node ${c} (${n})`);let m=ce(a,"node.tar.xz");Zn(d,m),s("extracting node binary"),et("tar",["-xf",m,"-C",a,`${u}/bin/node`],{stdio:"inherit"});let p=it(ce(a,u,"bin","node"));s("packaging layer");let g=[{name:"bootstrap",data:Yn("node"),mode:493},{name:"runtime.mjs",data:rd(),mode:420},{name:"bin/node",data:p,mode:493}];return{zip:It(g),architecture:n,version:c,fileCount:g.length}}finally{zn(a,{recursive:!0,force:!0})}}function eh(e){let n=e.architecture??"x86_64",r=n==="arm64"?"bun-linux-aarch64":"bun-linux-x64",i=e.version==="latest"?"":e.version.replace(/^v/,""),s=e.onStep??(()=>{}),a=qn(ce(Qn(),"tscloud-bun-layer-"));try{let c=i?`https://github.com/oven-sh/bun/releases/download/bun-v${i}/${r}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${r}.zip`;s(`downloading Bun ${i||"latest"} (${n})`);let u=ce(a,"bun.zip");Zn(c,u),s("extracting bun binary"),et("unzip",["-o","-q",u,"-d",a],{stdio:"inherit"});let d=it(ce(a,r,"bun"));s("packaging layer");let m=[{name:"bootstrap",data:Yn("bun"),mode:493},{name:"runtime.mjs",data:rd(),mode:420},{name:"bin/bun",data:d,mode:493}];return{zip:It(m),architecture:n,version:i||"latest",fileCount:m.length}}finally{zn(a,{recursive:!0,force:!0})}}function Zn(e,n){et("curl",["-fsSL","-o",n,e],{stdio:["ignore","ignore","inherit"]})}function Ts(e){let n=et("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),i=JSON.parse(n).find((s)=>s.version.startsWith(`v${e}.`));if(!i)throw Error(`No Node release found for major version ${e}`);return i.version.replace(/^v/,"")}import{AsyncLocalStorage as Ps}from"node:async_hooks";import{createHash as Rs}from"node:crypto";var Ga="x-ts-cloud-invoke-depth",qa="x-ts-cloud-invoke-chain",Wa="x-ts-cloud-trace-id";function nd(e){return Rs("sha256").update(e).digest("hex").slice(0,8)}var Mi={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Yt(e,n){if(typeof e.get==="function")return e.get(n)??void 0;let r=e;return r[n]??r[n.toLowerCase()]??r[n.toUpperCase()]}function id(e,n=64){if(!e)return[];return e.split(".").map((r)=>r.trim()).filter((r)=>/^[0-9a-f]{8}$/.test(r)).slice(-n)}function od(e,n=Mi){let r=nd(e.functionId),i=id(Yt(e.headers,qa)),s=e.traceId??Yt(e.headers,Wa)??crypto.randomUUID(),a=[...i,r],c=i.filter((g)=>g===r).length,u=i[i.length-1]===r,d=Number.parseInt(Yt(e.headers,Ga)??"",10),m=Math.max(a.length,Number.isFinite(d)?d+1:0),p="ok";if(m>n.maxDepth)p="depth_exceeded";else if(c>=n.maxRepeats)p="cycle_detected";else if(u&&n.maxRepeats<=1)p="self_invocation";return{reason:p,depth:m,chain:a,traceId:s,selfInvocation:u,repeats:c,propagate:{[Ga]:String(m),[qa]:a.join("."),[Wa]:s}}}var Xn={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 Go{limits;clock;traces=new Map;breakers=new Map;constructor(e=Mi,n=()=>Date.now()){this.limits=e;this.clock=n}check(e){let n=this.clock();this.expireTraces(n);let r=od(e,this.limits),i=this.breakers.get(e.functionId);if(i?.openUntil!=null&&i.openUntil>n)return this.deny(e.functionId,r,"breaker_open",n,!1);if(r.reason!=="ok")return this.deny(e.functionId,r,r.reason,n,!0);let s=this.traces.get(r.traceId)??{count:0,firstAt:n};if(s.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(r.traceId,s),this.deny(e.functionId,r,"trace_budget_exceeded",n,!0);if(this.traces.set(r.traceId,{count:s.count+1,firstAt:s.firstAt}),i)this.breakers.set(e.functionId,{consecutiveBlocks:0});return{...r,allowed:!0,reason:"ok",propagate:r.propagate}}deny(e,n,r,i,s){if(s){let a=this.breakers.get(e)??{consecutiveBlocks:0},c=a.consecutiveBlocks+1;this.breakers.set(e,{consecutiveBlocks:c,openUntil:c>=this.limits.breakerThreshold?i+this.limits.breakerCooldownMs:a.openUntil})}return{...n,allowed:!1,reason:r,message:Xn[r]}}breakerOpen(e){let n=this.breakers.get(e);return n?.openUntil!=null&&n.openUntil>this.clock()}reset(e){if(e){this.breakers.delete(e);return}this.breakers.clear(),this.traces.clear()}expireTraces(e){if(this.traces.size===0)return;for(let[n,r]of this.traces)if(e-r.firstAt>this.limits.traceWindowMs)this.traces.delete(n)}get trackedTraces(){return this.traces.size}}function Ka(e){return{...e.propagate}}function Ja(e){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":e.reason},body:{error:"recursion_blocked",reason:e.reason,message:e.message??Xn[e.reason],depth:e.depth,traceId:e.traceId}}}var sd=new Ps;function er(e){let n=globalThis.process?.env?.[e];if(n==null||n==="")return;return n!=="0"&&n.toLowerCase()!=="false"}function Es(){let e=globalThis.process?.env??{};return e.TS_CLOUD_FUNCTION_ID||e.AWS_LAMBDA_FUNCTION_NAME||e.FUNCTION_NAME||"function"}function pp(e){let n=e===!1?{enabled:!1}:e??{},r=er("TS_CLOUD_RECURSION_PROTECTION"),i=er("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:r??n.enabled??!0,detectionOnly:i??n.detectionOnly??!1,limits:{...Mi,...n.limits},functionId:n.functionId??Es()}}var pe,ie;function mp(){let e=globalThis.fetch;if(!e||pe===e)return()=>{};ie=e;let n=async(r,i)=>{let s=sd.getStore();if(!s)return ie(r,i);let a=new Headers(i?.headers??(r instanceof Request?r.headers:void 0));for(let[c,u]of Object.entries(Ka(s)))a.set(c,u);if(r instanceof Request)return ie(new Request(r,{headers:a}),i);return ie(r,{...i,headers:a})};return Object.assign(n,e),globalThis.fetch=n,pe=n,()=>{if(globalThis.fetch===pe&&ie)globalThis.fetch=ie;pe=void 0}}var st,Zt;function gp(e){if(!st||JSON.stringify(Zt)!==JSON.stringify(e))st=new Go(e),Zt=e;return st}function th(){if(st=void 0,Zt=void 0,pe&&ie&&globalThis.fetch===pe)globalThis.fetch=ie;pe=void 0,ie=void 0}function ad(e,n){let r=pp(n);if(!r.enabled)return;let i=gp(r.limits),s={functionId:r.functionId,headers:e},a=i.check(s);return{verdict:a,blocked:!a.allowed&&!r.detectionOnly,observed:!a.allowed&&r.detectionOnly}}function cd(e,n){return mp(),sd.run(e,n)}function rh(e){let n=e,r=n?.default??n;if(typeof r==="function")return{fetch:r};return{fetch:r?.fetch??n?.fetch,queue:r?.queue??n?.queue,cli:r?.cli??n?.cli}}var Is=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function ws(e){if(!e)return!0;return Is.test(e)}function Ds(e){if(e?.maintenance)return e.maintenance;let n=globalThis.process?.env??{};return{enabled:n.MAINTENANCE_MODE==="1"||n.MAINTENANCE_MODE==="true",bypassSecret:n.MAINTENANCE_BYPASS_SECRET}}function fp(e){let n=e.requestContext?.domainName??"localhost",r=e.rawQueryString?`?${e.rawQueryString}`:"",i=`https://${n}${e.rawPath||"/"}${r}`,s=new Headers;for(let[u,d]of Object.entries(e.headers??{}))if(d!==void 0)s.set(u,d);if(e.cookies?.length)s.set("cookie",e.cookies.join("; "));let a=e.requestContext.http.method,c;if(e.body!==void 0&&a!=="GET"&&a!=="HEAD")c=e.isBase64Encoded?new Uint8Array(Buffer.from(e.body,"base64")):new TextEncoder().encode(e.body);return new Request(i,{method:a,headers:s,body:c})}async function ld(e){let n={},r=[],i=typeof e.headers.getSetCookie==="function"?e.headers.getSetCookie():[];for(let c of i)r.push(c);e.headers.forEach((c,u)=>{if(u.toLowerCase()==="set-cookie")return;n[u]=c});let s=Buffer.from(await e.arrayBuffer()),a=ws(e.headers.get("content-type"));return{statusCode:e.status,headers:n,...r.length?{cookies:r}:{},body:a?s.toString("utf-8"):s.toString("base64"),isBase64Encoded:!a}}function hp(e,n){return async(r)=>{if(r.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!e)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let i=Ds(n);if(i.enabled){let c=r.headers?.["x-maintenance-bypass"]??r.cookies?.find((u)=>u.startsWith("tscloud_bypass="))?.split("=")[1];if(!i.bypassSecret||c!==i.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let s=ad(r.headers??{},n?.recursionProtection);if(s?.blocked){let c=Ja(s.verdict);return{statusCode:c.status,headers:{...c.headers,"retry-after":"60"},body:JSON.stringify(c.body),isBase64Encoded:!1}}let a=fp(r);if(!s){let c=await e(a);return ld(c)}if(s.observed)console.warn(`[ts-cloud] recursion detected (${s.verdict.reason}) at depth ${s.verdict.depth}; detection-only mode let it run`);return cd(s.verdict,async()=>ld(await e(a)))}}function Ns(e){try{return JSON.parse(e)}catch{return e}}function yp(e){return async(n)=>{let r=[];if(n.warmer)return{batchItemFailures:r};if(!e)return{batchItemFailures:r};for(let i of n.Records??[])try{await e(Ns(i.body),i)}catch{r.push({itemIdentifier:i.messageId})}return{batchItemFailures:r}}}function bp(e){return async(n)=>{if(n.warmer)return{statusCode:0,output:"warm"};if(!e)return{statusCode:501,output:"No CLI handler configured"};return e(n)}}function nh(e,n){return{http:hp(e.fetch,n),queue:yp(e.queue),cli:bp(e.cli)}}function dd(e={}){let n=e.socketPath??"/tmp/.tscloud-fpm.sock",r=e.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7312
+ `}import{execFileSync as et}from"node:child_process";import{mkdtempSync as qn,readFileSync as it,rmSync as zn}from"node:fs";import{tmpdir as Qn}from"node:os";import{dirname as Cs,join as ce}from"node:path";import{fileURLToPath as vs}from"node:url";function Jn(){return Cs(vs(import.meta.url))}function sd(){return it(ce(Jn(),"runtime.mjs"),"utf-8")}function Yn(e){return it(ce(Jn(),`${e}-bootstrap`),"utf-8")}function nh(e){let n=e.architecture??"x86_64",r=n==="arm64"?"arm64":"x64",i=e.version.replace(/^v/,""),s=e.onStep??(()=>{}),a=qn(ce(Qn(),"tscloud-node-layer-"));try{let c=i.includes(".")?i:Ts(i),u=`node-v${c}-linux-${r}`,d=`https://nodejs.org/dist/v${c}/${u}.tar.xz`;s(`downloading Node ${c} (${n})`);let m=ce(a,"node.tar.xz");Zn(d,m),s("extracting node binary"),et("tar",["-xf",m,"-C",a,`${u}/bin/node`],{stdio:"inherit"});let p=it(ce(a,u,"bin","node"));s("packaging layer");let g=[{name:"bootstrap",data:Yn("node"),mode:493},{name:"runtime.mjs",data:sd(),mode:420},{name:"bin/node",data:p,mode:493}];return{zip:It(g),architecture:n,version:c,fileCount:g.length}}finally{zn(a,{recursive:!0,force:!0})}}function ih(e){let n=e.architecture??"x86_64",r=n==="arm64"?"bun-linux-aarch64":"bun-linux-x64",i=e.version==="latest"?"":e.version.replace(/^v/,""),s=e.onStep??(()=>{}),a=qn(ce(Qn(),"tscloud-bun-layer-"));try{let c=i?`https://github.com/oven-sh/bun/releases/download/bun-v${i}/${r}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${r}.zip`;s(`downloading Bun ${i||"latest"} (${n})`);let u=ce(a,"bun.zip");Zn(c,u),s("extracting bun binary"),et("unzip",["-o","-q",u,"-d",a],{stdio:"inherit"});let d=it(ce(a,r,"bun"));s("packaging layer");let m=[{name:"bootstrap",data:Yn("bun"),mode:493},{name:"runtime.mjs",data:sd(),mode:420},{name:"bin/bun",data:d,mode:493}];return{zip:It(m),architecture:n,version:i||"latest",fileCount:m.length}}finally{zn(a,{recursive:!0,force:!0})}}function Zn(e,n){et("curl",["-fsSL","-o",n,e],{stdio:["ignore","ignore","inherit"]})}function Ts(e){let n=et("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),i=JSON.parse(n).find((s)=>s.version.startsWith(`v${e}.`));if(!i)throw Error(`No Node release found for major version ${e}`);return i.version.replace(/^v/,"")}import{AsyncLocalStorage as Ps}from"node:async_hooks";import{createHash as Rs}from"node:crypto";var Ja="x-ts-cloud-invoke-depth",Xa="x-ts-cloud-invoke-chain",Qa="x-ts-cloud-trace-id";function ad(e){return Rs("sha256").update(e).digest("hex").slice(0,8)}var ji={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Yt(e,n){if(typeof e.get==="function")return e.get(n)??void 0;let r=e;return r[n]??r[n.toLowerCase()]??r[n.toUpperCase()]}function cd(e,n=64){if(!e)return[];return e.split(".").map((r)=>r.trim()).filter((r)=>/^[0-9a-f]{8}$/.test(r)).slice(-n)}function ld(e,n=ji){let r=ad(e.functionId),i=cd(Yt(e.headers,Xa)),s=e.traceId??Yt(e.headers,Qa)??crypto.randomUUID(),a=[...i,r],c=i.filter((g)=>g===r).length,u=i[i.length-1]===r,d=Number.parseInt(Yt(e.headers,Ja)??"",10),m=Math.max(a.length,Number.isFinite(d)?d+1:0),p="ok";if(m>n.maxDepth)p="depth_exceeded";else if(c>=n.maxRepeats)p="cycle_detected";else if(u&&n.maxRepeats<=1)p="self_invocation";return{reason:p,depth:m,chain:a,traceId:s,selfInvocation:u,repeats:c,propagate:{[Ja]:String(m),[Xa]:a.join("."),[Qa]:s}}}var Xn={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 Jo{limits;clock;traces=new Map;breakers=new Map;constructor(e=ji,n=()=>Date.now()){this.limits=e;this.clock=n}check(e){let n=this.clock();this.expireTraces(n);let r=ld(e,this.limits),i=this.breakers.get(e.functionId);if(i?.openUntil!=null&&i.openUntil>n)return this.deny(e.functionId,r,"breaker_open",n,!1);if(r.reason!=="ok")return this.deny(e.functionId,r,r.reason,n,!0);let s=this.traces.get(r.traceId)??{count:0,firstAt:n};if(s.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(r.traceId,s),this.deny(e.functionId,r,"trace_budget_exceeded",n,!0);if(this.traces.set(r.traceId,{count:s.count+1,firstAt:s.firstAt}),i)this.breakers.set(e.functionId,{consecutiveBlocks:0});return{...r,allowed:!0,reason:"ok",propagate:r.propagate}}deny(e,n,r,i,s){if(s){let a=this.breakers.get(e)??{consecutiveBlocks:0},c=a.consecutiveBlocks+1;this.breakers.set(e,{consecutiveBlocks:c,openUntil:c>=this.limits.breakerThreshold?i+this.limits.breakerCooldownMs:a.openUntil})}return{...n,allowed:!1,reason:r,message:Xn[r]}}breakerOpen(e){let n=this.breakers.get(e);return n?.openUntil!=null&&n.openUntil>this.clock()}reset(e){if(e){this.breakers.delete(e);return}this.breakers.clear(),this.traces.clear()}expireTraces(e){if(this.traces.size===0)return;for(let[n,r]of this.traces)if(e-r.firstAt>this.limits.traceWindowMs)this.traces.delete(n)}get trackedTraces(){return this.traces.size}}function Ya(e){return{...e.propagate}}function Za(e){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":e.reason},body:{error:"recursion_blocked",reason:e.reason,message:e.message??Xn[e.reason],depth:e.depth,traceId:e.traceId}}}var dd=new Ps;function er(e){let n=globalThis.process?.env?.[e];if(n==null||n==="")return;return n!=="0"&&n.toLowerCase()!=="false"}function Es(){let e=globalThis.process?.env??{};return e.TS_CLOUD_FUNCTION_ID||e.AWS_LAMBDA_FUNCTION_NAME||e.FUNCTION_NAME||"function"}function hp(e){let n=e===!1?{enabled:!1}:e??{},r=er("TS_CLOUD_RECURSION_PROTECTION"),i=er("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:r??n.enabled??!0,detectionOnly:i??n.detectionOnly??!1,limits:{...ji,...n.limits},functionId:n.functionId??Es()}}var pe,ie;function yp(){let e=globalThis.fetch;if(!e||pe===e)return()=>{};ie=e;let n=async(r,i)=>{let s=dd.getStore();if(!s)return ie(r,i);let a=new Headers(i?.headers??(r instanceof Request?r.headers:void 0));for(let[c,u]of Object.entries(Ya(s)))a.set(c,u);if(r instanceof Request)return ie(new Request(r,{headers:a}),i);return ie(r,{...i,headers:a})};return Object.assign(n,e),globalThis.fetch=n,pe=n,()=>{if(globalThis.fetch===pe&&ie)globalThis.fetch=ie;pe=void 0}}var st,Zt;function bp(e){if(!st||JSON.stringify(Zt)!==JSON.stringify(e))st=new Jo(e),Zt=e;return st}function oh(){if(st=void 0,Zt=void 0,pe&&ie&&globalThis.fetch===pe)globalThis.fetch=ie;pe=void 0,ie=void 0}function ud(e,n){let r=hp(n);if(!r.enabled)return;let i=bp(r.limits),s={functionId:r.functionId,headers:e},a=i.check(s);return{verdict:a,blocked:!a.allowed&&!r.detectionOnly,observed:!a.allowed&&r.detectionOnly}}function pd(e,n){return yp(),dd.run(e,n)}function sh(e){let n=e,r=n?.default??n;if(typeof r==="function")return{fetch:r};return{fetch:r?.fetch??n?.fetch,queue:r?.queue??n?.queue,cli:r?.cli??n?.cli}}var Is=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function ws(e){if(!e)return!0;return Is.test(e)}function Ds(e){if(e?.maintenance)return e.maintenance;let n=globalThis.process?.env??{};return{enabled:n.MAINTENANCE_MODE==="1"||n.MAINTENANCE_MODE==="true",bypassSecret:n.MAINTENANCE_BYPASS_SECRET}}function Sp(e){let n=e.requestContext?.domainName??"localhost",r=e.rawQueryString?`?${e.rawQueryString}`:"",i=`https://${n}${e.rawPath||"/"}${r}`,s=new Headers;for(let[u,d]of Object.entries(e.headers??{}))if(d!==void 0)s.set(u,d);if(e.cookies?.length)s.set("cookie",e.cookies.join("; "));let a=e.requestContext.http.method,c;if(e.body!==void 0&&a!=="GET"&&a!=="HEAD")c=e.isBase64Encoded?new Uint8Array(Buffer.from(e.body,"base64")):new TextEncoder().encode(e.body);return new Request(i,{method:a,headers:s,body:c})}async function md(e){let n={},r=[],i=typeof e.headers.getSetCookie==="function"?e.headers.getSetCookie():[];for(let c of i)r.push(c);e.headers.forEach((c,u)=>{if(u.toLowerCase()==="set-cookie")return;n[u]=c});let s=Buffer.from(await e.arrayBuffer()),a=ws(e.headers.get("content-type"));return{statusCode:e.status,headers:n,...r.length?{cookies:r}:{},body:a?s.toString("utf-8"):s.toString("base64"),isBase64Encoded:!a}}function vp(e,n){return async(r)=>{if(r.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!e)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let i=Ds(n);if(i.enabled){let c=r.headers?.["x-maintenance-bypass"]??r.cookies?.find((u)=>u.startsWith("tscloud_bypass="))?.split("=")[1];if(!i.bypassSecret||c!==i.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let s=ud(r.headers??{},n?.recursionProtection);if(s?.blocked){let c=Za(s.verdict);return{statusCode:c.status,headers:{...c.headers,"retry-after":"60"},body:JSON.stringify(c.body),isBase64Encoded:!1}}let a=Sp(r);if(!s){let c=await e(a);return md(c)}if(s.observed)console.warn(`[ts-cloud] recursion detected (${s.verdict.reason}) at depth ${s.verdict.depth}; detection-only mode let it run`);return pd(s.verdict,async()=>md(await e(a)))}}function Ns(e){try{return JSON.parse(e)}catch{return e}}function Cp(e){return async(n)=>{let r=[];if(n.warmer)return{batchItemFailures:r};if(!e)return{batchItemFailures:r};for(let i of n.Records??[])try{await e(Ns(i.body),i)}catch{r.push({itemIdentifier:i.messageId})}return{batchItemFailures:r}}}function Tp(e){return async(n)=>{if(n.warmer)return{statusCode:0,output:"warm"};if(!e)return{statusCode:501,output:"No CLI handler configured"};return e(n)}}function ah(e,n){return{http:vp(e.fetch,n),queue:Cp(e.queue),cli:Tp(e.cli)}}function gd(e={}){let n=e.socketPath??"/tmp/.tscloud-fpm.sock",r=e.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7313
7313
  [global]
7314
7314
  daemonize = no
7315
7315
  error_log = ${e.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7326,4 +7326,4 @@ decorate_workers_output = no
7326
7326
  php_admin_value[error_log] = /dev/stderr
7327
7327
  php_admin_flag[log_errors] = on
7328
7328
  clear_env = no
7329
- `}import{readFileSync as xs}from"node:fs";import{dirname as ks,join as tr}from"node:path";import{fileURLToPath as Ms}from"node:url";function Ls(){return tr(ks(Ms(import.meta.url)),"runtime-assets")}function Cn(){let e=Ls(),n=(r)=>xs(tr(e,r),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:dd(),mode:420}]}function Xa(e={}){let n=e.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,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 ud=["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 at}from"node:child_process";import{existsSync as Os,mkdirSync as $s,mkdtempSync as Bs,readdirSync as Fs,readFileSync as Gs,rmSync as _s,statSync as nr,writeFileSync as Ws}from"node:fs";import{tmpdir as Vs}from"node:os";import{join as Ce,relative as Us}from"node:path";function*rr(e){for(let n of Fs(e)){let r=Ce(e,n);if(nr(r).isDirectory())yield*rr(r);else yield r}}function ih(e={}){let n=e.architecture??"x86_64",r=e.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),i=e.onStep??(()=>{}),s=Bs(Ce(Vs(),"tscloud-php-layer-")),a="tscloud-php-layer:build";try{Ws(Ce(s,"Dockerfile"),td(e)),i("Building PHP runtime image (docker)"),at("docker",["build","--platform",r,"-t","tscloud-php-layer:build",s],{stdio:"inherit"}),i("Extracting /opt/php from image");let c=at("docker",["create","--platform",r,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),u=Ce(s,"opt");$s(u,{recursive:!0});try{at("docker",["cp",`${c}:/opt/php`,Ce(u,"php")],{stdio:"inherit"})}finally{at("docker",["rm",c],{stdio:"ignore"})}if(!Os(Ce(u,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let d=[];for(let y of rr(u)){let h=Us(u,y).replace(/\\/g,"/"),f=nr(y).mode&73?493:420;d.push({name:h,data:Gs(y),mode:f})}i("Injecting runtime assets");let m=new Set(Cn().map((y)=>y.path)),p=d.filter((y)=>!m.has(y.name));for(let y of Cn())p.push({name:y.path,data:y.contents,mode:y.mode});return i("Packaging layer ZIP"),{zip:It(p),architecture:n,fileCount:p.length}}finally{_s(s,{recursive:!0,force:!0})}}import{execSync as Hs}from"node:child_process";import{createHash as js}from"node:crypto";import{readdirSync as Ks,readFileSync as qs,statSync as ir}from"node:fs";import{join as zs,relative as sr,resolve as en}from"node:path";var Sp=[".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 Qs(e,n){return n.some((r)=>e===r||e.startsWith(`${r}/`))}function*ar(e,n,r){for(let i of Ks(e)){let s=zs(e,i),a=sr(n,s).replace(/\\/g,"/");if(Qs(a,r))continue;if(ir(s).isDirectory())yield*ar(s,n,r);else yield s}}function qo(e){if(e.skipBuild)return;let n=en(e.projectRoot??process.cwd()),r=e.app.build??ud;for(let i of r)e.onStep?.(`build: ${i}`),Hs(i,{stdio:"inherit",cwd:n})}function Wo(e,n=[]){let r=en(e),i=[...Sp,gn(),...n],s=[];for(let a of ar(r,r,i)){let c=sr(r,a).replace(/\\/g,"/"),u=(ir(a).mode&73)!==0;s.push({name:c,data:qs(a),mode:u?493:420})}return s}function Qa(e){let n=en(e.projectRoot??process.cwd());qo(e),e.onStep?.("packaging application tree");let r=Wo(n,e.exclude);if(!r.length)throw Error(`No files to package under ${n}`);let i=It(r),s=e.app.handlers?.http??"public/index.php";return{zip:i,sha256:js("sha256").update(i).digest("hex"),handlers:{http:s,queue:e.app.handlers?.queue??s,cli:e.app.handlers?.cli??s},fileCount:r.length}}class pd{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(e){let n=`asset-opt-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.optimizations.set(n,r),r}createImageOptimization(e){let n=`image-opt-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.imageConfigs.set(n,r),r}createSSGConfig(e){let n=`ssg-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.ssgConfigs.set(n,r),r}createPrerenderConfig(e){let n=`prerender-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.prerenderConfigs.set(n,r),r}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 oh=new pd;class Ya{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(e,n){let r=`lifecycle-${Date.now()}-${this.counter++}`,i={id:r,transitions:e,expiration:n};return this.policies.set(r,i),i}enableVersioning(e=!1){let n=`versioning-${Date.now()}-${this.counter++}`,r={id:n,enabled:!0,mfaDelete:e};return this.versioningConfigs.set(n,r),r}createReplicationRule(e,n,r){let i=`replication-${Date.now()}-${this.counter++}`,s={id:i,sourceRegion:e,destRegion:n,destBucket:r};return this.replicationRules.set(i,s),s}createIntelligentTiering(e,n){let r=`tiering-${Date.now()}-${this.counter++}`,i={id:r,archiveDays:e,deepArchiveDays:n};return this.tieringConfigs.set(r,i),i}enableObjectLock(e){let n=`object-lock-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,mode:e.mode||"COMPLIANCE",retentionDays:e.retentionDays,retentionYears:e.retentionYears,legalHoldEnabled:e.legalHoldEnabled||!1};return this.objectLocks.set(n,r),r}enableTransferAcceleration(e){let n=`transfer-accel-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e,enabled:!0,endpoint:`${e}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,r),r}createAccessPoint(e){let n=`access-point-${Date.now()}-${this.counter++}`,r={id:n,name:e.name,bucketName:e.bucketName,vpcId:e.vpcId,publicAccessBlock:e.publicAccessBlock!==!1,policy:e.policy};return this.accessPoints.set(n,r),r}createGlacierArchive(e){let n=`glacier-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,archiveType:e.archiveType,transitionDays:e.transitionDays,restoreConfig:e.restoreTier?{tier:e.restoreTier,days:e.restoreDays||7}:void 0};return this.glacierConfigs.set(n,r),r}createInventory(e){let n=`inventory-${Date.now()}-${this.counter++}`,r={id:n,sourceBucket:e.sourceBucket,destinationBucket:e.destinationBucket,schedule:e.schedule||"Daily",format:e.format||"CSV",includedFields:e.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:e.prefix};return this.inventories.set(n,r),r}createBatchOperation(e){let n=`batch-op-${Date.now()}-${this.counter++}`,r={id:n,operation:e.operation,manifestBucket:e.manifestBucket,manifestKey:e.manifestKey,priority:e.priority||10,status:"pending"};return this.batchOps.set(n,r),r}executeBatchOperation(e){let n=this.batchOps.get(e);if(!n)throw Error(`Batch operation not found: ${e}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(e){return this.batchOps.get(e)}createLambdaNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"Lambda",arn:e.lambdaArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}createSQSNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"SQS",arn:e.queueArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}createSNSNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"SNS",arn:e.topicArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}generateObjectLockCF(e){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:e.mode}}}};if(e.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=e.retentionDays;if(e.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=e.retentionYears;return n}generateTransferAccelerationCF(e){return{AccelerateConfiguration:{AccelerationStatus:e.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(e){return{Type:"AWS::S3::AccessPoint",Properties:{Name:e.name,Bucket:e.bucketName,...e.vpcId&&{VpcConfiguration:{VpcId:e.vpcId}},PublicAccessBlockConfiguration:e.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...e.policy&&{Policy:e.policy}}}}generateInventoryCF(e){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:e.id,Destination:{BucketArn:`arn:aws:s3:::${e.destinationBucket}`,Format:e.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:e.includedFields,ScheduleFrequency:e.schedule,...e.prefix&&{Prefix:e.prefix}}]}}}generateEventNotificationCF(e){let n=e.destination.type==="Lambda"?"LambdaConfigurations":e.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",r=e.destination.type==="Lambda"?"Function":e.destination.type==="SQS"?"Queue":"Topic",i={Event:e.events[0],[r]:e.destination.arn};if(e.filter)i.Filter={S3Key:{Rules:[...e.filter.prefix?[{Name:"prefix",Value:e.filter.prefix}]:[],...e.filter.suffix?[{Name:"suffix",Value:e.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[i]}}}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 vp=new Ya;class md{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(e,n=30,r=10){let i=`health-${Date.now()}-${this.counter++}`,s={id:i,url:e,interval:n,timeout:r,status:"healthy"};return this.checks.set(i,s),s}createSyntheticMonitor(e,n,r,i){let s=`synthetic-${Date.now()}-${this.counter++}`,a={id:s,name:e,script:n,frequency:r,locations:i};return this.synthetics.set(s,a),a}trackUptime(e,n,r){let i=`uptime-${Date.now()}-${this.counter++}`,s=n/(n+r)*100,a={id:i,resource:e,uptime:n,downtime:r,availability:s};return this.uptimeTrackers.set(i,a),a}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var sh=new md;class gd{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(e,n,r,i){let s=`waf-${Date.now()}-${this.counter++}`,a={id:s,name:e,priority:n,action:r,conditions:i};return this.wafRules.set(s,a),a}enableShield(e,n="standard"){let r=`shield-${Date.now()}-${this.counter++}`,i={id:r,resourceArn:e,protectionType:n};return this.shieldProtections.set(r,i),i}createSecurityGroup(e,n,r){let i=`sg-${Date.now()}-${this.counter++}`,s={id:i,name:e,vpcId:n,rules:r};return this.securityGroups.set(i,s),s}createNACL(e,n){let r=`nacl-${Date.now()}-${this.counter++}`,i={id:r,vpcId:e,rules:n};return this.nacls.set(r,i),i}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var ah=new gd;class fd{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(e,n){let r=`tagging-${Date.now()}-${this.counter++}`,i={id:r,tags:e,resources:n};return this.strategies.set(r,i),i}createCostAllocation(e,n){let r=`cost-${Date.now()}-${this.counter++}`,i={id:r,tagKey:e,allocations:n};return this.allocations.set(r,i),i}createResourceGroup(e,n,r){let i=`group-${Date.now()}-${this.counter++}`,s={id:i,name:e,query:{resourceTypeFilters:n,tagFilters:r}};return this.groups.set(i,s),s}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var ch=new fd;export{dm,um,Zs,Wc,ea,ta,gn,Ue,A,ra,Kc,H,xr,w,Kd,Ri,na,ia,B,Lo,Jd,Xd,Qd,Yd,l,o,pm,mm,T,oa,sa,aa,gm,fm,ke,ca,Ii,Zd,hm,ym,Fe,Et,la,Jc,Xc,bm,Qc,Yc,Zc,Mo,da,tt,Uo,fn,Pi,hn,Be,eu,Fo,Bo,ua,pa,ma,ga,fa,ha,Te,j,tu,ru,el,b,L,rt,N,tl,wt,ge,Ht,Sm,rl,Ee,jo,je,Gt,Di,we,Vo,xe,nu,Ni,Ae,Re,ne,ki,X,qt,At,Ie,t,yn,vm,nl,ya,Cm,Tm,Em,wm,ba,Am,Rm,Im,Pm,Dm,Nm,km,xm,_m,Om,$m,Lm,iu,ou,su,au,cu,lu,du,Wt,il,ol,_r,xi,Mm,sl,Um,Fm,bn,Bm,jm,Vm,zm,Hm,Gm,uu,pu,mu,gu,fu,_i,qm,Sn,hu,al,yu,Sa,fe,bu,Su,Rt,zo,Kt,vu,cl,Cu,Tu,Eu,ll,he,Wm,Km,Jm,Xm,wu,Qm,Pe,Ym,Zm,eg,va,Ca,Au,dl,ul,tg,rg,ng,ig,og,Ru,Ta,sg,ag,cg,lg,dg,Iu,Pu,ug,pg,mg,gg,fg,hg,yg,Du,bg,pl,Ea,Sg,vg,Cg,Tg,ml,gl,fl,Eg,wa,Nu,ku,xu,_u,Aa,Ou,wg,Ag,Rg,Ig,Pg,Dg,Ng,$u,Lu,Mu,Uu,hl,kg,xg,_g,Og,$g,Lg,Mg,Ug,Fg,Fu,Bu,ju,Vu,Bg,jg,yl,Vg,bl,Sl,vl,Cl,zg,Hg,Gg,qg,nt,Oi,Wg,Kg,Jg,Xg,Qg,Yg,Zg,ef,zu,tf,rf,Tl,El,nf,of,Hu,sf,af,cf,lf,df,uf,pf,mf,gf,ff,hf,yf,bf,Sf,vf,Cf,Tf,Ef,wf,Af,Rf,Ra,Gu,Ia,qu,Pa,Wu,Da,Ku,Na,Ju,Or,Xu,ka,Qu,$i,Yu,xa,Zu,_a,ep,wl,If,Al,Pf,Oa,tp,$r,rp,Rl,Df,$a,np,Il,Nf,Pl,kf,Dl,xf,La,ip,Nl,_f,kl,Of,xl,$f,_l,Lf,Ma,op,Ua,sp,Ol,Mf,$l,Uf,Ll,Ff,Ml,Bf,Ul,jf,Fl,Vf,Fa,ap,Bl,zf,jl,Hf,Vl,Gf,zl,qf,Hl,Wf,Gl,Kf,ql,Wl,Kl,Jl,Xl,Jf,Ql,Xf,Yl,Qf,Zl,Yf,It,ed,cp,Ho,Ba,vn,lp,Li,Jt,ja,Va,dp,up,za,td,Ha,rd,Zf,eh,Ga,qa,Wa,nd,Mi,id,od,Go,Ka,Ja,sd,pp,mp,gp,th,ad,cd,rh,fp,ld,hp,yp,bp,nh,dd,Cn,Xa,ud,ih,Sp,qo,Wo,Qa,pd,oh,Ya,vp,md,sh,gd,ah,fd,ch};
7329
+ `}import{readFileSync as xs}from"node:fs";import{dirname as ks,join as tr}from"node:path";import{fileURLToPath as Ms}from"node:url";function Ls(){return tr(ks(Ms(import.meta.url)),"runtime-assets")}function wn(){let e=Ls(),n=(r)=>xs(tr(e,r),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:gd(),mode:420}]}function ec(e={}){let n=e.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,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 fd=["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 at}from"node:child_process";import{existsSync as Os,mkdirSync as $s,mkdtempSync as Bs,readdirSync as Fs,readFileSync as Gs,rmSync as _s,statSync as nr,writeFileSync as Ws}from"node:fs";import{tmpdir as Vs}from"node:os";import{join as Ce,relative as Us}from"node:path";function*rr(e){for(let n of Fs(e)){let r=Ce(e,n);if(nr(r).isDirectory())yield*rr(r);else yield r}}function ch(e={}){let n=e.architecture??"x86_64",r=e.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),i=e.onStep??(()=>{}),s=Bs(Ce(Vs(),"tscloud-php-layer-")),a="tscloud-php-layer:build";try{Ws(Ce(s,"Dockerfile"),od(e)),i("Building PHP runtime image (docker)"),at("docker",["build","--platform",r,"-t","tscloud-php-layer:build",s],{stdio:"inherit"}),i("Extracting /opt/php from image");let c=at("docker",["create","--platform",r,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),u=Ce(s,"opt");$s(u,{recursive:!0});try{at("docker",["cp",`${c}:/opt/php`,Ce(u,"php")],{stdio:"inherit"})}finally{at("docker",["rm",c],{stdio:"ignore"})}if(!Os(Ce(u,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let d=[];for(let y of rr(u)){let h=Us(u,y).replace(/\\/g,"/"),f=nr(y).mode&73?493:420;d.push({name:h,data:Gs(y),mode:f})}i("Injecting runtime assets");let m=new Set(wn().map((y)=>y.path)),p=d.filter((y)=>!m.has(y.name));for(let y of wn())p.push({name:y.path,data:y.contents,mode:y.mode});return i("Packaging layer ZIP"),{zip:It(p),architecture:n,fileCount:p.length}}finally{_s(s,{recursive:!0,force:!0})}}import{execSync as Hs}from"node:child_process";import{createHash as js}from"node:crypto";import{readdirSync as Ks,readFileSync as qs,statSync as ir}from"node:fs";import{join as zs,relative as sr,resolve as en}from"node:path";var Ep=[".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 Qs(e,n){return n.some((r)=>e===r||e.startsWith(`${r}/`))}function*ar(e,n,r){for(let i of Ks(e)){let s=zs(e,i),a=sr(n,s).replace(/\\/g,"/");if(Qs(a,r))continue;if(ir(s).isDirectory())yield*ar(s,n,r);else yield s}}function Xo(e){if(e.skipBuild)return;let n=en(e.projectRoot??process.cwd()),r=e.app.build??fd;for(let i of r)e.onStep?.(`build: ${i}`),Hs(i,{stdio:"inherit",cwd:n})}function Qo(e,n=[]){let r=en(e),i=[...Ep,yn(),...n],s=[];for(let a of ar(r,r,i)){let c=sr(r,a).replace(/\\/g,"/"),u=(ir(a).mode&73)!==0;s.push({name:c,data:qs(a),mode:u?493:420})}return s}function tc(e){let n=en(e.projectRoot??process.cwd());Xo(e),e.onStep?.("packaging application tree");let r=Qo(n,e.exclude);if(!r.length)throw Error(`No files to package under ${n}`);let i=It(r),s=e.app.handlers?.http??"public/index.php";return{zip:i,sha256:js("sha256").update(i).digest("hex"),handlers:{http:s,queue:e.app.handlers?.queue??s,cli:e.app.handlers?.cli??s},fileCount:r.length}}class hd{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(e){let n=`asset-opt-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.optimizations.set(n,r),r}createImageOptimization(e){let n=`image-opt-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.imageConfigs.set(n,r),r}createSSGConfig(e){let n=`ssg-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.ssgConfigs.set(n,r),r}createPrerenderConfig(e){let n=`prerender-${Date.now()}-${this.counter++}`,r={id:n,...e};return this.prerenderConfigs.set(n,r),r}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 lh=new hd;class rc{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(e,n){let r=`lifecycle-${Date.now()}-${this.counter++}`,i={id:r,transitions:e,expiration:n};return this.policies.set(r,i),i}enableVersioning(e=!1){let n=`versioning-${Date.now()}-${this.counter++}`,r={id:n,enabled:!0,mfaDelete:e};return this.versioningConfigs.set(n,r),r}createReplicationRule(e,n,r){let i=`replication-${Date.now()}-${this.counter++}`,s={id:i,sourceRegion:e,destRegion:n,destBucket:r};return this.replicationRules.set(i,s),s}createIntelligentTiering(e,n){let r=`tiering-${Date.now()}-${this.counter++}`,i={id:r,archiveDays:e,deepArchiveDays:n};return this.tieringConfigs.set(r,i),i}enableObjectLock(e){let n=`object-lock-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,mode:e.mode||"COMPLIANCE",retentionDays:e.retentionDays,retentionYears:e.retentionYears,legalHoldEnabled:e.legalHoldEnabled||!1};return this.objectLocks.set(n,r),r}enableTransferAcceleration(e){let n=`transfer-accel-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e,enabled:!0,endpoint:`${e}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,r),r}createAccessPoint(e){let n=`access-point-${Date.now()}-${this.counter++}`,r={id:n,name:e.name,bucketName:e.bucketName,vpcId:e.vpcId,publicAccessBlock:e.publicAccessBlock!==!1,policy:e.policy};return this.accessPoints.set(n,r),r}createGlacierArchive(e){let n=`glacier-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,archiveType:e.archiveType,transitionDays:e.transitionDays,restoreConfig:e.restoreTier?{tier:e.restoreTier,days:e.restoreDays||7}:void 0};return this.glacierConfigs.set(n,r),r}createInventory(e){let n=`inventory-${Date.now()}-${this.counter++}`,r={id:n,sourceBucket:e.sourceBucket,destinationBucket:e.destinationBucket,schedule:e.schedule||"Daily",format:e.format||"CSV",includedFields:e.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:e.prefix};return this.inventories.set(n,r),r}createBatchOperation(e){let n=`batch-op-${Date.now()}-${this.counter++}`,r={id:n,operation:e.operation,manifestBucket:e.manifestBucket,manifestKey:e.manifestKey,priority:e.priority||10,status:"pending"};return this.batchOps.set(n,r),r}executeBatchOperation(e){let n=this.batchOps.get(e);if(!n)throw Error(`Batch operation not found: ${e}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(e){return this.batchOps.get(e)}createLambdaNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"Lambda",arn:e.lambdaArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}createSQSNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"SQS",arn:e.queueArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}createSNSNotification(e){let n=`event-${Date.now()}-${this.counter++}`,r={id:n,bucketName:e.bucketName,events:e.events,destination:{type:"SNS",arn:e.topicArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(n,r),r}generateObjectLockCF(e){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:e.mode}}}};if(e.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=e.retentionDays;if(e.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=e.retentionYears;return n}generateTransferAccelerationCF(e){return{AccelerateConfiguration:{AccelerationStatus:e.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(e){return{Type:"AWS::S3::AccessPoint",Properties:{Name:e.name,Bucket:e.bucketName,...e.vpcId&&{VpcConfiguration:{VpcId:e.vpcId}},PublicAccessBlockConfiguration:e.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...e.policy&&{Policy:e.policy}}}}generateInventoryCF(e){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:e.id,Destination:{BucketArn:`arn:aws:s3:::${e.destinationBucket}`,Format:e.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:e.includedFields,ScheduleFrequency:e.schedule,...e.prefix&&{Prefix:e.prefix}}]}}}generateEventNotificationCF(e){let n=e.destination.type==="Lambda"?"LambdaConfigurations":e.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",r=e.destination.type==="Lambda"?"Function":e.destination.type==="SQS"?"Queue":"Topic",i={Event:e.events[0],[r]:e.destination.arn};if(e.filter)i.Filter={S3Key:{Rules:[...e.filter.prefix?[{Name:"prefix",Value:e.filter.prefix}]:[],...e.filter.suffix?[{Name:"suffix",Value:e.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[i]}}}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 wp=new rc;class yd{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(e,n=30,r=10){let i=`health-${Date.now()}-${this.counter++}`,s={id:i,url:e,interval:n,timeout:r,status:"healthy"};return this.checks.set(i,s),s}createSyntheticMonitor(e,n,r,i){let s=`synthetic-${Date.now()}-${this.counter++}`,a={id:s,name:e,script:n,frequency:r,locations:i};return this.synthetics.set(s,a),a}trackUptime(e,n,r){let i=`uptime-${Date.now()}-${this.counter++}`,s=n/(n+r)*100,a={id:i,resource:e,uptime:n,downtime:r,availability:s};return this.uptimeTrackers.set(i,a),a}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var dh=new yd;class bd{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(e,n,r,i){let s=`waf-${Date.now()}-${this.counter++}`,a={id:s,name:e,priority:n,action:r,conditions:i};return this.wafRules.set(s,a),a}enableShield(e,n="standard"){let r=`shield-${Date.now()}-${this.counter++}`,i={id:r,resourceArn:e,protectionType:n};return this.shieldProtections.set(r,i),i}createSecurityGroup(e,n,r){let i=`sg-${Date.now()}-${this.counter++}`,s={id:i,name:e,vpcId:n,rules:r};return this.securityGroups.set(i,s),s}createNACL(e,n){let r=`nacl-${Date.now()}-${this.counter++}`,i={id:r,vpcId:e,rules:n};return this.nacls.set(r,i),i}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var uh=new bd;class Sd{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(e,n){let r=`tagging-${Date.now()}-${this.counter++}`,i={id:r,tags:e,resources:n};return this.strategies.set(r,i),i}createCostAllocation(e,n){let r=`cost-${Date.now()}-${this.counter++}`,i={id:r,tagKey:e,allocations:n};return this.allocations.set(r,i),i}createResourceGroup(e,n,r){let i=`group-${Date.now()}-${this.counter++}`,s={id:i,name:e,query:{resourceTypeFilters:n,tagFilters:r}};return this.groups.set(i,s),s}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var ph=new Sd;export{gm,fm,na,Qc,ia,oa,yn,Be,A,sa,Yc,H,$r,w,Yd,ki,aa,ca,F,Fo,Zd,eu,tu,ru,l,o,hm,ym,T,la,da,ua,bm,Sm,xe,pa,Ni,nu,vm,Cm,Fe,Et,ma,Zc,el,Tm,tl,rl,nl,jo,ga,tt,Vo,bn,xi,Sn,je,iu,zo,Ho,fa,ha,ya,ba,Sa,va,Te,j,ou,su,il,b,L,rt,k,ol,wt,ge,Ht,Em,sl,Ee,Go,Ve,Gt,_i,we,qo,_e,au,Oi,Ae,Re,ne,$i,X,qt,At,Ie,t,vn,wm,al,Ca,Am,Rm,Im,Pm,Ta,Dm,km,Nm,xm,_m,Om,$m,Lm,Mm,Um,Bm,Fm,cu,lu,du,uu,pu,mu,gu,Wt,cl,ll,Lr,Li,jm,dl,Vm,zm,Cn,Hm,Gm,qm,Wm,Km,Jm,fu,hu,yu,bu,Su,Mi,Xm,Tn,vu,ul,Cu,Ea,fe,Tu,Eu,Rt,Wo,Kt,wu,pl,Au,Ru,Iu,ml,he,Qm,Ym,Zm,eg,Pu,tg,Pe,rg,ng,ig,wa,Aa,Du,gl,fl,og,sg,ag,cg,lg,ku,Ra,dg,ug,pg,mg,gg,Nu,xu,fg,hg,yg,bg,Sg,vg,Cg,_u,Tg,hl,Ia,Eg,wg,Ag,Rg,yl,bl,Sl,Ig,Pa,Ou,$u,Lu,Mu,Da,Uu,Pg,Dg,kg,Ng,xg,_g,Og,Bu,Fu,ju,Vu,vl,$g,Lg,Mg,Ug,Bg,Fg,jg,Vg,zg,zu,Hu,Gu,qu,Hg,Gg,Cl,qg,Tl,El,wl,Al,Wg,Kg,Jg,Xg,nt,Ui,Qg,Yg,Zg,ef,tf,rf,nf,of,Wu,sf,af,Rl,Il,cf,lf,Ku,df,uf,pf,mf,gf,ff,hf,yf,bf,Sf,vf,Cf,Tf,Ef,wf,Af,Rf,If,Pf,Df,kf,ka,Ju,Na,Xu,xa,Qu,_a,Yu,Oa,Zu,Mr,ep,$a,tp,Bi,rp,La,np,Ma,ip,Pl,Nf,Dl,xf,Ua,op,Ur,sp,kl,_f,Ba,ap,Nl,Of,xl,$f,_l,Lf,Fa,cp,Ol,Mf,$l,Uf,Ll,Bf,Ml,Ff,ja,lp,Va,dp,Ul,jf,Bl,Vf,Fl,zf,jl,Hf,Vl,Gf,zl,qf,za,up,Hl,Wf,Gl,Kf,ql,Jf,Wl,Xf,Kl,Qf,Jl,Yf,Xl,Ql,Yl,Zl,ed,Zf,td,eh,rd,th,nd,rh,It,id,pp,Ko,Ha,En,mp,Fi,Jt,Ga,qa,gp,fp,Wa,od,Ka,sd,nh,ih,Ja,Xa,Qa,ad,ji,cd,ld,Jo,Ya,Za,dd,hp,yp,bp,oh,ud,pd,sh,Sp,md,vp,Cp,Tp,ah,gd,wn,ec,fd,ch,Ep,Xo,Qo,tc,hd,lh,rc,wp,yd,dh,bd,uh,Sd,ph};