@stacksjs/ts-cloud 0.16.36 → 0.16.38

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 (193) hide show
  1. package/dist/aws/bedrock.d.ts +0 -23
  2. package/dist/aws/client.d.ts +16 -7
  3. package/dist/aws/event-stream.d.ts +36 -0
  4. package/dist/aws/index.d.ts +1 -0
  5. package/dist/aws/index.js +1 -1
  6. package/dist/bin/{chunk-9n3wmdd6.js → chunk-07qwk0sj.js} +5 -5
  7. package/dist/bin/{chunk-4f5hhqh9.js → chunk-0c1fv0xt.js} +4 -4
  8. package/dist/bin/chunk-0c5vn8rp.js +1 -0
  9. package/dist/bin/{chunk-v4gpkkzh.js → chunk-0ynfqf9t.js} +1 -1
  10. package/dist/bin/chunk-1wf1s8db.js +1 -0
  11. package/dist/bin/{chunk-kcsjaam6.js → chunk-48nz63ab.js} +3 -3
  12. package/dist/bin/{chunk-2ax1rm70.js → chunk-4bp4k1x2.js} +2 -2
  13. package/dist/bin/chunk-4dtrry0t.js +1 -0
  14. package/dist/bin/{chunk-h42xsxhm.js → chunk-4h60xsat.js} +2 -2
  15. package/dist/bin/{chunk-svrgx20b.js → chunk-55cckkb2.js} +3 -3
  16. package/dist/bin/{chunk-71jh460j.js → chunk-5wqjqh6c.js} +2 -2
  17. package/dist/bin/chunk-6kcxf3b2.js +1 -0
  18. package/dist/bin/chunk-6ksbfg6t.js +1 -0
  19. package/dist/bin/{chunk-twmeg17s.js → chunk-6r5mehaj.js} +2 -2
  20. package/dist/bin/chunk-7rkg1yph.js +1 -0
  21. package/dist/bin/{chunk-4mt7rspg.js → chunk-7rpj0qhb.js} +2 -2
  22. package/dist/bin/{chunk-0870bs4x.js → chunk-8496fsmq.js} +75 -75
  23. package/dist/bin/{chunk-ar6bxdv4.js → chunk-85k5gvnc.js} +3 -3
  24. package/dist/bin/{chunk-bpw8m7rw.js → chunk-8zn63v9h.js} +3 -3
  25. package/dist/bin/chunk-989j6ezd.js +1 -0
  26. package/dist/bin/{chunk-5yv95sqs.js → chunk-aykdp1wv.js} +1 -1
  27. package/dist/bin/chunk-bgdvhp6m.js +1 -0
  28. package/dist/bin/{chunk-2qdktx9h.js → chunk-c7z8et78.js} +1 -1
  29. package/dist/bin/{chunk-cnwncp50.js → chunk-cqhtnsby.js} +4 -4
  30. package/dist/bin/{chunk-tv0rtc0s.js → chunk-cvc9bxd4.js} +2 -2
  31. package/dist/bin/chunk-czzrfhn7.js +1 -0
  32. package/dist/bin/chunk-d5arnf2f.js +1 -0
  33. package/dist/bin/{chunk-c8439azc.js → chunk-d8x60kvn.js} +2 -2
  34. package/dist/bin/{chunk-7rwc5bvv.js → chunk-dmwfnbg0.js} +5 -5
  35. package/dist/bin/{chunk-y2qz4vw1.js → chunk-dnmb3sr0.js} +1 -1
  36. package/dist/bin/{chunk-7n84q4np.js → chunk-e06m9m6z.js} +1 -1
  37. package/dist/bin/{chunk-exc2mqcc.js → chunk-e0kapeev.js} +12 -12
  38. package/dist/bin/chunk-e51ajfyr.js +1 -0
  39. package/dist/bin/{chunk-r3gxhy1k.js → chunk-e6mfcw0v.js} +5 -5
  40. package/dist/bin/chunk-fh5bjm3d.js +1 -0
  41. package/dist/bin/chunk-fw6hbyeg.js +1 -0
  42. package/dist/bin/{chunk-ymfnqae6.js → chunk-gc8p1tdr.js} +1 -1
  43. package/dist/bin/chunk-h7gfd2yq.js +1 -0
  44. package/dist/bin/{chunk-r8e263ne.js → chunk-hjq05rxh.js} +1 -1
  45. package/dist/bin/chunk-jxnw879g.js +1 -0
  46. package/dist/bin/chunk-k3yq569a.js +1 -0
  47. package/dist/bin/{chunk-bfzdbe4g.js → chunk-mbr9j2fw.js} +6 -6
  48. package/dist/bin/chunk-nhrwct94.js +1 -0
  49. package/dist/bin/chunk-pa4fymr0.js +1 -0
  50. package/dist/bin/{chunk-8p2v1gat.js → chunk-pyr0dc6j.js} +50 -50
  51. package/dist/bin/{chunk-qbagghsb.js → chunk-q8hp4dfy.js} +193 -216
  52. package/dist/bin/{chunk-haqap7d1.js → chunk-r0yapyqc.js} +1 -1
  53. package/dist/bin/chunk-s9xven24.js +1 -0
  54. package/dist/bin/{chunk-s7f24j6k.js → chunk-sqmays54.js} +1 -1
  55. package/dist/bin/{chunk-f76wtb7d.js → chunk-tt3m3fda.js} +1 -1
  56. package/dist/bin/{chunk-vkdw6sxn.js → chunk-w6yx9bhb.js} +1 -1
  57. package/dist/bin/{chunk-gbpmgae9.js → chunk-w8jfw39t.js} +2 -2
  58. package/dist/bin/{chunk-j01jx36v.js → chunk-wga7gj0h.js} +1 -1
  59. package/dist/bin/chunk-wgv9nv0z.js +1 -0
  60. package/dist/bin/{chunk-yt95wsqg.js → chunk-x0ywfbk5.js} +1 -1
  61. package/dist/bin/chunk-y5980ycr.js +1 -0
  62. package/dist/bin/chunk-y5ez6ba7.js +1 -0
  63. package/dist/bin/chunk-ya71t2ed.js +1 -0
  64. package/dist/bin/{chunk-v3prk467.js → chunk-ygsdntxq.js} +4 -4
  65. package/dist/bin/chunk-zb1nh252.js +1 -0
  66. package/dist/bin/cli.js +188 -188
  67. package/dist/bin/dashboard-server.js +1 -1
  68. package/dist/chunk-1ty76ybd.js +1 -0
  69. package/dist/chunk-2mypcz4a.js +1 -0
  70. package/dist/{chunk-yzns0k2b.js → chunk-2n4ktft4.js} +1 -1
  71. package/dist/{chunk-kcj92xx7.js → chunk-3cyszqzh.js} +2 -2
  72. package/dist/{chunk-my6yn5sd.js → chunk-5vk7nss8.js} +2 -2
  73. package/dist/{chunk-kzjvasjs.js → chunk-bx3jmgd0.js} +2 -2
  74. package/dist/{chunk-3nqtbyfp.js → chunk-c45ay9fx.js} +5 -5
  75. package/dist/{chunk-7gvnrx46.js → chunk-dg834141.js} +5 -5
  76. package/dist/{chunk-2x636sgn.js → chunk-ej9dqt2r.js} +7 -10
  77. package/dist/chunk-fe5sbczg.js +1 -0
  78. package/dist/{chunk-ctkzxq0d.js → chunk-ffba3270.js} +2 -2
  79. package/dist/{chunk-n4z75mk8.js → chunk-gcqq9m4b.js} +4 -4
  80. package/dist/chunk-gtc1gvfj.js +1 -0
  81. package/dist/{chunk-ajn6xp8v.js → chunk-j1aq97br.js} +3 -3
  82. package/dist/chunk-j5t1amn0.js +1 -0
  83. package/dist/{chunk-sekw1nyx.js → chunk-jsnhb1p4.js} +19 -19
  84. package/dist/{chunk-tez0qfv9.js → chunk-kkeb1dk1.js} +1 -1
  85. package/dist/{chunk-nr6z3e1p.js → chunk-kpjhfgbh.js} +3 -3
  86. package/dist/{chunk-hvwqct5q.js → chunk-kyn6a4zf.js} +2 -2
  87. package/dist/{chunk-0kddm2mt.js → chunk-n1r9313b.js} +2 -2
  88. package/dist/{chunk-mhv7dbr1.js → chunk-n8g8t8hf.js} +3 -3
  89. package/dist/{chunk-q9rdxpmg.js → chunk-nzmangkw.js} +4 -4
  90. package/dist/{chunk-pdjap529.js → chunk-p4rknh9f.js} +1 -1
  91. package/dist/{chunk-k3mazfb2.js → chunk-q08s698e.js} +49 -49
  92. package/dist/{chunk-fszn9rnn.js → chunk-qhtgfjhd.js} +19 -19
  93. package/dist/chunk-s20830hg.js +1 -0
  94. package/dist/{chunk-p0ksat08.js → chunk-t52wetq8.js} +1 -1
  95. package/dist/{chunk-78shfb0z.js → chunk-t80x808z.js} +94 -94
  96. package/dist/{chunk-9aaj9a0s.js → chunk-tbn385ak.js} +100 -123
  97. package/dist/{chunk-50m6sq01.js → chunk-v83qx041.js} +4 -4
  98. package/dist/{chunk-ncsb3sdn.js → chunk-xr7ew64s.js} +1 -1
  99. package/dist/{chunk-pfav9qnt.js → chunk-yrcv3hrj.js} +6 -6
  100. package/dist/{chunk-mxw5gkd8.js → chunk-zvyrpmvd.js} +1 -1
  101. package/dist/deploy/index.js +1 -1
  102. package/dist/dns/index.js +1 -1
  103. package/dist/drivers/index.js +1 -1
  104. package/dist/generators/infrastructure.d.ts +7 -0
  105. package/dist/index.js +24 -24
  106. package/dist/operations/index.js +1 -1
  107. package/dist/protection/index.js +1 -1
  108. package/dist/spend/index.js +1 -1
  109. package/dist/ui/404.html +1 -1
  110. package/dist/ui/accept-invitation.html +1 -1
  111. package/dist/ui/access-denied.html +1 -1
  112. package/dist/ui/account/automation.html +6 -6
  113. package/dist/ui/account/security.html +2 -2
  114. package/dist/ui/applications/compose.html +6 -6
  115. package/dist/ui/applications/new.html +2 -2
  116. package/dist/ui/data/backups.html +6 -6
  117. package/dist/ui/data/services.html +6 -6
  118. package/dist/ui/data/volumes.html +6 -6
  119. package/dist/ui/index.html +5 -5
  120. package/dist/ui/infrastructure/topology.html +6 -6
  121. package/dist/ui/integrations.html +2 -2
  122. package/dist/ui/operations/alerts.html +6 -6
  123. package/dist/ui/operations/configuration.html +6 -6
  124. package/dist/ui/operations/jobs.html +5 -5
  125. package/dist/ui/operations/maintenance.html +6 -6
  126. package/dist/ui/operations/observability.html +6 -6
  127. package/dist/ui/operations/previews.html +6 -6
  128. package/dist/ui/operations/queue.html +5 -5
  129. package/dist/ui/operations/regions.html +6 -6
  130. package/dist/ui/operations/releases.html +6 -6
  131. package/dist/ui/operations/spend.html +6 -6
  132. package/dist/ui/operations/workloads.html +6 -6
  133. package/dist/ui/security.html +2 -2
  134. package/dist/ui/server/actions.html +6 -6
  135. package/dist/ui/server/activity.html +2 -2
  136. package/dist/ui/server/capacity.html +5 -5
  137. package/dist/ui/server/database.html +6 -6
  138. package/dist/ui/server/deployments.html +6 -6
  139. package/dist/ui/server/diagnostics.html +2 -2
  140. package/dist/ui/server/firewall.html +6 -6
  141. package/dist/ui/server/fleet.html +6 -6
  142. package/dist/ui/server/logs.html +6 -6
  143. package/dist/ui/server/metrics.html +6 -6
  144. package/dist/ui/server/security.html +2 -2
  145. package/dist/ui/server/services.html +2 -2
  146. package/dist/ui/server/sites.html +6 -6
  147. package/dist/ui/server/ssh-keys.html +6 -6
  148. package/dist/ui/server/team.html +6 -6
  149. package/dist/ui/server/terminal.html +2 -2
  150. package/dist/ui/serverless/alarms.html +6 -6
  151. package/dist/ui/serverless/assets.html +2 -2
  152. package/dist/ui/serverless/cost.html +2 -2
  153. package/dist/ui/serverless/data.html +6 -6
  154. package/dist/ui/serverless/deployments.html +2 -2
  155. package/dist/ui/serverless/firewall.html +2 -2
  156. package/dist/ui/serverless/functions.html +6 -6
  157. package/dist/ui/serverless/logs.html +6 -6
  158. package/dist/ui/serverless/metrics.html +2 -2
  159. package/dist/ui/serverless/queues.html +6 -6
  160. package/dist/ui/serverless/secrets.html +6 -6
  161. package/dist/ui/serverless/traces.html +5 -5
  162. package/dist/ui/serverless.html +6 -6
  163. package/package.json +3 -3
  164. package/dist/bin/chunk-1k9sw5y7.js +0 -1
  165. package/dist/bin/chunk-2cx4k97r.js +0 -1
  166. package/dist/bin/chunk-2rcwhdx9.js +0 -1
  167. package/dist/bin/chunk-3gg55dkc.js +0 -1
  168. package/dist/bin/chunk-683zr91n.js +0 -1
  169. package/dist/bin/chunk-691k55nw.js +0 -1
  170. package/dist/bin/chunk-7s3wtq40.js +0 -1
  171. package/dist/bin/chunk-8bb6kyhm.js +0 -1
  172. package/dist/bin/chunk-9pvkb6br.js +0 -1
  173. package/dist/bin/chunk-dd567z84.js +0 -1
  174. package/dist/bin/chunk-dzx0w4zb.js +0 -1
  175. package/dist/bin/chunk-e7h2j23x.js +0 -1
  176. package/dist/bin/chunk-e9mkg5dn.js +0 -1
  177. package/dist/bin/chunk-h5darb19.js +0 -1
  178. package/dist/bin/chunk-h6n5v6rf.js +0 -1
  179. package/dist/bin/chunk-hc4s84v1.js +0 -1
  180. package/dist/bin/chunk-hfswzdzj.js +0 -1
  181. package/dist/bin/chunk-p5k5z7gm.js +0 -1
  182. package/dist/bin/chunk-tj589nbw.js +0 -1
  183. package/dist/bin/chunk-w68hker6.js +0 -1
  184. package/dist/bin/chunk-x8wvsf1k.js +0 -1
  185. package/dist/bin/chunk-y1qk3df2.js +0 -1
  186. package/dist/bin/chunk-y4pfvx0x.js +0 -1
  187. package/dist/bin/chunk-zjw9sdr5.js +0 -1
  188. package/dist/chunk-0my5jwq8.js +0 -1
  189. package/dist/chunk-fxk29btr.js +0 -1
  190. package/dist/chunk-fz62nas4.js +0 -1
  191. package/dist/chunk-gyp7jcgw.js +0 -1
  192. package/dist/chunk-wxtr8sv8.js +0 -1
  193. package/dist/chunk-yhjagaff.js +0 -1
@@ -1,14 +1,14 @@
1
- import{R,Oo}from"./chunk-3nqtbyfp.js";import{tn,he}from"./chunk-kcj92xx7.js";var YS={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}},ZS={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 ht,join as Ze,relative as rr}from"node:path";var Nd=".ts-cloud",Mp="TS_CLOUD_STATE_DIR",ft=null;function kd(n){ft=n?.trim()||null}function Bd(){return Boolean(process.env[Mp]?.trim()||ft)}function zr(){return process.env[Mp]?.trim()||ft||Nd}function L(...n){return Ze(zr(),...n)}function d(n,...i){let s=zr();return ht(s)?Ze(s,...i):Ze(n,s,...i)}function xd(n,i=process.cwd()){let s=(c,l)=>{let u=rr(c,l);return u===""||!u.startsWith("..")&&!ht(u)},o=ht(n)?n:Ze(i,n);return s(d(i),o)}function Fp(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function U(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=Fp(n);return i?"serverless":"server"}function Od(n){let{server:i,serverless:s}=Fp(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function g(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function ir(n){return typeof n==="object"&&n!==null?n:{}}function bA(n){return n===!0||typeof n==="object"&&n!==null}function sr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function ar(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function _i(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=ir(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=sr(n,i.environment),f=o.hostname??(u?`mail.${h}`:"localhost"),S=o.ports??{},A=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},v=o.tls??{},C=v.enabled??u,P=!!(v.certPath&&v.keyPath),E=(o.accounts??[]).map((J)=>({address:J.address,password:J.password})),I=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},D=o.dkim===!1?!1:o.dkim===!0||u,x=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},O=o.webmail===!1?!1:x.enabled??!0,w=o.spam??{},B=o.delivery??(u?"direct":"none"),_=o.expose??u,K=ar(f),Z=[...new Set([f,...K?[K]:[],...o.domains??[]])];return{enabled:bA(s),mode:l,version:o.version,hostname:f,domains:Z,ports:A,tls:{enabled:C,acme:C&&!P&&(v.acme??!0),certPath:v.certPath,keyPath:v.keyPath,requireForAuth:v.requireForAuth??(C&&u),acmeEmail:v.acmeEmail??E[0]?.address},dkim:{enabled:D,selector:I.selector??"default",rotate:I.rotate??!1,rotateIntervalDays:I.rotateIntervalDays??90},webmail:{enabled:O,port:x.port??A.webmail,domain:x.domain},delivery:B,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:w.enabled??u,enforce:w.enforce??!1,junkScore:w.junkScore??5,rejectScore:w.rejectScore??12,dnsbl:w.dnsbl??u,greylist:w.greylist??!1},webhookUrl:o.webhookUrl,expose:_,bindAddress:_?"0.0.0.0":"127.0.0.1"}}function _d(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Ld(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function me(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class $d{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
1
+ import{R,Oo}from"./chunk-c45ay9fx.js";import{tn,Xe}from"./chunk-3cyszqzh.js";var aI={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}},cI={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 ht,join as Ze,relative as rr}from"node:path";var Bd=".ts-cloud",Gp="TS_CLOUD_STATE_DIR",ft=null;function xd(n){ft=n?.trim()||null}function Od(){return Boolean(process.env[Gp]?.trim()||ft)}function zr(){return process.env[Gp]?.trim()||ft||Bd}function L(...n){return Ze(zr(),...n)}function d(n,...i){let s=zr();return ht(s)?Ze(s,...i):Ze(n,s,...i)}function _d(n,i=process.cwd()){let s=(c,l)=>{let u=rr(c,l);return u===""||!u.startsWith("..")&&!ht(u)},o=ht(n)?n:Ze(i,n);return s(d(i),o)}function Vp(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function U(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=Vp(n);return i?"serverless":"server"}function Ld(n){let{server:i,serverless:s}=Vp(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function g(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function ir(n){return typeof n==="object"&&n!==null?n:{}}function DA(n){return n===!0||typeof n==="object"&&n!==null}function sr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function ar(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function _i(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=ir(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=sr(n,i.environment),f=o.hostname??(u?`mail.${h}`:"localhost"),S=o.ports??{},A=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},v=o.tls??{},C=v.enabled??u,P=!!(v.certPath&&v.keyPath),E=(o.accounts??[]).map((J)=>({address:J.address,password:J.password})),I=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},D=o.dkim===!1?!1:o.dkim===!0||u,x=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},O=o.webmail===!1?!1:x.enabled??!0,w=o.spam??{},B=o.delivery??(u?"direct":"none"),_=o.expose??u,W=ar(f),Z=[...new Set([f,...W?[W]:[],...o.domains??[]])];return{enabled:DA(s),mode:l,version:o.version,hostname:f,domains:Z,ports:A,tls:{enabled:C,acme:C&&!P&&(v.acme??!0),certPath:v.certPath,keyPath:v.keyPath,requireForAuth:v.requireForAuth??(C&&u),acmeEmail:v.acmeEmail??E[0]?.address},dkim:{enabled:D,selector:I.selector??"default",rotate:I.rotate??!1,rotateIntervalDays:I.rotateIntervalDays??90},webmail:{enabled:O,port:x.port??A.webmail,domain:x.domain},delivery:B,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:w.enabled??u,enforce:w.enforce??!1,junkScore:w.junkScore??5,rejectScore:w.rejectScore??12,dnsbl:w.dnsbl??u,greylist:w.greylist??!1},webhookUrl:o.webhookUrl,expose:_,bindAddress:_?"0.0.0.0":"127.0.0.1"}}function $d(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Md(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function me(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class Fd{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
2
2
  ${this.convertToYAML(l,i+1)}`;else if(Array.isArray(l)){o+=`${s}${c}:
3
3
  `;for(let u of l)if(typeof u==="object")o+=`${s} -
4
4
  ${this.convertToYAML(u,i+2)}`;else o+=`${s} - ${u}
5
5
  `}else o+=`${s}${c}: ${l}
6
- `}return o}}var N={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},CA={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function eI(){return Date.now().toString()}function tI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function p(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function rI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function nI(n,i){return`${n.project.slug}-${i}`}function iI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function sI(n,i,s,o){return o??`${n}-${i}-${s}`}function oI(n,i){return`${n}-${i}-deploy`}function Kt(n,i){return`${n.project.slug}-${i}-app`}function Md(n,i){return`${n}-${i}-deployments`}function Li(n,i){return`${n}-${i}-assets`}class EA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function aI(n,i){let s=[],o=[],c=[],l=[],u=[],h=n.Resources||{},f=i.Resources||{},S=new Set([...Object.keys(h),...Object.keys(f)]);for(let v of S){let C=h[v],P=f[v];if(!C&&P)s.push({logicalId:v,action:"add",resourceType:P.Type});else if(C&&!P)o.push({logicalId:v,action:"remove",resourceType:C.Type});else if(C&&P)if(C.Type!==P.Type)l.push({logicalId:v,action:"replace",resourceType:P.Type,reason:`Type changed from ${C.Type} to ${P.Type}`});else{let E=on(C.Properties||{},P.Properties||{});if(E.length>0)if(or(C.Type,E))l.push({logicalId:v,action:"replace",resourceType:P.Type,changes:E,reason:"Property changes require replacement"});else c.push({logicalId:v,action:"update",resourceType:P.Type,changes:E});else u.push(v)}}let A=cr([...o,...l,...c]);return{added:s,removed:o,updated:c,replaced:l,unchanged:u,summary:{totalChanges:s.length+o.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:A}}}function on(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let l of c){let u=s?`${s}.${l}`:l,h=n[l],f=i[l];if(h===void 0&&f!==void 0)o.push({path:u,oldValue:void 0,newValue:f});else if(h!==void 0&&f===void 0)o.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof f)o.push({path:u,oldValue:h,newValue:f});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(f)){if(JSON.stringify(h)!==JSON.stringify(f))o.push({path:u,oldValue:h,newValue:f})}else if(!Array.isArray(h)&&!Array.isArray(f)){let S=on(h,f,u);o.push(...S)}else o.push({path:u,oldValue:h,newValue:f});else if(h!==f)o.push({path:u,oldValue:h,newValue:f})}return o}function or(n,i){let o={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!o)return!1;for(let c of i){let l=c.path.split(".")[0];if(o.has(l))return!0}return!1}function cr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function cI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
6
+ `}return o}}var N={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},PA={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function dI(){return Date.now().toString()}function lI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function p(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function uI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function gI(n,i){return`${n.project.slug}-${i}`}function pI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function mI(n,i,s,o){return o??`${n}-${i}-${s}`}function fI(n,i){return`${n}-${i}-deploy`}function Kt(n,i){return`${n.project.slug}-${i}-app`}function Ud(n,i){return`${n}-${i}-deployments`}function Li(n,i){return`${n}-${i}-assets`}class NA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function hI(n,i){let s=[],o=[],c=[],l=[],u=[],h=n.Resources||{},f=i.Resources||{},S=new Set([...Object.keys(h),...Object.keys(f)]);for(let v of S){let C=h[v],P=f[v];if(!C&&P)s.push({logicalId:v,action:"add",resourceType:P.Type});else if(C&&!P)o.push({logicalId:v,action:"remove",resourceType:C.Type});else if(C&&P)if(C.Type!==P.Type)l.push({logicalId:v,action:"replace",resourceType:P.Type,reason:`Type changed from ${C.Type} to ${P.Type}`});else{let E=on(C.Properties||{},P.Properties||{});if(E.length>0)if(or(C.Type,E))l.push({logicalId:v,action:"replace",resourceType:P.Type,changes:E,reason:"Property changes require replacement"});else c.push({logicalId:v,action:"update",resourceType:P.Type,changes:E});else u.push(v)}}let A=cr([...o,...l,...c]);return{added:s,removed:o,updated:c,replaced:l,unchanged:u,summary:{totalChanges:s.length+o.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:A}}}function on(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let l of c){let u=s?`${s}.${l}`:l,h=n[l],f=i[l];if(h===void 0&&f!==void 0)o.push({path:u,oldValue:void 0,newValue:f});else if(h!==void 0&&f===void 0)o.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof f)o.push({path:u,oldValue:h,newValue:f});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(f)){if(JSON.stringify(h)!==JSON.stringify(f))o.push({path:u,oldValue:h,newValue:f})}else if(!Array.isArray(h)&&!Array.isArray(f)){let S=on(h,f,u);o.push(...S)}else o.push({path:u,oldValue:h,newValue:f});else if(h!==f)o.push({path:u,oldValue:h,newValue:f})}return o}function or(n,i){let o={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!o)return!1;for(let c of i){let l=c.path.split(".")[0];if(o.has(l))return!0}return!1}function cr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function yI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
7
7
  `),n.summary.totalChanges===0)return i.push(`No changes detected.
8
8
  `),i.join(`
9
9
  `);if(i.push(`Total changes: ${n.summary.totalChanges}`),i.push(`Requires replacement: ${n.summary.requiresReplacement?"Yes":"No"}
10
10
  `),n.summary.dangerousChanges.length>0){i.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let s of n.summary.dangerousChanges)i.push(` • ${s}`);i.push("")}if(n.added.length>0){i.push(`✅ Resources to Add (${n.added.length}):`);for(let s of n.added)i.push(` + ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.removed.length>0){i.push(`❌ Resources to Remove (${n.removed.length}):`);for(let s of n.removed)i.push(` - ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.replaced.length>0){i.push(`\uD83D\uDD04 Resources to Replace (${n.replaced.length}):`);for(let s of n.replaced){if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.reason)i.push(` Reason: ${s.reason}`);if(s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}}i.push("")}if(n.updated.length>0){i.push(`\uD83D\uDCDD Resources to Update (${n.updated.length}):`);for(let s of n.updated)if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}i.push("")}if(n.unchanged.length>0)i.push(`⚪ Unchanged Resources (${n.unchanged.length})`);return i.join(`
11
- `)}import{existsSync as _e,readdirSync as lr}from"node:fs";import{join as Ce}from"node:path";class Pe{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:f=!0,intelligentTiering:S=!1,cors:A,lifecycleRules:v}=n,C=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),P=t(C),E={Type:"AWS::S3::Bucket",Properties:{BucketName:C}};if(f)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(A&&A.length>0)E.Properties.CorsConfiguration={CorsRules:A.map((D)=>({AllowedOrigins:D.allowedOrigins,AllowedMethods:D.allowedMethods,AllowedHeaders:D.allowedHeaders,MaxAge:D.maxAge}))};if(v&&v.length>0)E.Properties.LifecycleConfiguration={Rules:v.map((D)=>({Id:D.id,Status:D.enabled?"Enabled":"Disabled",ExpirationInDays:D.expirationDays,Transitions:D.transitions?.map((x)=>({TransitionInDays:x.days,StorageClass:x.storageClass}))}))};if(S&&v){let D={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:D.id,Status:"Enabled",Transitions:D.transitions?.map((x)=>({TransitionInDays:x.days,StorageClass:x.storageClass}))})}let I;if(l)I={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(P),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(P,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:I,logicalId:P}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:f=!1,moveToColdStorageAfterDays:S}=n,A=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),v=t(A),C={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:A}},P=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(P),I={Type:"AWS::IAM::Role",Properties:{RoleName:P,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"]}},D=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),x=t(D),O={DeleteAfterDays:l};if(S&&S<l)O.MoveToColdStorageAfterDays=S;let w={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:D,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:N.Ref(v),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:O,EnableContinuousBackup:f}]}}},B=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),_=t(B),K=c.map((J)=>N.GetAtt(J,"Arn")),Z={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:N.Ref(x),BackupSelection:{SelectionName:B,IamRoleArn:N.GetAtt(E,"Arn"),Resources:K}}};return{vault:C,plan:w,selection:Z,role:I,vaultLogicalId:v,planLogicalId:x,selectionLogicalId:_,roleLogicalId:E}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:N.Join("",[N.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":N.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=Ce(i,o);if(_e(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=Ce(c,u);if(_e(h))try{if(lr(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=Pe.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=Pe.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:_e(Ce(i,o)),path:Ce(i,o)},docs:{exists:_e(Ce(i,c)),path:Ce(i,c)},private:{exists:_e(Ce(i,l)),path:Ce(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=Pe.checkSourcePaths({projectRoot:c,paths:l}),h={},f={web:!1,docs:!1,private:!1},S=Pe.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,f.web=!0,u.docs.exists){let A=Pe.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[A.logicalId]=A.bucket,A.bucketPolicy)h[`${A.logicalId}Policy`]=A.bucketPolicy;f.docs=!0}if(u.private.exists){let A=Pe.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[A.logicalId]=A.bucket,f.private=!0}return{resources:h,created:f,sourcePaths:u}}}class ze{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:f,tags:S}=n,A=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),v=t(A),C={Type:"AWS::ECR::Repository",Properties:{RepositoryName:A,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(f)C.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(f))};if(S)C.Properties.Tags=Object.entries(S).map(([P,E])=>({Key:P,Value:E}));return{repository:C,logicalId:v}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:f=[],runCommand:S}=n,A=["app","config",...c],v=S||`bun run ${s}`,C=`# Multi-stage build for Bun application
11
+ `)}import{existsSync as Ge,readdirSync as lr}from"node:fs";import{join as Ae}from"node:path";class De{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:f=!0,intelligentTiering:S=!1,cors:A,lifecycleRules:v}=n,C=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),P=t(C),E={Type:"AWS::S3::Bucket",Properties:{BucketName:C}};if(f)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(A&&A.length>0)E.Properties.CorsConfiguration={CorsRules:A.map((D)=>({AllowedOrigins:D.allowedOrigins,AllowedMethods:D.allowedMethods,AllowedHeaders:D.allowedHeaders,MaxAge:D.maxAge}))};if(v&&v.length>0)E.Properties.LifecycleConfiguration={Rules:v.map((D)=>({Id:D.id,Status:D.enabled?"Enabled":"Disabled",ExpirationInDays:D.expirationDays,Transitions:D.transitions?.map((x)=>({TransitionInDays:x.days,StorageClass:x.storageClass}))}))};if(S&&v){let D={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:D.id,Status:"Enabled",Transitions:D.transitions?.map((x)=>({TransitionInDays:x.days,StorageClass:x.storageClass}))})}let I;if(l)I={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(P),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(P,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:I,logicalId:P}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:f=!1,moveToColdStorageAfterDays:S}=n,A=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),v=t(A),C={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:A}},P=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(P),I={Type:"AWS::IAM::Role",Properties:{RoleName:P,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"]}},D=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),x=t(D),O={DeleteAfterDays:l};if(S&&S<l)O.MoveToColdStorageAfterDays=S;let w={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:D,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:N.Ref(v),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:O,EnableContinuousBackup:f}]}}},B=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),_=t(B),W=c.map((J)=>N.GetAtt(J,"Arn")),Z={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:N.Ref(x),BackupSelection:{SelectionName:B,IamRoleArn:N.GetAtt(E,"Arn"),Resources:W}}};return{vault:C,plan:w,selection:Z,role:I,vaultLogicalId:v,planLogicalId:x,selectionLogicalId:_,roleLogicalId:E}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:N.Join("",[N.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":N.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=Ae(i,o);if(Ge(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=Ae(c,u);if(Ge(h))try{if(lr(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=De.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=De.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:Ge(Ae(i,o)),path:Ae(i,o)},docs:{exists:Ge(Ae(i,c)),path:Ae(i,c)},private:{exists:Ge(Ae(i,l)),path:Ae(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=De.checkSourcePaths({projectRoot:c,paths:l}),h={},f={web:!1,docs:!1,private:!1},S=De.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,f.web=!0,u.docs.exists){let A=De.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[A.logicalId]=A.bucket,A.bucketPolicy)h[`${A.logicalId}Policy`]=A.bucketPolicy;f.docs=!0}if(u.private.exists){let A=De.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[A.logicalId]=A.bucket,f.private=!0}return{resources:h,created:f,sourcePaths:u}}}class je{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:f,tags:S}=n,A=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),v=t(A),C={Type:"AWS::ECR::Repository",Properties:{RepositoryName:A,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(f)C.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(je.generateLifecyclePolicy(f))};if(S)C.Properties.Tags=Object.entries(S).map(([P,E])=>({Key:P,Value:E}));return{repository:C,logicalId:v}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(je.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:f=[],runCommand:S}=n,A=["app","config",...c],v=S||`bun run ${s}`,C=`# Multi-stage build for Bun application
12
12
  # Generated by ts-cloud
13
13
 
14
14
  # Builder stage
@@ -62,7 +62,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
62
62
 
63
63
  # Start application
64
64
  CMD ["bun", "run", "${s}"]
65
- `,C}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:f=!1}=n,S=`${i}:${s}`,A=[s,...l],v=`docker build -f ${o} -t ${S}`;if(h)v+=` --platform ${h}`;if(f)v+=" --no-cache";for(let[E,I]of Object.entries(u))v+=` --build-arg ${E}=${I}`;v+=` ${c}`;let C=A.slice(1).map((E)=>`docker tag ${S} ${i}:${E}`),P=A.map((E)=>`docker push ${i}:${E}`);return{build:v,tag:C,push:P,all:[v,...C,...P]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=ze.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
65
+ `,C}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:f=!1}=n,S=`${i}:${s}`,A=[s,...l],v=`docker build -f ${o} -t ${S}`;if(h)v+=` --platform ${h}`;if(f)v+=" --no-cache";for(let[E,I]of Object.entries(u))v+=` --build-arg ${E}=${I}`;v+=` ${c}`;let C=A.slice(1).map((E)=>`docker tag ${S} ${i}:${E}`),P=A.map((E)=>`docker push ${i}:${E}`);return{build:v,tag:C,push:P,all:[v,...C,...P]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=je.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
66
66
  set -e
67
67
 
68
68
  # Configuration
@@ -73,7 +73,7 @@ IMAGE_URI="${i}"
73
73
  DOCKERFILE="${n.dockerfilePath||"Dockerfile"}"
74
74
 
75
75
  echo "=== ECR Login ==="
76
- ${ze.generateEcrLoginCommand(n.region,n.accountId)}
76
+ ${je.generateEcrLoginCommand(n.region,n.accountId)}
77
77
 
78
78
  echo "=== Building Image ==="
79
79
  docker build -f $DOCKERFILE -t $IMAGE_URI:${o} --platform linux/amd64 .
@@ -91,7 +91,7 @@ echo "Image: $IMAGE_URI:${o}"
91
91
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
92
92
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...n.ecsCluster&&n.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${n.ecsCluster} --service ${n.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
93
93
  ${JSON.stringify(i,null,2).replace(/"/g,"").replace(/,\n/g,`
94
- `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>ze.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var Fd=[400,403,404,416,429,500,502,503,504],Up=[500,502,503,504],Qp=["GET","HEAD","OPTIONS"],dI="-failover-group",Hp=["default","media-quality-based"],Gp={min:1,max:3},Vp={min:1,max:10};function So(n){if(n===void 0)return[...Up];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${Fd.join(", ")}). Omit it to use the default ${Up.join(", ")}.`);let i=n.filter((s)=>!Fd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${Fd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Ud(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=So(n.statusCodes);return cn(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function cn(n,i="the origin group"){if(n===void 0)return;if(!Hp.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Hp.join(", ")}.`)}function et(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function te(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)et(n.connectionAttempts,Gp,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)et(n.connectionTimeout,Vp,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Kr(n){return{Quantity:1,Items:[Ud(n)]}}function yt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!Qp.includes(c.toUpperCase()));if(o.length>0)throw Error(`CloudFront origin failover: ${i} allows ${o.join(", ")}, but a cache behavior that targets an origin group may only allow ${Qp.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Io(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function Ve(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function be(n){return typeof n==="string"?n:void 0}var ur=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function St(n,i="the distribution"){let s=Ve(n.Origins),o=new Set(s.map((A)=>be(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[be(A.Id)??"",A.DomainName])),l=s.some((A)=>be(A.Id)===void 0);for(let A of s){let v=be(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)et(A.ConnectionAttempts,Gp,`${i} origin "${v}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)et(A.ConnectionTimeout,Vp,`${i} origin "${v}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=Ve(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let f=new Set;for(let A of h){let v=be(A.Id);if(A.Id===void 0||A.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let C=`${i} origin group "${v??"(intrinsic id)"}"`;if(v){if(f.has(v))throw Error(`CloudFront origin failover: ${i} declares origin group "${v}" twice.`);if(o.has(v))throw Error(`CloudFront origin failover: ${C} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);f.add(v)}let P=A.Members,E=Ve(P);if(E.length!==2||P?.Quantity!==void 0&&P.Quantity!==E.length)throw Error(`CloudFront origin failover: ${C} must have exactly 2 members (a primary and a secondary), it has ${E.length}${P?.Quantity!==void 0&&P.Quantity!==E.length?` with Quantity ${P.Quantity}`:""}.`);let I=E.map((O)=>be(O.OriginId));for(let O of I)if(O&&!o.has(O)&&!l)throw Error(`CloudFront origin failover: ${C} lists member "${O}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(I[0]&&I[0]===I[1])throw Error(`CloudFront origin failover: ${C} lists "${I[0]}" as both primary and secondary.`);let D=A.FailoverCriteria?.StatusCodes,x=Ve(D);if(So(x),D?.Quantity!==void 0&&D.Quantity!==x.length)throw Error(`CloudFront origin failover: ${C} FailoverCriteria.StatusCodes.Quantity is ${D.Quantity} but it lists ${x.length} code(s).`);if(cn(A.SelectionCriteria,C),A.SelectionCriteria==="media-quality-based")for(let O of I){let w=O?be(c.get(O)):void 0;if(w&&!ur.test(w))throw Error(`CloudFront origin failover: ${C} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${O}" is ${w}. Use 'default'.`)}}let S=[];if(n.DefaultCacheBehavior)S.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let A of Ve(n.CacheBehaviors))S.push({behavior:A,name:`the cache behavior for ${JSON.stringify(A.PathPattern)}`});for(let{behavior:A,name:v}of S){let C=be(A.TargetOriginId);if(!C)continue;if(f.has(C))yt(A.AllowedMethods??["GET","HEAD"],`${v} of ${i} (origin group "${C}")`);else if(!o.has(C)&&!l&&h.every((P)=>be(P.Id)!==void 0))throw Error(`CloudFront: ${v} of ${i} targets "${C}", which is neither an origin nor an origin group of this distribution.`)}}class fe{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:f,http3:S=!1,comment:A,failoverOrigin:v}=n,C=r({slug:i,environment:s,resourceType:"cdn"}),P=t(C),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...te(o,"the CDN origin")},I;if(o.type==="s3"){let x=`${P}OAC`;I={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${C}-oac`,Description:`Origin Access Control for ${C}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=N.Ref(x)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let D={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:A||`CDN for ${C}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)D.Properties.DistributionConfig.Aliases=[c],D.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)D.Properties.DistributionConfig.CustomErrorResponses=u.map((x)=>({ErrorCode:x.errorCode,ResponseCode:x.responseCode,ResponsePagePath:x.responsePagePath}));if(f&&f.length>0)D.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=f.map((x)=>({EventType:x.event,LambdaFunctionARN:x.functionArn}));if(v)fe.addOriginFailover(D,v);return{distribution:D,originAccessControl:I,logicalId:P}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(yt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((A)=>A.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=Ud({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(Io(i.domainName)?"s3":"custom"),f={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...te(i,"the failover origin")},S=te(i.primary,"the primary origin");if(Object.keys(S).length>0){let A=s.Origins.find((v)=>v.Id===c);if(A)Object.assign(A,S)}if(h==="s3"){let A=s.Origins.find((v)=>v.Id===c);if(f.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)f.OriginAccessControlId=A.OriginAccessControlId}else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(f),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,St(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return fe.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},f=`
94
+ `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>je.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var Qd=[400,403,404,416,429,500,502,503,504],qp=[500,502,503,504],jp=["GET","HEAD","OPTIONS"],SI="-failover-group",zp=["default","media-quality-based"],Kp={min:1,max:3},Wp={min:1,max:10};function So(n){if(n===void 0)return[...qp];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${Qd.join(", ")}). Omit it to use the default ${qp.join(", ")}.`);let i=n.filter((s)=>!Qd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${Qd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Hd(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=So(n.statusCodes);return cn(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function cn(n,i="the origin group"){if(n===void 0)return;if(!zp.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${zp.join(", ")}.`)}function et(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function te(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)et(n.connectionAttempts,Kp,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)et(n.connectionTimeout,Wp,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Kr(n){return{Quantity:1,Items:[Hd(n)]}}function yt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!jp.includes(c.toUpperCase()));if(o.length>0)throw Error(`CloudFront origin failover: ${i} allows ${o.join(", ")}, but a cache behavior that targets an origin group may only allow ${jp.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Io(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function _e(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function he(n){return typeof n==="string"?n:void 0}var ur=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function St(n,i="the distribution"){let s=_e(n.Origins),o=new Set(s.map((A)=>he(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[he(A.Id)??"",A.DomainName])),l=s.some((A)=>he(A.Id)===void 0);for(let A of s){let v=he(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)et(A.ConnectionAttempts,Kp,`${i} origin "${v}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)et(A.ConnectionTimeout,Wp,`${i} origin "${v}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=_e(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let f=new Set;for(let A of h){let v=he(A.Id);if(A.Id===void 0||A.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let C=`${i} origin group "${v??"(intrinsic id)"}"`;if(v){if(f.has(v))throw Error(`CloudFront origin failover: ${i} declares origin group "${v}" twice.`);if(o.has(v))throw Error(`CloudFront origin failover: ${C} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);f.add(v)}let P=A.Members,E=_e(P);if(E.length!==2||P?.Quantity!==void 0&&P.Quantity!==E.length)throw Error(`CloudFront origin failover: ${C} must have exactly 2 members (a primary and a secondary), it has ${E.length}${P?.Quantity!==void 0&&P.Quantity!==E.length?` with Quantity ${P.Quantity}`:""}.`);let I=E.map((O)=>he(O.OriginId));for(let O of I)if(O&&!o.has(O)&&!l)throw Error(`CloudFront origin failover: ${C} lists member "${O}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(I[0]&&I[0]===I[1])throw Error(`CloudFront origin failover: ${C} lists "${I[0]}" as both primary and secondary.`);let D=A.FailoverCriteria?.StatusCodes,x=_e(D);if(So(x),D?.Quantity!==void 0&&D.Quantity!==x.length)throw Error(`CloudFront origin failover: ${C} FailoverCriteria.StatusCodes.Quantity is ${D.Quantity} but it lists ${x.length} code(s).`);if(cn(A.SelectionCriteria,C),A.SelectionCriteria==="media-quality-based")for(let O of I){let w=O?he(c.get(O)):void 0;if(w&&!ur.test(w))throw Error(`CloudFront origin failover: ${C} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${O}" is ${w}. Use 'default'.`)}}let S=[];if(n.DefaultCacheBehavior)S.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let A of _e(n.CacheBehaviors))S.push({behavior:A,name:`the cache behavior for ${JSON.stringify(A.PathPattern)}`});for(let{behavior:A,name:v}of S){let C=he(A.TargetOriginId);if(!C)continue;if(f.has(C))yt(A.AllowedMethods??["GET","HEAD"],`${v} of ${i} (origin group "${C}")`);else if(!o.has(C)&&!l&&h.every((P)=>he(P.Id)!==void 0))throw Error(`CloudFront: ${v} of ${i} targets "${C}", which is neither an origin nor an origin group of this distribution.`)}}class fe{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:f,http3:S=!1,comment:A,failoverOrigin:v}=n,C=r({slug:i,environment:s,resourceType:"cdn"}),P=t(C),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...te(o,"the CDN origin")},I;if(o.type==="s3"){let x=`${P}OAC`;I={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${C}-oac`,Description:`Origin Access Control for ${C}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=N.Ref(x)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let D={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:A||`CDN for ${C}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)D.Properties.DistributionConfig.Aliases=[c],D.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)D.Properties.DistributionConfig.CustomErrorResponses=u.map((x)=>({ErrorCode:x.errorCode,ResponseCode:x.responseCode,ResponsePagePath:x.responsePagePath}));if(f&&f.length>0)D.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=f.map((x)=>({EventType:x.event,LambdaFunctionARN:x.functionArn}));if(v)fe.addOriginFailover(D,v);return{distribution:D,originAccessControl:I,logicalId:P}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(yt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((A)=>A.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=Hd({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(Io(i.domainName)?"s3":"custom"),f={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...te(i,"the failover origin")},S=te(i.primary,"the primary origin");if(Object.keys(S).length>0){let A=s.Origins.find((v)=>v.Id===c);if(A)Object.assign(A,S)}if(h==="s3"){let A=s.Origins.find((v)=>v.Id===c);if(f.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)f.OriginAccessControlId=A.OriginAccessControlId}else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(f),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,St(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return fe.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},f=`
95
95
  'use strict';
96
96
 
97
97
  exports.handler = async (event) => {
@@ -197,7 +197,7 @@ exports.handler = async (event) => {
197
197
 
198
198
  return request;
199
199
  };
200
- `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:f=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:fe.Config.allowedMethods(c),CachedMethods:fe.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:f,Cookies:fe.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=fe.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=fe.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=fe.Config.cookies(i.cookies,i.allowedCookies)}return n}}var vA=[403,404,500,502,503,504],Qd="TsCloud::StorageFailover",bo="AllowCloudFrontFailoverRead",dr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,mr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function qp(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!dr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!mr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:So(i.statusCodes??vA),primaryConnection:te(i,`${c}.failover`)}}function jp(n,i){return`${n}.s3.${i}.amazonaws.com`}function zp(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Kp(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function Hd(n){return{Sid:bo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function lI(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[Qd];return Array.isArray(s)?s:[]}class Q{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,f=t(`record-${o.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)S.Properties.HostedZoneId=i;else if(s)S.Properties.HostedZoneName=s;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:f}}static createCloudFrontAlias(n,i,s){return Q.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return Q.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return Q.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return Q.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return Q.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return Q.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return Q.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return Q.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return Q.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class b{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),f=t(`${h}-${i.replace(/\./g,"")}`),S=[i];for(let v of s)if(v==="*")S.push(`*.${i}`);else S.push(`${v}.${i}`);let A={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)A.Properties.DomainValidationOptions=S.map((v)=>({DomainName:v,HostedZoneId:u}));return{certificate:A,logicalId:f}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),f={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:N.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:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:f,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},A=t(`${u}-alias`),v={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:N.Ref(h)}};return{key:S,alias:v,logicalId:h,aliasId:A}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:N.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return b.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return b.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:f}=b.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(h=b.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...b.ManagedRuleGroups.AmazonIpReputation}),h=b.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...b.ManagedRuleGroups.AnonymousIpList}),h=b.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...b.ManagedRuleGroups.CoreRuleSet}),h=b.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...b.ManagedRuleGroups.KnownBadInputs}),h=b.addManagedRules(h,{name:"AWSSQLi",priority:S++,...b.ManagedRuleGroups.SqlDatabase}),c)h=b.addManagedRules(h,{name:"AWSBotControl",priority:S++,...b.ManagedRuleGroups.BotControl});if(l)h=b.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:f}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:f,volumeSize:S=20,volumeType:A="gp3",encrypted:v=!0}=n,C=r({slug:i,environment:s,resourceType:"ec2"}),P=t(C),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(f)E.Properties.UserData=N.Base64(f);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:A,Encrypted:v,DeleteOnTermination:!0}}],{instance:E,logicalId:P}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),f=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)S.Properties.VpcId=o;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,SourceSecurityGroupId:A.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,DestinationSecurityGroupId:A.sourceSecurityGroupId}));return{securityGroup:S,logicalId:f}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),f=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:f}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:f=30,healthCheckTimeout:S=5,healthyThreshold:A=2,unhealthyThreshold:v=3}=n,C=r({slug:i,environment:s,resourceType:"tg"}),P=t(C);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:C,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:f,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:A,UnhealthyThresholdCount:v,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}},logicalId:P}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:f={},secrets:S=[],healthCheck:A,logGroup:v,subnets:C,securityGroups:P,targetGroupArn:E}=n,{cluster:I,logicalId:D}=a.createEcsCluster(i,s),x=r({slug:i,environment:s,resourceType:"fargate"}),O=t(`${x}-execution-role`),w={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"]}},B=t(`${x}-task-role`),_={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},K=t(`${x}-task`),Z={Type:"AWS::ECS::TaskDefinition",Properties:{Family:x,TaskRoleArn:N.GetAtt(B,"Arn"),ExecutionRoleArn:N.GetAtt(O,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(f).map(([X,ae])=>({Name:X,Value:ae})),Secrets:S.map((X)=>({Name:X.name,ValueFrom:X.valueFrom}))}],Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}};if(A)Z.Properties.ContainerDefinitions[0].HealthCheck={Command:A.command,Interval:A.interval||30,Timeout:A.timeout||5,Retries:A.retries||3,StartPeriod:60};if(v)Z.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":v,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let J=t(`${x}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:x,Cluster:N.Ref(D),TaskDefinition:N.Ref(K),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:C,SecurityGroups:P,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:I,taskDefinition:Z,service:Y,taskRole:_,executionRole:w,clusterLogicalId:D,taskDefinitionLogicalId:K,serviceLogicalId:J,taskRoleLogicalId:B,executionRoleLogicalId:O}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:f={},vpcConfig:S}=n,A=r({slug:i,environment:s,resourceType:"lambda"}),v=t(A),C=t(`${A}-role`),P={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(S)P.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:A,Runtime:o,Role:N.GetAtt(C,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(f).length>0)E.Properties.Environment={Variables:f};if(S)E.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:E,role:P,logicalId:v,roleLogicalId:C}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
200
+ `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:f=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:fe.Config.allowedMethods(c),CachedMethods:fe.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:f,Cookies:fe.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=fe.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=fe.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=fe.Config.cookies(i.cookies,i.allowedCookies)}return n}}var kA=[403,404,500,502,503,504],Gd="TsCloud::StorageFailover",bo="AllowCloudFrontFailoverRead",dr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,mr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function Jp(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!dr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!mr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:So(i.statusCodes??kA),primaryConnection:te(i,`${c}.failover`)}}function Xp(n,i){return`${n}.s3.${i}.amazonaws.com`}function Yp(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Zp(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function Vd(n){return{Sid:bo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function II(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[Gd];return Array.isArray(s)?s:[]}class Q{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,f=t(`record-${o.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)S.Properties.HostedZoneId=i;else if(s)S.Properties.HostedZoneName=s;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:f}}static createCloudFrontAlias(n,i,s){return Q.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return Q.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return Q.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return Q.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return Q.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return Q.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return Q.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return Q.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return Q.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return Q.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class b{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),f=t(`${h}-${i.replace(/\./g,"")}`),S=[i];for(let v of s)if(v==="*")S.push(`*.${i}`);else S.push(`${v}.${i}`);let A={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)A.Properties.DomainValidationOptions=S.map((v)=>({DomainName:v,HostedZoneId:u}));return{certificate:A,logicalId:f}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),f={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:N.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:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:f,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},A=t(`${u}-alias`),v={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:N.Ref(h)}};return{key:S,alias:v,logicalId:h,aliasId:A}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:N.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return b.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return b.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:f}=b.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(h=b.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...b.ManagedRuleGroups.AmazonIpReputation}),h=b.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...b.ManagedRuleGroups.AnonymousIpList}),h=b.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...b.ManagedRuleGroups.CoreRuleSet}),h=b.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...b.ManagedRuleGroups.KnownBadInputs}),h=b.addManagedRules(h,{name:"AWSSQLi",priority:S++,...b.ManagedRuleGroups.SqlDatabase}),c)h=b.addManagedRules(h,{name:"AWSBotControl",priority:S++,...b.ManagedRuleGroups.BotControl});if(l)h=b.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:f}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function BA(n){let i=n.split(".")[0]??"";return i==="a1"||/^[a-z]+\d+g[a-z]*$/.test(i)}function xA(n="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${BA(n)?"arm64":"x86_64"}`}function em(n="t3.micro"){return`{{resolve:ssm:${xA(n)}}}`}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c=em(o),keyName:l,securityGroupIds:u,subnetId:h,userData:f,volumeSize:S=20,volumeType:A="gp3",encrypted:v=!0}=n,C=r({slug:i,environment:s,resourceType:"ec2"}),P=t(C),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(f)E.Properties.UserData=N.Base64(f);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:A,Encrypted:v,DeleteOnTermination:!0}}],{instance:E,logicalId:P}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),f=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)S.Properties.VpcId=o;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,SourceSecurityGroupId:A.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,DestinationSecurityGroupId:A.sourceSecurityGroupId}));return{securityGroup:S,logicalId:f}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),f=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:f}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:f=30,healthCheckTimeout:S=5,healthyThreshold:A=2,unhealthyThreshold:v=3}=n,C=r({slug:i,environment:s,resourceType:"tg"}),P=t(C);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:C,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:f,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:A,UnhealthyThresholdCount:v,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}},logicalId:P}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:f={},secrets:S=[],healthCheck:A,logGroup:v,subnets:C,securityGroups:P,targetGroupArn:E}=n,{cluster:I,logicalId:D}=a.createEcsCluster(i,s),x=r({slug:i,environment:s,resourceType:"fargate"}),O=t(`${x}-execution-role`),w={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"]}},B=t(`${x}-task-role`),_={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},W=t(`${x}-task`),Z={Type:"AWS::ECS::TaskDefinition",Properties:{Family:x,TaskRoleArn:N.GetAtt(B,"Arn"),ExecutionRoleArn:N.GetAtt(O,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(f).map(([X,ae])=>({Name:X,Value:ae})),Secrets:S.map((X)=>({Name:X.name,ValueFrom:X.valueFrom}))}],Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}};if(A)Z.Properties.ContainerDefinitions[0].HealthCheck={Command:A.command,Interval:A.interval||30,Timeout:A.timeout||5,Retries:A.retries||3,StartPeriod:60};if(v)Z.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":v,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let J=t(`${x}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:x,Cluster:N.Ref(D),TaskDefinition:N.Ref(W),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:C,SecurityGroups:P,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:I,taskDefinition:Z,service:Y,taskRole:_,executionRole:w,clusterLogicalId:D,taskDefinitionLogicalId:W,serviceLogicalId:J,taskRoleLogicalId:B,executionRoleLogicalId:O}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:f={},vpcConfig:S}=n,A=r({slug:i,environment:s,resourceType:"lambda"}),v=t(A),C=t(`${A}-role`),P={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(S)P.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:A,Runtime:o,Role:N.GetAtt(C,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(f).length>0)E.Properties.Environment={Variables:f};if(S)E.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:E,role:P,logicalId:v,roleLogicalId:C}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
201
201
  `);return`#!/bin/bash
202
202
  # Update system
203
203
  yum update -y
@@ -298,43 +298,20 @@ systemctl enable caddy
298
298
  systemctl start caddy
299
299
 
300
300
  echo "Bun server setup complete!"
301
- `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:f=20,volumeType:S="gp3",encrypted:A=!0,iamInstanceProfile:v}=n,C=r({slug:i,environment:s,resourceType:"launch-config"}),P=t(C),E={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:f,VolumeType:S,Encrypted:A,DeleteOnTermination:!0}}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroups=u;if(h)E.Properties.UserData=N.Base64(h);if(v)E.Properties.IamInstanceProfile=v;return{launchConfiguration:E,logicalId:P}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:f,healthCheckType:S="EC2",healthCheckGracePeriod:A=300,cooldown:v=300,tags:C={}}=n,P=r({slug:i,environment:s,resourceType:"asg"}),E=t(P),I={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:P,LaunchConfigurationName:o,MinSize:c,MaxSize:l,HealthCheckType:S,HealthCheckGracePeriod:A,Cooldown:v,Tags:[{Key:"Name",Value:P,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(C).map(([D,x])=>({Key:D,Value:x,PropagateAtLaunch:!0}))]}};if(u!==void 0)I.Properties.DesiredCapacity=u;if(h)I.Properties.VPCZoneIdentifier=h;if(f)I.Properties.TargetGroupARNs=f;return I.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:I,logicalId:E}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=n,h=r({slug:i,environment:s,resourceType:"scaling-policy"}),f=t(h),S={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")S.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:S,logicalId:f}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h="ami-0f3caa1cf4417e51b",allowedCidrs:f=["0.0.0.0/0"],mountEfs:S}=n,A=r({slug:i,environment:s,resourceType:"jumpbox"}),v=t(`${A}-sg`),C={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${A}-sg`,GroupDescription:`Security group for ${A} JumpBox SSH access`,VpcId:o,SecurityGroupIngress:f.map((_)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:_,Description:`SSH access from ${_}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${A}-sg`},{Key:"Environment",Value:s}]}},P=t(`${A}-role`),E={Type:"AWS::IAM::Role",Properties:{RoleName:`${A}-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:S?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},I=t(`${A}-profile`),D={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${A}-profile`,Roles:[N.Ref(P)]}},x=`#!/bin/bash
302
- yum update -y
303
- yum install -y amazon-efs-utils nfs-utils jq curl wget htop
304
- `;if(S){let _=S.mountPath||"/mnt/efs";x+=`
301
+ `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:f=20,volumeType:S="gp3",encrypted:A=!0,iamInstanceProfile:v}=n,C=r({slug:i,environment:s,resourceType:"launch-config"}),P=t(C),E={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:f,VolumeType:S,Encrypted:A,DeleteOnTermination:!0}}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroups=u;if(h)E.Properties.UserData=N.Base64(h);if(v)E.Properties.IamInstanceProfile=v;return{launchConfiguration:E,logicalId:P}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:f,healthCheckType:S="EC2",healthCheckGracePeriod:A=300,cooldown:v=300,tags:C={}}=n,P=r({slug:i,environment:s,resourceType:"asg"}),E=t(P),I={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:P,LaunchConfigurationName:o,MinSize:c,MaxSize:l,HealthCheckType:S,HealthCheckGracePeriod:A,Cooldown:v,Tags:[{Key:"Name",Value:P,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(C).map(([D,x])=>({Key:D,Value:x,PropagateAtLaunch:!0}))]}};if(u!==void 0)I.Properties.DesiredCapacity=u;if(h)I.Properties.VPCZoneIdentifier=h;if(f)I.Properties.TargetGroupARNs=f;return I.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:I,logicalId:E}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=n,h=r({slug:i,environment:s,resourceType:"scaling-policy"}),f=t(h),S={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")S.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:S,logicalId:f}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h=em(u),mountEfs:f,databaseTools:S=!1}=n,A=n.allowedCidrs??(l?["0.0.0.0/0"]:[]),v=r({slug:i,environment:s,resourceType:"jumpbox"}),C=t(`${v}-sg`),P={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${v}-sg`,GroupDescription:`Security group for ${v} JumpBox access`,VpcId:o,SecurityGroupIngress:A.map((W)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:W,Description:`SSH access from ${W}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${v}-sg`},{Key:"Environment",Value:s}]}},E=t(`${v}-role`),I={Type:"AWS::IAM::Role",Properties:{RoleName:`${v}-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:f?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},D=t(`${v}-profile`),x={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${v}-profile`,Roles:[N.Ref(E)]}},O=`#!/bin/bash
302
+ dnf install -y amazon-efs-utils nfs-utils jq wget htop
303
+ `;if(S)O+=`
304
+ # Database clients: psql, mysql (MariaDB), redis-cli
305
+ dnf install -y postgresql16 mariadb105 redis6
306
+ `;if(f){let W=f.mountPath||"/mnt/efs";O+=`
305
307
  # Mount EFS
306
- mkdir -p ${_}
307
- mount -t efs ${S.fileSystemId}:/ ${_}
308
- echo "${S.fileSystemId}:/ ${_} efs defaults,_netdev 0 0" >> /etc/fstab
309
- `}let O=t(A),w={Type:"AWS::EC2::Instance",DependsOn:[I],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[N.Ref(v)],IamInstanceProfile:N.Ref(I),UserData:N.Base64(x),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},B={[v]:C,[P]:E,[I]:D,[O]:w};return{instance:w,securityGroup:C,instanceProfile:D,instanceRole:E,instanceLogicalId:O,securityGroupLogicalId:v,instanceProfileLogicalId:I,instanceRoleLogicalId:P,resources:B}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>{let i=a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs}),s=`#!/bin/bash
310
- yum update -y
311
- yum install -y amazon-efs-utils nfs-utils jq curl wget htop
312
-
313
- # Install PostgreSQL client
314
- amazon-linux-extras install postgresql14 -y
315
-
316
- # Install MySQL client
317
- yum install -y mysql
318
-
319
- # Install Redis CLI
320
- yum install -y redis
321
-
322
- echo "Database tools installed!"
323
- `;return i.instance.Properties.UserData=N.Base64(`#!/bin/bash
324
- yum update -y
325
- yum install -y amazon-efs-utils nfs-utils jq curl wget htop
326
-
327
- # Install PostgreSQL client
328
- amazon-linux-extras install postgresql14 -y
329
-
330
- # Install MySQL client
331
- yum install -y mysql
332
-
333
- # Install Redis CLI
334
- yum install -y redis
335
-
336
- echo "Database tools installed!"
337
- `),i},commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(n,i="t3")=>`${i}.${n}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(n)=>{let i={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return i[n]||i.medium},toLambdaMemory:(n)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[n]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(n)=>{let{size:i,type:s="ssd",encrypted:o=!0,iops:c,throughput:l,deleteOnTermination:u=!0}=n,f={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[s]||"gp3",S={VolumeSize:i,VolumeType:f,Encrypted:o,DeleteOnTermination:u};if((f==="io1"||f==="io2"||f==="gp3")&&c)S.Iops=c;if(f==="gp3"&&l)S.Throughput=l;return S},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(n)=>{let{maxPrice:i,spotInstanceType:s="one-time",interruptionBehavior:o="terminate",blockDurationMinutes:c}=n,l={SpotInstanceType:s,InstanceInterruptionBehavior:o};if(i)l.MaxPrice=i;if(c)l.BlockDurationMinutes=c;return{SpotOptions:l}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(n)=>{let{instanceTypes:i,baseCapacity:s=0,onDemandPercentage:o=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:l}=n,u={OnDemandBaseCapacity:s,OnDemandPercentageAboveBaseCapacity:o,SpotAllocationStrategy:c};if(l)u.SpotMaxPrice=l;let h=i.map(({size:f,weight:S})=>{let A={InstanceType:a.InstanceSize.toInstanceType(f)};if(S)A.WeightedCapacity=String(S);return A});return{MixedInstancesPolicy:{InstancesDistribution:u,LaunchTemplate:{Overrides:h}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(n)=>{let{min:i,max:s,desired:o=i,scaleUpThreshold:c=70,scaleDownThreshold:l=30,cooldownSeconds:u=300,targetMetric:h="cpu"}=n,f={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:i,maxSize:s,desiredCapacity:o,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:f[h]||f.cpu,scaleInCooldown:u,scaleOutCooldown:u}]}},forEcs:(n)=>{let{min:i,max:s,cpuTarget:o=70,memoryTarget:c}=n,l=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:o}];if(c)l.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:i,maxCapacity:s,targetTrackingPolicies:l}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(n)=>{let{path:i="/",interval:s=30,timeout:o=5,healthyThreshold:c=2,unhealthyThreshold:l=5,protocol:u="HTTP"}=n,h={HealthCheckIntervalSeconds:s,HealthCheckTimeoutSeconds:o,HealthyThresholdCount:c,UnhealthyThresholdCount:l};if(u!=="TCP")h.HealthCheckPath=i,h.HealthCheckProtocol=u;return h},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(n)=>{let{certificateArn:i,targetGroupArn:s,port:o=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=n;return{Port:o,Protocol:"HTTPS",Certificates:[{CertificateArn:i}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:s}]}},httpRedirectListener:(n=80)=>({Port:n,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(n)=>{let{handler:i,runtime:s="nodejs20.x",timeout:o=30,memorySize:c=256,environmentVariables:l,reservedConcurrency:u}=n,h={Handler:i,Runtime:s,Timeout:o,MemorySize:c};if(l)h.Environment={Variables:l};if(u)h.ReservedConcurrentExecutions=u;return h},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(n)=>{let{runtime:i="bun",runtimeVersion:s="latest",webServer:o="nginx",processManager:c="systemd",enableSsl:l=!0,sslEmail:u="admin@example.com",domain:h,appPort:f=3000,installDatabaseClients:S=!1,installRedis:A=!1,extraPackages:v=[]}=n,C=`#!/bin/bash
308
+ mkdir -p ${W}
309
+ for attempt in $(seq 1 30); do
310
+ mount -t efs -o tls \${FileSystemId}:/ ${W} && break
311
+ sleep 10
312
+ done
313
+ echo "\${FileSystemId}:/ ${W} efs _netdev,tls,nofail 0 0" >> /etc/fstab
314
+ `}let w=t(v),B={Type:"AWS::EC2::Instance",DependsOn:[D],Properties:{ImageId:h,InstanceType:u,SubnetId:c,SecurityGroupIds:[N.Ref(C)],IamInstanceProfile:N.Ref(D),UserData:f?{"Fn::Base64":N.Sub(O,{FileSystemId:f.fileSystemId})}:N.Base64(O),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}};if(l)B.Properties.KeyName=l;let _={[C]:P,[E]:I,[D]:x,[w]:B};return{instance:B,securityGroup:P,instanceProfile:x,instanceRole:I,instanceLogicalId:w,securityGroupLogicalId:C,instanceProfileLogicalId:D,instanceRoleLogicalId:E,resources:_}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,databaseTools:!0}),commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(n,i="t3")=>`${i}.${n}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(n)=>{let i={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return i[n]||i.medium},toLambdaMemory:(n)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[n]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(n)=>{let{size:i,type:s="ssd",encrypted:o=!0,iops:c,throughput:l,deleteOnTermination:u=!0}=n,f={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[s]||"gp3",S={VolumeSize:i,VolumeType:f,Encrypted:o,DeleteOnTermination:u};if((f==="io1"||f==="io2"||f==="gp3")&&c)S.Iops=c;if(f==="gp3"&&l)S.Throughput=l;return S},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(n)=>{let{maxPrice:i,spotInstanceType:s="one-time",interruptionBehavior:o="terminate",blockDurationMinutes:c}=n,l={SpotInstanceType:s,InstanceInterruptionBehavior:o};if(i)l.MaxPrice=i;if(c)l.BlockDurationMinutes=c;return{SpotOptions:l}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(n)=>{let{instanceTypes:i,baseCapacity:s=0,onDemandPercentage:o=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:l}=n,u={OnDemandBaseCapacity:s,OnDemandPercentageAboveBaseCapacity:o,SpotAllocationStrategy:c};if(l)u.SpotMaxPrice=l;let h=i.map(({size:f,weight:S})=>{let A={InstanceType:a.InstanceSize.toInstanceType(f)};if(S)A.WeightedCapacity=String(S);return A});return{MixedInstancesPolicy:{InstancesDistribution:u,LaunchTemplate:{Overrides:h}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(n)=>{let{min:i,max:s,desired:o=i,scaleUpThreshold:c=70,scaleDownThreshold:l=30,cooldownSeconds:u=300,targetMetric:h="cpu"}=n,f={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:i,maxSize:s,desiredCapacity:o,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:f[h]||f.cpu,scaleInCooldown:u,scaleOutCooldown:u}]}},forEcs:(n)=>{let{min:i,max:s,cpuTarget:o=70,memoryTarget:c}=n,l=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:o}];if(c)l.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:i,maxCapacity:s,targetTrackingPolicies:l}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(n)=>{let{path:i="/",interval:s=30,timeout:o=5,healthyThreshold:c=2,unhealthyThreshold:l=5,protocol:u="HTTP"}=n,h={HealthCheckIntervalSeconds:s,HealthCheckTimeoutSeconds:o,HealthyThresholdCount:c,UnhealthyThresholdCount:l};if(u!=="TCP")h.HealthCheckPath=i,h.HealthCheckProtocol=u;return h},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(n)=>{let{certificateArn:i,targetGroupArn:s,port:o=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=n;return{Port:o,Protocol:"HTTPS",Certificates:[{CertificateArn:i}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:s}]}},httpRedirectListener:(n=80)=>({Port:n,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(n)=>{let{handler:i,runtime:s="nodejs20.x",timeout:o=30,memorySize:c=256,environmentVariables:l,reservedConcurrency:u}=n,h={Handler:i,Runtime:s,Timeout:o,MemorySize:c};if(l)h.Environment={Variables:l};if(u)h.ReservedConcurrentExecutions=u;return h},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(n)=>{let{runtime:i="bun",runtimeVersion:s="latest",webServer:o="nginx",processManager:c="systemd",enableSsl:l=!0,sslEmail:u="admin@example.com",domain:h,appPort:f=3000,installDatabaseClients:S=!1,installRedis:A=!1,extraPackages:v=[]}=n,C=`#!/bin/bash
338
315
  set -e
339
316
 
340
317
  # Update system
@@ -592,7 +569,7 @@ ufw default allow outgoing
592
569
  ${n.map((i)=>`ufw allow ${i}`).join(`
593
570
  `)}
594
571
  ufw --force enable
595
- `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},f={[u]:h},S,A;if(c)A=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:N.GetAtt(u,"AllocationId"),InstanceId:N.Ref(c)}},f[A]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:A,resources:f}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:f,userData:S,allowedPorts:A=[22,80,443],volumeSize:v=20,volumeType:C="gp3"}=n,P={},E=r({slug:i,environment:s,resourceType:"server-sg"}),I=t(E),D={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:A.map((oe)=>({IpProtocol:"tcp",FromPort:oe,ToPort:oe,CidrIp:"0.0.0.0/0",Description:`Port ${oe}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};P[I]=D;let x=r({slug:i,environment:s,resourceType:"server-role"}),O=t(x),w={Type:"AWS::IAM::Role",Properties:{RoleName:x,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:"*"}]}}]}};P[O]=w;let B=r({slug:i,environment:s,resourceType:"server-profile"}),_=t(B),K={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:B,Roles:[N.Ref(O)]}};P[_]=K;let Z=r({slug:i,environment:s,resourceType:"server"}),J=t(Z),Y={Type:"AWS::EC2::Instance",DependsOn:[_],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[N.Ref(I)],IamInstanceProfile:N.Ref(_),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:v,VolumeType:C,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:s},...f?[{Key:"Domain",Value:f}]:[]]}};if(S)Y.Properties.UserData=N.Base64(S);P[J]=Y;let{eip:X,eipAssociation:ae,eipLogicalId:$e,associationLogicalId:le,resources:Re}=a.createElasticIp({slug:i,environment:s,domain:f,instanceLogicalId:J});return Object.assign(P,Re),{instance:Y,securityGroup:D,eip:X,eipAssociation:ae,instanceRole:w,instanceProfile:K,resources:P,outputs:{instanceLogicalId:J,securityGroupLogicalId:I,eipLogicalId:$e,associationLogicalId:le,roleLogicalId:O,profileLogicalId:_}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
572
+ `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},f={[u]:h},S,A;if(c)A=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:N.GetAtt(u,"AllocationId"),InstanceId:N.Ref(c)}},f[A]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:A,resources:f}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:f,userData:S,allowedPorts:A=[22,80,443],volumeSize:v=20,volumeType:C="gp3"}=n,P={},E=r({slug:i,environment:s,resourceType:"server-sg"}),I=t(E),D={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:A.map((oe)=>({IpProtocol:"tcp",FromPort:oe,ToPort:oe,CidrIp:"0.0.0.0/0",Description:`Port ${oe}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};P[I]=D;let x=r({slug:i,environment:s,resourceType:"server-role"}),O=t(x),w={Type:"AWS::IAM::Role",Properties:{RoleName:x,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:"*"}]}}]}};P[O]=w;let B=r({slug:i,environment:s,resourceType:"server-profile"}),_=t(B),W={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:B,Roles:[N.Ref(O)]}};P[_]=W;let Z=r({slug:i,environment:s,resourceType:"server"}),J=t(Z),Y={Type:"AWS::EC2::Instance",DependsOn:[_],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[N.Ref(I)],IamInstanceProfile:N.Ref(_),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:v,VolumeType:C,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:s},...f?[{Key:"Domain",Value:f}]:[]]}};if(S)Y.Properties.UserData=N.Base64(S);P[J]=Y;let{eip:X,eipAssociation:ae,eipLogicalId:Oe,associationLogicalId:le,resources:Te}=a.createElasticIp({slug:i,environment:s,domain:f,instanceLogicalId:J});return Object.assign(P,Te),{instance:Y,securityGroup:D,eip:X,eipAssociation:ae,instanceRole:w,instanceProfile:W,resources:P,outputs:{instanceLogicalId:J,securityGroupLogicalId:I,eipLogicalId:Oe,associationLogicalId:le,roleLogicalId:O,profileLogicalId:_}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
596
573
  set -e
597
574
  apt-get update && apt-get upgrade -y
598
575
  apt-get install -y redis-server
@@ -600,7 +577,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
600
577
  systemctl enable redis-server
601
578
  systemctl restart redis-server
602
579
  echo "Redis server setup complete!"
603
- `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class y{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,f=r({slug:i,environment:s,resourceType:`subnet-${c}`}),S=t(`${f}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${f}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:N.Ref(n),InternetGatewayId:N.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:N.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:N.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:N.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=N.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=N.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=N.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:N.Ref(n),RouteTableId:N.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),f=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[f,S,A,v]=o.split(".").map(Number),C=(f<<24)+(S<<16)+(A<<8)+v,P=2**(32-h),E=[];for(let I=0;I<i*s;I++){let D=C+I*P,x=[D>>>24&255,D>>>16&255,D>>>8&255,D&255].join(".");E.push(`${x}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((o)=>`${n}${o}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:f=!1}=n,S={},A=[],v=[],C=[],{vpc:P,logicalId:E}=y.createVpc({slug:i,environment:s,cidr:c});S[E]=P;let{internetGateway:I,logicalId:D}=y.createInternetGateway(i,s);S[D]=I;let{attachment:x,logicalId:O}=y.attachInternetGateway(E,D);S[O]=x;let{routeTable:w,logicalId:B}=y.createRouteTable(i,s,E,"public");S[B]=w;let{route:_,logicalId:K}=y.createRoute(B,"0.0.0.0/0",{type:"igw",logicalId:D});_.DependsOn=O,S[K]=_;let Z=y.calculateSubnetCidrs(c,l,2),J=y.getAvailabilityZones(o,l),Y=[];for(let X=0;X<l;X++){let ae=J[X],$e=Z[X*2],le=Z[X*2+1],{subnet:Re,logicalId:oe}=y.createSubnet({slug:i,environment:s,vpcId:N.Ref(E),type:"public",cidr:$e,availabilityZone:ae});S[oe]=Re,A.push(oe);let{association:dt,logicalId:mt}=y.associateSubnetWithRouteTable(oe,B);S[mt]=dt;let{subnet:pt,logicalId:pe}=y.createSubnet({slug:i,environment:s,vpcId:N.Ref(E),type:"private",cidr:le,availabilityZone:ae});if(S[pe]=pt,v.push(pe),u&&(!h||X===0)){let{eip:ue,logicalId:ge}=y.createEip(`${i}-${ae}`,s);S[ge]=ue;let{natGateway:Ee,logicalId:ye}=y.createNatGateway({slug:`${i}-${ae}`,environment:s,subnetId:N.Ref(oe)},ge);Ee.DependsOn=O,S[ye]=Ee,C.push(ye);let{routeTable:Ae,logicalId:xe}=y.createRouteTable(`${i}-${ae}`,s,E,"private");S[xe]=Ae,Y.push(xe);let{route:Be,logicalId:W}=y.createRoute(xe,"0.0.0.0/0",{type:"nat",logicalId:ye});S[W]=Be;let{association:ee,logicalId:se}=y.associateSubnetWithRouteTable(pe,xe);S[se]=ee}else if(u&&h&&X>0){let{association:ue,logicalId:ge}=y.associateSubnetWithRouteTable(pe,Y[0]);S[ge]=ue}else{let{routeTable:ue,logicalId:ge}=y.createRouteTable(`${i}-${ae}-isolated`,s,E,"private");S[ge]=ue;let{association:Ee,logicalId:ye}=y.associateSubnetWithRouteTable(pe,ge);S[ye]=Ee}}if(f){let{flowLog:X,logicalId:ae}=y.enableFlowLogs({slug:i,environment:s,resourceId:N.Ref(E),resourceType:"VPC"});S[ae]=X}return{resources:S,outputs:{vpcId:E,publicSubnetIds:A,privateSubnetIds:v,natGatewayIds:C.length>0?C:void 0}}}static NatGatewayCostWarning=`
580
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class y{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,f=r({slug:i,environment:s,resourceType:`subnet-${c}`}),S=t(`${f}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${f}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:N.Ref(n),InternetGatewayId:N.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:N.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:N.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:N.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=N.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=N.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=N.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:N.Ref(n),RouteTableId:N.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),f=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[f,S,A,v]=o.split(".").map(Number),C=(f<<24)+(S<<16)+(A<<8)+v,P=2**(32-h),E=[];for(let I=0;I<i*s;I++){let D=C+I*P,x=[D>>>24&255,D>>>16&255,D>>>8&255,D&255].join(".");E.push(`${x}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((o)=>`${n}${o}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:f=!1}=n,S={},A=[],v=[],C=[],{vpc:P,logicalId:E}=y.createVpc({slug:i,environment:s,cidr:c});S[E]=P;let{internetGateway:I,logicalId:D}=y.createInternetGateway(i,s);S[D]=I;let{attachment:x,logicalId:O}=y.attachInternetGateway(E,D);S[O]=x;let{routeTable:w,logicalId:B}=y.createRouteTable(i,s,E,"public");S[B]=w;let{route:_,logicalId:W}=y.createRoute(B,"0.0.0.0/0",{type:"igw",logicalId:D});_.DependsOn=O,S[W]=_;let Z=y.calculateSubnetCidrs(c,l,2),J=y.getAvailabilityZones(o,l),Y=[];for(let X=0;X<l;X++){let ae=J[X],Oe=Z[X*2],le=Z[X*2+1],{subnet:Te,logicalId:oe}=y.createSubnet({slug:i,environment:s,vpcId:N.Ref(E),type:"public",cidr:Oe,availabilityZone:ae});S[oe]=Te,A.push(oe);let{association:dt,logicalId:mt}=y.associateSubnetWithRouteTable(oe,B);S[mt]=dt;let{subnet:pt,logicalId:pe}=y.createSubnet({slug:i,environment:s,vpcId:N.Ref(E),type:"private",cidr:le,availabilityZone:ae});if(S[pe]=pt,v.push(pe),u&&(!h||X===0)){let{eip:ue,logicalId:ge}=y.createEip(`${i}-${ae}`,s);S[ge]=ue;let{natGateway:Re,logicalId:ye}=y.createNatGateway({slug:`${i}-${ae}`,environment:s,subnetId:N.Ref(oe)},ge);Re.DependsOn=O,S[ye]=Re,C.push(ye);let{routeTable:Se,logicalId:xe}=y.createRouteTable(`${i}-${ae}`,s,E,"private");S[xe]=Se,Y.push(xe);let{route:$e,logicalId:K}=y.createRoute(xe,"0.0.0.0/0",{type:"nat",logicalId:ye});S[K]=$e;let{association:ee,logicalId:se}=y.associateSubnetWithRouteTable(pe,xe);S[se]=ee}else if(u&&h&&X>0){let{association:ue,logicalId:ge}=y.associateSubnetWithRouteTable(pe,Y[0]);S[ge]=ue}else{let{routeTable:ue,logicalId:ge}=y.createRouteTable(`${i}-${ae}-isolated`,s,E,"private");S[ge]=ue;let{association:Re,logicalId:ye}=y.associateSubnetWithRouteTable(pe,ge);S[ye]=Re}}if(f){let{flowLog:X,logicalId:ae}=y.enableFlowLogs({slug:i,environment:s,resourceId:N.Ref(E),resourceType:"VPC"});S[ae]=X}return{resources:S,outputs:{vpcId:E,publicSubnetIds:A,privateSubnetIds:v,natGatewayIds:C.length>0?C:void 0}}}static NatGatewayCostWarning=`
604
581
  ⚠️ NAT Gateway Cost Warning:
605
582
  - Each NAT Gateway costs approximately $32-45/month (hourly charges)
606
583
  - Data processing charges: $0.045/GB processed
@@ -608,7 +585,7 @@ echo "Redis server setup complete!"
608
585
  - Using a single NAT Gateway (singleNatGateway: true)
609
586
  - Using NAT Instances instead (cheaper but requires management)
610
587
  - Disabling NAT entirely for isolated private subnets
611
- `}class Ke{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:f=!0}=n,S=r({slug:i,environment:s,resourceType:"efs"}),A=t(S),v={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(c)v.Properties.KmsKeyId=c;if(u==="provisioned"&&h)v.Properties.ProvisionedThroughputInMibps=h;if(f)v.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:v,logicalId:A}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),f=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:f}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,f=r({slug:s,environment:o,resourceType:"efs-ap"}),S=t(`${f}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:N.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${f}-${c}`},{Key:"Environment",Value:o}]}},logicalId:S}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),f=t(h),S=[];for(let v of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:v,Description:"NFS from security group"});for(let v of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:v,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let f=0;f<c.length;f++){let S=c[f],A=r({slug:s,environment:o,resourceType:"efs-mt"}),v=t(`${A}-az${f+1}`),C={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(n),SubnetId:S,SecurityGroups:[l]}};u.push(C),h.push(v)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:f="elastic",enableBackup:S=!0,transitionToIA:A}=n,v={},{fileSystem:C,logicalId:P}=Ke.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:f,enableBackup:S});if(A)Ke.setLifecyclePolicy(C,{transitionToIA:A,transitionToPrimary:!0});v[P]=C;let{securityGroup:E,logicalId:I}=Ke.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});v[I]=E;let{mountTargets:D,logicalIds:x}=Ke.createMultiAzMountTargets(P,{slug:i,environment:s,subnetIds:c,securityGroupId:N.Ref(I)});for(let O=0;O<D.length;O++)v[x[O]]=D[O];return{resources:v,outputs:{fileSystemId:P,securityGroupId:I,mountTargetIds:x}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),f={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)f.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:f,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,f=o||r({slug:i,environment:s,resourceType:"ses-config"}),S=t(f),A=[];if(u)A.push("BOUNCE");if(h)A.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:f,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:A}}},logicalId:S}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:f="Require",s3Action:S,lambdaAction:A,snsAction:v}=i,C=r({slug:s,environment:o,resourceType:"ses-rule"}),P=t(C),E=[];if(S)E.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(A)E.push({LambdaAction:{FunctionArn:A.functionArn,InvocationType:A.invocationType||"Event"}});if(v)E.push({SNSAction:{TopicArn:v.topicArn,Encoding:v.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:C,Enabled:u,ScanEnabled:h,TlsPolicy:f,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:P}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let f of o)u+=` include:${f}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},f=t(`dmarc-${n.replace(/\./g,"")}`),S=`v=DMARC1; p=${o}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:f}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:f,snsTopicArn:S}=n,A={},{ruleSet:v,logicalId:C}=m.createReceiptRuleSet({slug:i,environment:s});A[C]=v;let{receiptRule:P,logicalId:E}=m.createReceiptRule(C,{slug:i,environment:s,ruleSetName:v.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:f?{functionArn:f,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});A[E]=P;let{record:I,logicalId:D}=m.createMxRecord(o,h,u);return A[D]=I,{resources:A,outputs:{ruleSetLogicalId:C,ruleLogicalId:E,mxRecordLogicalId:D}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:f}=n,S={},{emailIdentity:A,logicalId:v}=m.verifyDomain({domain:o,slug:i,environment:s});S[v]=A;let{configurationSet:C,logicalId:P}=m.createConfigurationSet({slug:i,environment:s});S[P]=C;let{record:E,logicalId:I}=m.createSpfRecord(o,c);S[I]=E;let{record:D,logicalId:x}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:f||`dmarc-reports@${o}`});if(S[x]=D,u&&h){let O=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,O.resources)}return{resources:S,outputs:{identityLogicalId:v,configSetLogicalId:P}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),f={Type:"AWS::IAM::Role",Properties:{RoleName:l,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:l},{Key:"Environment",Value:s}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let A={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[N.Ref(u)]}};return{role:f,policy:A,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,f=r({slug:i,environment:s,resourceType:"outbound-email"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"inbound-email"}),S=t(f),A=t(`${f}-permission`),v={Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},C={Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:N.Ref("AWS::AccountId")}};return{function:v,permission:C,logicalId:S,permissionLogicalId:A}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"email-conversion"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:f=!0}=n,S={},{role:A,policy:v,roleLogicalId:C,policyLogicalId:P}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});S[C]=A,S[P]=v;let{function:E,logicalId:I}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),domain:o,configurationSetName:u});S[I]=E;let D={roleLogicalId:C,outboundLambdaLogicalId:I};if(h){let{function:x,permission:O,logicalId:w,permissionLogicalId:B}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[w]=x,S[B]=O;let{permission:_,logicalId:K}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:w,s3BucketArn:l});S[K]=_,D.inboundLambdaLogicalId=w}if(f){let{function:x,logicalId:O}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[O]=x,D.conversionLambdaLogicalId=O}return{resources:S,outputs:D}}static LambdaCode={outboundEmail:`
588
+ `}class ze{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:f=!0}=n,S=r({slug:i,environment:s,resourceType:"efs"}),A=t(S),v={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(c)v.Properties.KmsKeyId=c;if(u==="provisioned"&&h)v.Properties.ProvisionedThroughputInMibps=h;if(f)v.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:v,logicalId:A}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),f=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:f}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,f=r({slug:s,environment:o,resourceType:"efs-ap"}),S=t(`${f}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:N.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${f}-${c}`},{Key:"Environment",Value:o}]}},logicalId:S}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),f=t(h),S=[];for(let v of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:v,Description:"NFS from security group"});for(let v of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:v,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let f=0;f<c.length;f++){let S=c[f],A=r({slug:s,environment:o,resourceType:"efs-mt"}),v=t(`${A}-az${f+1}`),C={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(n),SubnetId:S,SecurityGroups:[l]}};u.push(C),h.push(v)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:f="elastic",enableBackup:S=!0,transitionToIA:A}=n,v={},{fileSystem:C,logicalId:P}=ze.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:f,enableBackup:S});if(A)ze.setLifecyclePolicy(C,{transitionToIA:A,transitionToPrimary:!0});v[P]=C;let{securityGroup:E,logicalId:I}=ze.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});v[I]=E;let{mountTargets:D,logicalIds:x}=ze.createMultiAzMountTargets(P,{slug:i,environment:s,subnetIds:c,securityGroupId:N.Ref(I)});for(let O=0;O<D.length;O++)v[x[O]]=D[O];return{resources:v,outputs:{fileSystemId:P,securityGroupId:I,mountTargetIds:x}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),f={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)f.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:f,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,f=o||r({slug:i,environment:s,resourceType:"ses-config"}),S=t(f),A=[];if(u)A.push("BOUNCE");if(h)A.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:f,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:A}}},logicalId:S}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:f="Require",s3Action:S,lambdaAction:A,snsAction:v}=i,C=r({slug:s,environment:o,resourceType:"ses-rule"}),P=t(C),E=[];if(S)E.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(A)E.push({LambdaAction:{FunctionArn:A.functionArn,InvocationType:A.invocationType||"Event"}});if(v)E.push({SNSAction:{TopicArn:v.topicArn,Encoding:v.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:C,Enabled:u,ScanEnabled:h,TlsPolicy:f,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:P}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let f of o)u+=` include:${f}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},f=t(`dmarc-${n.replace(/\./g,"")}`),S=`v=DMARC1; p=${o}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:f}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:f,snsTopicArn:S}=n,A={},{ruleSet:v,logicalId:C}=m.createReceiptRuleSet({slug:i,environment:s});A[C]=v;let{receiptRule:P,logicalId:E}=m.createReceiptRule(C,{slug:i,environment:s,ruleSetName:v.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:f?{functionArn:f,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});A[E]=P;let{record:I,logicalId:D}=m.createMxRecord(o,h,u);return A[D]=I,{resources:A,outputs:{ruleSetLogicalId:C,ruleLogicalId:E,mxRecordLogicalId:D}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:f}=n,S={},{emailIdentity:A,logicalId:v}=m.verifyDomain({domain:o,slug:i,environment:s});S[v]=A;let{configurationSet:C,logicalId:P}=m.createConfigurationSet({slug:i,environment:s});S[P]=C;let{record:E,logicalId:I}=m.createSpfRecord(o,c);S[I]=E;let{record:D,logicalId:x}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:f||`dmarc-reports@${o}`});if(S[x]=D,u&&h){let O=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,O.resources)}return{resources:S,outputs:{identityLogicalId:v,configSetLogicalId:P}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),f={Type:"AWS::IAM::Role",Properties:{RoleName:l,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:l},{Key:"Environment",Value:s}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let A={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[N.Ref(u)]}};return{role:f,policy:A,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,f=r({slug:i,environment:s,resourceType:"outbound-email"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"inbound-email"}),S=t(f),A=t(`${f}-permission`),v={Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},C={Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:N.Ref("AWS::AccountId")}};return{function:v,permission:C,logicalId:S,permissionLogicalId:A}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"email-conversion"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:f=!0}=n,S={},{role:A,policy:v,roleLogicalId:C,policyLogicalId:P}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});S[C]=A,S[P]=v;let{function:E,logicalId:I}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),domain:o,configurationSetName:u});S[I]=E;let D={roleLogicalId:C,outboundLambdaLogicalId:I};if(h){let{function:x,permission:O,logicalId:w,permissionLogicalId:B}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[w]=x,S[B]=O;let{permission:_,logicalId:W}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:w,s3BucketArn:l});S[W]=_,D.inboundLambdaLogicalId=w}if(f){let{function:x,logicalId:O}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[O]=x,D.conversionLambdaLogicalId=O}return{resources:S,outputs:D}}static LambdaCode={outboundEmail:`
612
589
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
613
590
  const ses = new SESClient({});
614
591
 
@@ -1154,7 +1131,7 @@ else if (encoding === 'quoted-printable') {
1154
1131
 
1155
1132
  return content;
1156
1133
  }
1157
- `}}var Wp={};tn(Wp,{default:()=>pr,handler:()=>At});var At=`
1134
+ `}}var tm={};tn(tm,{default:()=>pr,handler:()=>At});var At=`
1158
1135
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1159
1136
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1160
1137
 
@@ -1646,7 +1623,7 @@ catch (error) {
1646
1623
 
1647
1624
  return { statusCode: 200, body: 'OK' };
1648
1625
  };
1649
- `;class We{static LambdaCode={incomingCall:At,voicemail:un,missedCall:ln};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:We.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:We.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:We.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,We.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,We.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},l={Ref:`${n.slug}CallLogTable`},u={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,We.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,We.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,We.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class H{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:f=0,fifo:S=!1,contentBasedDeduplication:A=!1,encrypted:v=!0,kmsKeyId:C}=n,P=o||r({slug:i,environment:s,resourceType:"queue"}),E=S?`${P}.fifo`:P,I=t(P),D={Type:"AWS::SQS::Queue",Properties:{QueueName:E,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:f,VisibilityTimeout:l,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};if(S)D.Properties.FifoQueue=!0,D.Properties.ContentBasedDeduplication=A;if(v)if(C)D.Properties.KmsMasterKeyId=C;else D.Properties.SqsManagedSseEnabled=!0;return{queue:D,logicalId:I}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,l=r({slug:s,environment:o,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},f={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:N.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:f,deadLetterLogicalId:u}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"schedule"}),f=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:f}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:f,clusterArn:S,subnets:A,securityGroups:v=[],assignPublicIp:C=!1,taskCount:P=1,containerOverrides:E}=s,I=l||r({slug:o,environment:c,resourceType:"ecs-schedule"}),D=t(I),O={Id:"1",Arn:S,RoleArn:i,EcsParameters:{TaskDefinitionArn:f,TaskCount:P,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:A,SecurityGroups:v,AssignPublicIp:C?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(E&&E.length>0)O.Input=JSON.stringify({containerOverrides:E});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:I,Description:u||`Scheduled ECS task: ${f}`,ScheduleExpression:n,State:h?"ENABLED":"DISABLED",Targets:[O]}},logicalId:D}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,functionArn:h,input:f}=i,S=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),A=t(S),v={Id:"1",Arn:h};if(f)v.Input=JSON.stringify(f);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[v]}},logicalId:A}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:f}=i,S=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),A=t(S),v={Id:"1",Arn:h};if(f)v.SqsParameters={MessageGroupId:f};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[v]}},logicalId:A}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let S=parseInt(s[1],10),A=s[2].toLowerCase(),v=A.endsWith("s")&&S===1?A.slice(0,-1):A,C=!A.endsWith("s")&&S>1?`${A}s`:A;return`rate(${S} ${S===1?v:C})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let l=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let S=parseInt(l[1],10),A=l[2]?.toLowerCase();if(A==="pm"&&S!==12)S+=12;else if(A==="am"&&S===12)S=0;return`cron(0 ${S} * * ? *)`}let u=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let S=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${S} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},f=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(f)return`cron(0 0 ? * ${h[f[1].toLowerCase()]} *)`;return H.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:f=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:f}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:l}=i,u;switch(s){case"linear":u=o*n;break;case"exponential":u=o*2**(n-1);break;case"fixed":default:u=o}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,l=[{name:"JOB_CLASS",value:s}];if(o)l.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:f,securityGroups:S=[],roleArn:A,containerName:v="app"}=n,C=H.rateStringToExpression(o),P=H.createJobContainerOverride({containerName:v,jobClass:c,jobData:l});return H.scheduleEcsTask(C,A,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:f,securityGroups:S,containerOverrides:[P]})}static QueuePresets={highThroughput:(n,i)=>H.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>H.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>H.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>H.createQueue({slug:n,environment:i,delaySeconds:s})}}class It{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((f)=>f.endsWith(".ts")&&!f.startsWith("_")&&f!=="runner.ts");for(let f of h){let S=u.join(o,f),A=f.replace(".ts",""),v=l.readFileSync(S,"utf-8"),C=It.parseJobMetadata(v,A,S);if(C)c.push(C)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),l=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),u=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),h=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),f=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:f?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((f)=>f.endsWith(".ts")&&!f.startsWith("_"));for(let f of h){let S=u.join(o,f),A=f.replace(".ts",""),v=l.readFileSync(S,"utf-8"),C=It.parseActionMetadata(v,A,S);if(C)c.push(C)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let c=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:c?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:f,containerName:S="app"}=n,A={},v=0;for(let C of o){if(!C.schedule||!C.enabled)continue;let{rule:P,logicalId:E}=H.createScheduledJob({slug:i,environment:s,schedule:C.schedule,jobClass:C.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:f,containerName:S});A[E]=P,v++}return{rules:A,count:v}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1626
+ `;class Ke{static LambdaCode={incomingCall:At,voicemail:un,missedCall:ln};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ke.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:Ke.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ke.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Ke.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,Ke.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},l={Ref:`${n.slug}CallLogTable`},u={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,Ke.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,Ke.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,Ke.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class H{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:f=0,fifo:S=!1,contentBasedDeduplication:A=!1,encrypted:v=!0,kmsKeyId:C}=n,P=o||r({slug:i,environment:s,resourceType:"queue"}),E=S?`${P}.fifo`:P,I=t(P),D={Type:"AWS::SQS::Queue",Properties:{QueueName:E,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:f,VisibilityTimeout:l,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};if(S)D.Properties.FifoQueue=!0,D.Properties.ContentBasedDeduplication=A;if(v)if(C)D.Properties.KmsMasterKeyId=C;else D.Properties.SqsManagedSseEnabled=!0;return{queue:D,logicalId:I}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,l=r({slug:s,environment:o,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},f={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:N.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:f,deadLetterLogicalId:u}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"schedule"}),f=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:f}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:f,clusterArn:S,subnets:A,securityGroups:v=[],assignPublicIp:C=!1,taskCount:P=1,containerOverrides:E}=s,I=l||r({slug:o,environment:c,resourceType:"ecs-schedule"}),D=t(I),O={Id:"1",Arn:S,RoleArn:i,EcsParameters:{TaskDefinitionArn:f,TaskCount:P,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:A,SecurityGroups:v,AssignPublicIp:C?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(E&&E.length>0)O.Input=JSON.stringify({containerOverrides:E});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:I,Description:u||`Scheduled ECS task: ${f}`,ScheduleExpression:n,State:h?"ENABLED":"DISABLED",Targets:[O]}},logicalId:D}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,functionArn:h,input:f}=i,S=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),A=t(S),v={Id:"1",Arn:h};if(f)v.Input=JSON.stringify(f);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[v]}},logicalId:A}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:f}=i,S=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),A=t(S),v={Id:"1",Arn:h};if(f)v.SqsParameters={MessageGroupId:f};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[v]}},logicalId:A}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let S=parseInt(s[1],10),A=s[2].toLowerCase(),v=A.endsWith("s")&&S===1?A.slice(0,-1):A,C=!A.endsWith("s")&&S>1?`${A}s`:A;return`rate(${S} ${S===1?v:C})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let l=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let S=parseInt(l[1],10),A=l[2]?.toLowerCase();if(A==="pm"&&S!==12)S+=12;else if(A==="am"&&S===12)S=0;return`cron(0 ${S} * * ? *)`}let u=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let S=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${S} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},f=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(f)return`cron(0 0 ? * ${h[f[1].toLowerCase()]} *)`;return H.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:f=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:f}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:l}=i,u;switch(s){case"linear":u=o*n;break;case"exponential":u=o*2**(n-1);break;case"fixed":default:u=o}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,l=[{name:"JOB_CLASS",value:s}];if(o)l.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:f,securityGroups:S=[],roleArn:A,containerName:v="app"}=n,C=H.rateStringToExpression(o),P=H.createJobContainerOverride({containerName:v,jobClass:c,jobData:l});return H.scheduleEcsTask(C,A,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:f,securityGroups:S,containerOverrides:[P]})}static QueuePresets={highThroughput:(n,i)=>H.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>H.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>H.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>H.createQueue({slug:n,environment:i,delaySeconds:s})}}class It{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((f)=>f.endsWith(".ts")&&!f.startsWith("_")&&f!=="runner.ts");for(let f of h){let S=u.join(o,f),A=f.replace(".ts",""),v=l.readFileSync(S,"utf-8"),C=It.parseJobMetadata(v,A,S);if(C)c.push(C)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),l=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),u=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),h=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),f=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:f?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((f)=>f.endsWith(".ts")&&!f.startsWith("_"));for(let f of h){let S=u.join(o,f),A=f.replace(".ts",""),v=l.readFileSync(S,"utf-8"),C=It.parseActionMetadata(v,A,S);if(C)c.push(C)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let c=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:c?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:f,containerName:S="app"}=n,A={},v=0;for(let C of o){if(!C.schedule||!C.enabled)continue;let{rule:P,logicalId:E}=H.createScheduledJob({slug:i,environment:s,schedule:C.schedule,jobClass:C.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:f,containerName:S});A[E]=P,v++}return{rules:A,count:v}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1650
1627
  /**
1651
1628
  * Job Runner Script
1652
1629
  * This script is invoked by ECS scheduled tasks to run jobs
@@ -1691,7 +1668,7 @@ catch (error) {
1691
1668
  }
1692
1669
 
1693
1670
  run()
1694
- `}static async generateJobManifest(n){let i=await It.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var uI={loadJobs:It.discoverJobs,loadActions:It.discoverActions,generateScheduledJobs:It.generateScheduledJobResources,generateRunner:It.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}};var Jp={};tn(Jp,{default:()=>gr,handler:()=>vt});var vt=`
1671
+ `}static async generateJobManifest(n){let i=await It.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var bI={loadJobs:It.discoverJobs,loadActions:It.discoverActions,generateScheduledJobs:It.generateScheduledJobResources,generateRunner:It.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}};var rm={};tn(rm,{default:()=>gr,handler:()=>vt});var vt=`
1695
1672
  const { PinpointClient, SendMessagesCommand } = require('@aws-sdk/client-pinpoint');
1696
1673
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1697
1674
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -2294,14 +2271,14 @@ catch (error) {
2294
2271
 
2295
2272
  return { statusCode: 200, body: 'OK' };
2296
2273
  };
2297
- `;class G{static LambdaCode={send:vt,receive:mn,deliveryStatus:dn};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,G.createPinpointApp({slug:n.slug})),Object.assign(i,G.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,G.createSmsLambdaRole({slug:n.slug})),Object.assign(i,G.createMessageLogTable({slug:n.slug})),Object.assign(i,G.createOptOutTable({slug:n.slug})),Object.assign(i,G.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,G.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,G.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,G.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Tt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((o)=>o.charAt(0).toUpperCase()+o.slice(1)).join("")||"User"}function yr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function hr(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function fr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function br(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Sr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class Gd{static create(n){let i=hr(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Tt(n.slug)}${Tt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let f=`${c}LoggingRole`;u[f]={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/*"}]}}]}},h={"Fn::GetAtt":[f,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[f,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(f))throw Error(`sftp: invalid username ${f}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${f} requires at least one SSH public key`);let A=Tt(f),v=yr(S.homeDirectory,f),C=`${c}${A}User`,P=S.roleArn;if(!P){let E=`${c}${A}Role`,I;if(i.type==="efs")I=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(i.fileSystemId)}];else{let D=`arn:aws:s3:::${i.bucket}`;I=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:D,Condition:{StringLike:{"s3:prefix":[v,`${v}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${D}/${v}/*`}]}u[E]={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:I}}]}},P={"Fn::GetAtt":[E,"Arn"]}}u[C]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:f,Role:P,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?br(i.fileSystemId,v):`/${i.bucket}/${v}`,...i.type==="efs"?{PosixProfile:fr(f,S,i.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Ne{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),f=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let A=l.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:A}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:f}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,f=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(f),A=[];if(l)A.push("bedrock:InvokeModel");if(u)A.push("bedrock:InvokeModelWithResponseStream");if(h)A.push("bedrock:InvokeModelAsync");let v=c.map((P)=>P==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${P}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:f,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:A,Resource:v}]}}},logicalId:S}}static enableBedrockForLambda(n){return Ne.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Ne.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Ne.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Wt{static createPostgres(n){return Wt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return Wt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:f="admin",masterPassword:S,databaseName:A,subnetIds:v,securityGroupIds:C,encrypted:P=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:D=7,publiclyAccessible:x=!1,enableCloudwatchLogs:O=!0,deletionProtection:w=!0}=s,B=r({slug:o,environment:c,resourceType:`${n}-db`}),_=t(B),K,Z;if(v&&v.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});Z=t(Y),K={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${B}`,SubnetIds:v,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let J={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:B,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:f,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:P,MultiAZ:I,BackupRetentionPeriod:D,PubliclyAccessible:x,DeletionProtection:w,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:c}]}};if(A)J.Properties.DBName=A;if(E)J.Properties.KmsKeyId=E;if(Z)J.Properties.DBSubnetGroupName=N.Ref(Z);if(C&&C.length>0)J.Properties.VPCSecurityGroups=C;if(O)J.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:J,subnetGroup:K,logicalId:_,subnetGroupId:Z}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),f=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:f}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),f=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:f,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:f=5,streamEnabled:S=!1,streamViewType:A="NEW_AND_OLD_IMAGES",encrypted:v=!0,kmsKeyId:C,pointInTimeRecovery:P=!0,ttlAttribute:E}=n,I=o||r({slug:i,environment:s,resourceType:"table"}),D=t(I),x=[{AttributeName:c.name,AttributeType:c.type}];if(l)x.push({AttributeName:l.name,AttributeType:l.type});let O=[{AttributeName:c.name,KeyType:"HASH"}];if(l)O.push({AttributeName:l.name,KeyType:"RANGE"});let w={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:x,KeySchema:O,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")w.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(S)w.Properties.StreamSpecification={StreamViewType:A};if(v)w.Properties.SSESpecification={SSEEnabled:!0,SSEType:C?"KMS":"AES256",KMSMasterKeyId:C};if(P)w.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)w.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:w,logicalId:D}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:f=5}=i;if(!n.Properties.AttributeDefinitions.some((v)=>v.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((v)=>v.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:o.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let A={IndexName:s,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")A.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(A),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Co{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:f=2,automaticFailover:S=!0,multiAz:A=!0,clusterMode:v=!1,numNodeGroups:C=1,replicasPerNodeGroup:P=1,atRestEncryption:E=!0,transitEncryption:I=!0,authToken:D,kmsKeyId:x,snapshotRetentionDays:O=7,snapshotWindow:w,maintenanceWindow:B}=n,_=r({slug:i,environment:s,resourceType:"redis"}),K=t(_),Z,J;if(u&&u.length>0){let X=r({slug:i,environment:s,resourceType:"cache-subnet-group"});J=t(X),Z={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:X,Description:`Subnet group for ${_}`,SubnetIds:u,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:_,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:A,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:O,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s}]}};if(v)Y.Properties.NumNodeGroups=C,Y.Properties.ReplicasPerNodeGroup=P;else Y.Properties.NumCacheClusters=f;if(D)Y.Properties.AuthToken=D;if(x)Y.Properties.KmsKeyId=x;if(J)Y.Properties.CacheSubnetGroupName=N.Ref(J);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(w)Y.Properties.SnapshotWindow=w;if(B)Y.Properties.PreferredMaintenanceWindow=B;return{replicationGroup:Y,subnetGroup:Z,logicalId:K,subnetGroupId:J}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:f,azMode:S="cross-az",preferredAzs:A,maintenanceWindow:v}=n,C=r({slug:i,environment:s,resourceType:"memcached"}),P=t(C),E,I;if(h&&h.length>0){let x=r({slug:i,environment:s,resourceType:"cache-subnet-group"});I=t(x),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:x,Description:`Subnet group for ${C}`,SubnetIds:h,Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}}}let D={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:C,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}};if(I)D.Properties.CacheSubnetGroupName=N.Ref(I);if(f&&f.length>0)D.Properties.VpcSecurityGroupIds=f;if(A&&A.length>0)D.Properties.PreferredAvailabilityZones=A;if(v)D.Properties.PreferredMaintenanceWindow=v;return{cluster:D,subnetGroup:E,logicalId:P,subnetGroupId:I}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}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 re{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),f={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)f.Properties.Groups=c;if(l&&l.length>0)f.Properties.ManagedPolicyArns=l;return{user:f,logicalId:h}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),f=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let A={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.ManagedPolicyArns=u;return{role:A,logicalId:f}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),f=l.map((A)=>({Sid:A.sid,Effect:A.effect||"Allow",Action:A.actions,Resource:A.resources,Condition:A.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:f}}},logicalId:h}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(n)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((P)=>`${P}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:f}=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[f]=h;let{user:S,logicalId:A}=re.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(f)]});l[A]=S;let v,C;if(c){let P=re.createAccessKey(A,{slug:i,environment:s});v=P.accessKey,C=P.logicalId,l[C]=v}return{user:S,accessKey:v,policy:h,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:f,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:f,logicalId:S}=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[S]=f;let A=r({slug:i,environment:s,resourceType:"cross-account-role"}),v=t(A),C={};if(c)C.StringEquals={"sts:ExternalId":c};let P={Type:"AWS::IAM::Role",Properties:{RoleName:A,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(C).length>0?{Condition:C}:{}}]},ManagedPolicyArns:[N.Ref(S)],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[v]=P,{role:P,policy:f,roleLogicalId:v,policyLogicalId:S,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[re.ManagedPolicies.ReadOnlyAccess];break;case"deploy":l=[{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":u=[re.ManagedPolicies.AdministratorAccess];break}let h,f;if(l.length>0){let P=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=P.policy,f=P.logicalId,c[f]=h,u=[N.Ref(f)]}let{user:S,logicalId:A}=re.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[A]=S;let{accessKey:v,logicalId:C}=re.createAccessKey(A,{slug:i,environment:s});return c[C]=v,{user:S,accessKey:v,policy:h,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:f,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class Vd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,f=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(f),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:f,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.BinaryMediaTypes=u;if(h!==void 0)A.Properties.MinimumCompressionSize=h;return{restApi:A,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:f=["*"],corsMaxAge:S=86400,corsAllowCredentials:A=!1}=n,v=o||r({slug:i,environment:s,resourceType:"http-api"}),C=t(v),P={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:v,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:v,Environment:s}}};if(l)P.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:f,MaxAge:S,AllowCredentials:A};return{httpApi:P,logicalId:C}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:f="0.5",variables:S,throttling:A}=s,v=r({slug:o,environment:c,resourceType:"api-stage"}),C=t(v),P={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(n),DeploymentId:N.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:c}]}};if(h)P.Properties.CacheClusterSize=f;if(S)P.Properties.Variables=S;if(A)P.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:A.burstLimit,ThrottlingRateLimit:A.rateLimit}];return{stage:P,logicalId:C}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:f,ttl:S=300}=i,A=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),v=t(A),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:A,Type:l,RestApiId:N.Ref(n),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");C.Properties.AuthorizerUri=u,C.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!f||f.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=f,C.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:C,logicalId:v}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class ne{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),f=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:f}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,f=r({slug:s,environment:o,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),A=S.length>12?S.slice(-12):S,v=t(`${f}-${c}-${A}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:v}}static subscribeEmail(n,i,s){return ne.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ne.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ne.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ne.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ne.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),f=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:N.Ref(n)}]}}},logicalId:f}}static allowCloudWatchAlarms(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class TA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:f}=n,S=o||r({slug:i,environment:s,resourceType:"state-machine"}),A=t(S),v,C,P;if(u)P=u;else{let I=r({slug:i,environment:s,resourceType:"state-machine-role"});C=t(I),v={Type:"AWS::IAM::Role",Properties:{RoleName:I,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:I},{Key:"Environment",Value:s}]}},P=N.GetAtt(C,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:P,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(f)E.Properties.TracingConfiguration={Enabled:f.enabled};return{stateMachine:E,logicalId:A,role:v,roleLogicalId:C}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class Eo{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:f=1,threshold:S,comparisonOperator:A,treatMissingData:v="notBreaching",actionsEnabled:C=!0,alarmActions:P,okActions:E,insufficientDataActions:I,dimensions:D,unit:x,datapointsToAlarm:O}=n,w=o||r({slug:i,environment:s,resourceType:"alarm"}),B=t(w),_={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:w,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:f,Threshold:S,ComparisonOperator:A,TreatMissingData:v,ActionsEnabled:C}};if(P&&P.length>0)_.Properties.AlarmActions=P;if(E&&E.length>0)_.Properties.OKActions=E;if(I&&I.length>0)_.Properties.InsufficientDataActions=I;if(D)_.Properties.Dimensions=Object.entries(D).map(([K,Z])=>({Name:K,Value:Z}));if(x)_.Properties.Unit=x;if(O!==void 0)_.Properties.DatapointsToAlarm=O;return{alarm:_,logicalId:B}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:f}=n,S=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),A=t(S),v={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)v.Properties.AlarmActions=u;if(h&&h.length>0)v.Properties.OKActions=h;if(f&&f.length>0)v.Properties.InsufficientDataActions=f;return{alarm:v,logicalId:A}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((S)=>({type:S.type,x:S.x,y:S.y,width:S.width,height:S.height,properties:S.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),f={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)f.Properties.RetentionInDays=c;if(l)f.Properties.KmsKeyId=l;return{logGroup:f,logicalId:h}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),f=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(n),FilterPattern:l,MetricTransformations:u.map((A)=>({MetricName:A.metricName,MetricNamespace:A.metricNamespace,MetricValue:A.metricValue,DefaultValue:A.defaultValue,Unit:A.unit}))}},logicalId:f}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2274
+ `;class G{static LambdaCode={send:vt,receive:mn,deliveryStatus:dn};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:G.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,G.createPinpointApp({slug:n.slug})),Object.assign(i,G.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,G.createSmsLambdaRole({slug:n.slug})),Object.assign(i,G.createMessageLogTable({slug:n.slug})),Object.assign(i,G.createOptOutTable({slug:n.slug})),Object.assign(i,G.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,G.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,G.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,G.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Tt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((o)=>o.charAt(0).toUpperCase()+o.slice(1)).join("")||"User"}function yr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function hr(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function fr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function br(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Sr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class qd{static create(n){let i=hr(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Tt(n.slug)}${Tt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let f=`${c}LoggingRole`;u[f]={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/*"}]}}]}},h={"Fn::GetAtt":[f,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[f,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(f))throw Error(`sftp: invalid username ${f}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${f} requires at least one SSH public key`);let A=Tt(f),v=yr(S.homeDirectory,f),C=`${c}${A}User`,P=S.roleArn;if(!P){let E=`${c}${A}Role`,I;if(i.type==="efs")I=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(i.fileSystemId)}];else{let D=`arn:aws:s3:::${i.bucket}`;I=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:D,Condition:{StringLike:{"s3:prefix":[v,`${v}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${D}/${v}/*`}]}u[E]={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:I}}]}},P={"Fn::GetAtt":[E,"Arn"]}}u[C]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:f,Role:P,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?br(i.fileSystemId,v):`/${i.bucket}/${v}`,...i.type==="efs"?{PosixProfile:fr(f,S,i.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Pe{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),f=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let A=l.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:A}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:f}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,f=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(f),A=[];if(l)A.push("bedrock:InvokeModel");if(u)A.push("bedrock:InvokeModelWithResponseStream");if(h)A.push("bedrock:InvokeModelAsync");let v=c.map((P)=>P==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${P}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:f,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:A,Resource:v}]}}},logicalId:S}}static enableBedrockForLambda(n){return Pe.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Pe.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Pe.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Wt{static createPostgres(n){return Wt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return Wt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:f="admin",masterPassword:S,databaseName:A,subnetIds:v,securityGroupIds:C,encrypted:P=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:D=7,publiclyAccessible:x=!1,enableCloudwatchLogs:O=!0,deletionProtection:w=!0}=s,B=r({slug:o,environment:c,resourceType:`${n}-db`}),_=t(B),W,Z;if(v&&v.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});Z=t(Y),W={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${B}`,SubnetIds:v,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let J={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:B,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:f,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:P,MultiAZ:I,BackupRetentionPeriod:D,PubliclyAccessible:x,DeletionProtection:w,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:c}]}};if(A)J.Properties.DBName=A;if(E)J.Properties.KmsKeyId=E;if(Z)J.Properties.DBSubnetGroupName=N.Ref(Z);if(C&&C.length>0)J.Properties.VPCSecurityGroups=C;if(O)J.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:J,subnetGroup:W,logicalId:_,subnetGroupId:Z}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),f=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:f}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),f=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:f,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:f=5,streamEnabled:S=!1,streamViewType:A="NEW_AND_OLD_IMAGES",encrypted:v=!0,kmsKeyId:C,pointInTimeRecovery:P=!0,ttlAttribute:E}=n,I=o||r({slug:i,environment:s,resourceType:"table"}),D=t(I),x=[{AttributeName:c.name,AttributeType:c.type}];if(l)x.push({AttributeName:l.name,AttributeType:l.type});let O=[{AttributeName:c.name,KeyType:"HASH"}];if(l)O.push({AttributeName:l.name,KeyType:"RANGE"});let w={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:x,KeySchema:O,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")w.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(S)w.Properties.StreamSpecification={StreamViewType:A};if(v)w.Properties.SSESpecification={SSEEnabled:!0,SSEType:C?"KMS":"AES256",KMSMasterKeyId:C};if(P)w.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)w.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:w,logicalId:D}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:f=5}=i;if(!n.Properties.AttributeDefinitions.some((v)=>v.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((v)=>v.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:o.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let A={IndexName:s,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")A.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(A),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Co{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:f=2,automaticFailover:S=!0,multiAz:A=!0,clusterMode:v=!1,numNodeGroups:C=1,replicasPerNodeGroup:P=1,atRestEncryption:E=!0,transitEncryption:I=!0,authToken:D,kmsKeyId:x,snapshotRetentionDays:O=7,snapshotWindow:w,maintenanceWindow:B}=n,_=r({slug:i,environment:s,resourceType:"redis"}),W=t(_),Z,J;if(u&&u.length>0){let X=r({slug:i,environment:s,resourceType:"cache-subnet-group"});J=t(X),Z={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:X,Description:`Subnet group for ${_}`,SubnetIds:u,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:_,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:A,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:O,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s}]}};if(v)Y.Properties.NumNodeGroups=C,Y.Properties.ReplicasPerNodeGroup=P;else Y.Properties.NumCacheClusters=f;if(D)Y.Properties.AuthToken=D;if(x)Y.Properties.KmsKeyId=x;if(J)Y.Properties.CacheSubnetGroupName=N.Ref(J);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(w)Y.Properties.SnapshotWindow=w;if(B)Y.Properties.PreferredMaintenanceWindow=B;return{replicationGroup:Y,subnetGroup:Z,logicalId:W,subnetGroupId:J}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:f,azMode:S="cross-az",preferredAzs:A,maintenanceWindow:v}=n,C=r({slug:i,environment:s,resourceType:"memcached"}),P=t(C),E,I;if(h&&h.length>0){let x=r({slug:i,environment:s,resourceType:"cache-subnet-group"});I=t(x),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:x,Description:`Subnet group for ${C}`,SubnetIds:h,Tags:[{Key:"Name",Value:x},{Key:"Environment",Value:s}]}}}let D={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:C,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s}]}};if(I)D.Properties.CacheSubnetGroupName=N.Ref(I);if(f&&f.length>0)D.Properties.VpcSecurityGroupIds=f;if(A&&A.length>0)D.Properties.PreferredAvailabilityZones=A;if(v)D.Properties.PreferredMaintenanceWindow=v;return{cluster:D,subnetGroup:E,logicalId:P,subnetGroupId:I}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}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 re{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),f={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)f.Properties.Groups=c;if(l&&l.length>0)f.Properties.ManagedPolicyArns=l;return{user:f,logicalId:h}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),f=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let A={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.ManagedPolicyArns=u;return{role:A,logicalId:f}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),f=l.map((A)=>({Sid:A.sid,Effect:A.effect||"Allow",Action:A.actions,Resource:A.resources,Condition:A.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:f}}},logicalId:h}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(n)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((P)=>`${P}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:f}=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[f]=h;let{user:S,logicalId:A}=re.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(f)]});l[A]=S;let v,C;if(c){let P=re.createAccessKey(A,{slug:i,environment:s});v=P.accessKey,C=P.logicalId,l[C]=v}return{user:S,accessKey:v,policy:h,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:f,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:f,logicalId:S}=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[S]=f;let A=r({slug:i,environment:s,resourceType:"cross-account-role"}),v=t(A),C={};if(c)C.StringEquals={"sts:ExternalId":c};let P={Type:"AWS::IAM::Role",Properties:{RoleName:A,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(C).length>0?{Condition:C}:{}}]},ManagedPolicyArns:[N.Ref(S)],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[v]=P,{role:P,policy:f,roleLogicalId:v,policyLogicalId:S,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[re.ManagedPolicies.ReadOnlyAccess];break;case"deploy":l=[{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":u=[re.ManagedPolicies.AdministratorAccess];break}let h,f;if(l.length>0){let P=re.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=P.policy,f=P.logicalId,c[f]=h,u=[N.Ref(f)]}let{user:S,logicalId:A}=re.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[A]=S;let{accessKey:v,logicalId:C}=re.createAccessKey(A,{slug:i,environment:s});return c[C]=v,{user:S,accessKey:v,policy:h,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:f,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class jd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,f=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(f),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:f,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.BinaryMediaTypes=u;if(h!==void 0)A.Properties.MinimumCompressionSize=h;return{restApi:A,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:f=["*"],corsMaxAge:S=86400,corsAllowCredentials:A=!1}=n,v=o||r({slug:i,environment:s,resourceType:"http-api"}),C=t(v),P={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:v,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:v,Environment:s}}};if(l)P.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:f,MaxAge:S,AllowCredentials:A};return{httpApi:P,logicalId:C}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:f="0.5",variables:S,throttling:A}=s,v=r({slug:o,environment:c,resourceType:"api-stage"}),C=t(v),P={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(n),DeploymentId:N.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:c}]}};if(h)P.Properties.CacheClusterSize=f;if(S)P.Properties.Variables=S;if(A)P.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:A.burstLimit,ThrottlingRateLimit:A.rateLimit}];return{stage:P,logicalId:C}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:f,ttl:S=300}=i,A=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),v=t(A),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:A,Type:l,RestApiId:N.Ref(n),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");C.Properties.AuthorizerUri=u,C.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!f||f.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=f,C.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:C,logicalId:v}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class ne{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),f=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:f}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,f=r({slug:s,environment:o,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),A=S.length>12?S.slice(-12):S,v=t(`${f}-${c}-${A}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:v}}static subscribeEmail(n,i,s){return ne.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ne.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ne.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ne.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ne.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),f=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:N.Ref(n)}]}}},logicalId:f}}static allowCloudWatchAlarms(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ne.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ne.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class OA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:f}=n,S=o||r({slug:i,environment:s,resourceType:"state-machine"}),A=t(S),v,C,P;if(u)P=u;else{let I=r({slug:i,environment:s,resourceType:"state-machine-role"});C=t(I),v={Type:"AWS::IAM::Role",Properties:{RoleName:I,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:I},{Key:"Environment",Value:s}]}},P=N.GetAtt(C,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:P,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(f)E.Properties.TracingConfiguration={Enabled:f.enabled};return{stateMachine:E,logicalId:A,role:v,roleLogicalId:C}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class Eo{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:f=1,threshold:S,comparisonOperator:A,treatMissingData:v="notBreaching",actionsEnabled:C=!0,alarmActions:P,okActions:E,insufficientDataActions:I,dimensions:D,unit:x,datapointsToAlarm:O}=n,w=o||r({slug:i,environment:s,resourceType:"alarm"}),B=t(w),_={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:w,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:f,Threshold:S,ComparisonOperator:A,TreatMissingData:v,ActionsEnabled:C}};if(P&&P.length>0)_.Properties.AlarmActions=P;if(E&&E.length>0)_.Properties.OKActions=E;if(I&&I.length>0)_.Properties.InsufficientDataActions=I;if(D)_.Properties.Dimensions=Object.entries(D).map(([W,Z])=>({Name:W,Value:Z}));if(x)_.Properties.Unit=x;if(O!==void 0)_.Properties.DatapointsToAlarm=O;return{alarm:_,logicalId:B}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:f}=n,S=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),A=t(S),v={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)v.Properties.AlarmActions=u;if(h&&h.length>0)v.Properties.OKActions=h;if(f&&f.length>0)v.Properties.InsufficientDataActions=f;return{alarm:v,logicalId:A}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((S)=>({type:S.type,x:S.x,y:S.y,width:S.width,height:S.height,properties:S.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),f={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)f.Properties.RetentionInDays=c;if(l)f.Properties.KmsKeyId=l;return{logGroup:f,logicalId:h}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),f=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(n),FilterPattern:l,MetricTransformations:u.map((A)=>({MetricName:A.metricName,MetricNamespace:A.metricNamespace,MetricValue:A.metricValue,DefaultValue:A.defaultValue,Unit:A.unit}))}},logicalId:f}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2298
2275
  | fields @timestamp, @message
2299
2276
  | sort @timestamp desc
2300
2277
  | limit 20`,region:"us-east-1",title:l||"Logs"}})};static RetentionPeriods={ONE_DAY:1,THREE_DAYS:3,FIVE_DAYS:5,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,TWO_MONTHS:60,THREE_MONTHS:90,FOUR_MONTHS:120,FIVE_MONTHS:150,SIX_MONTHS:180,ONE_YEAR:365,THIRTEEN_MONTHS:400,EIGHTEEN_MONTHS:545,TWO_YEARS:731,FIVE_YEARS:1827,TEN_YEARS:3653,NEVER_EXPIRE:void 0};static FilterPatterns={errors:"[time, request_id, event_type = ERROR*, ...]",all:"",jsonField:(n,i)=>`{ $.${n} = "${i}" }`,httpStatus:(n)=>`[..., status_code = ${n}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(n){let{slug:i,environment:s,region:o="us-east-1",components:c={}}=n,l=[],u=0;if(l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:`# ${i.toUpperCase()} Dashboard (${s})`}}),u+=1,c.ec2InstanceIds&&c.ec2InstanceIds.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","CPUUtilization","InstanceId",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Network Traffic",region:o,metrics:[...c.ec2InstanceIds.flatMap((h)=>[["AWS/EC2","NetworkIn","InstanceId",h,{label:`${h} In`}],["AWS/EC2","NetworkOut","InstanceId",h,{label:`${h} Out`}]])],period:300,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Status Checks",region:o,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","StatusCheckFailed","InstanceId",h]),period:60,stat:"Maximum"}}),u+=6;if(c.lambdaFunctionNames&&c.lambdaFunctionNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Invocations",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Invocations","FunctionName",h]),period:300,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Duration",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Duration","FunctionName",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Errors",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Errors","FunctionName",h]),period:300,stat:"Sum"}}),u+=6;if(c.ecsClusterName&&c.ecsServiceName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## ECS Service"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/ECS","CPUUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Memory Utilization",region:o,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Running Tasks",region:o,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:60,stat:"Average"}}),u+=6;if(c.albName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Request Count",region:o,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",c.albName]],period:60,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Response Time",region:o,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",c.albName]],period:60,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"HTTP Errors",region:o,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",c.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",c.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),u+=6;if(c.rdsInstanceId)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## RDS Database"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Database Connections",region:o,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",c.rdsInstanceId]],period:60,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Free Storage Space",region:o,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),u+=6;if(c.sqsQueueNames&&c.sqsQueueNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## SQS Queues"}}),u+=1,l.push({type:"metric",x:0,y:u,width:12,height:6,properties:{title:"Messages Visible",region:o,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",h]),period:60,stat:"Sum"}}),l.push({type:"metric",x:12,y:u,width:12,height:6,properties:{title:"Message Age",region:o,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",h]),period:60,stat:"Maximum"}}),u+=6;if(c.logGroupNames&&c.logGroupNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Logs"}}),u+=1,l.push({type:"log",x:0,y:u,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
2301
2278
  | fields @timestamp, @message
2302
2279
  | filter @message like /ERROR|WARN|Exception/
2303
2280
  | sort @timestamp desc
2304
- | limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return Eo.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:f="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:f}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class V{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:f,smsConfiguration:S,lambdaTriggers:A,userPoolAddOns:v,accountRecoverySetting:C}=n,P=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(P),I={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:P,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)I.Properties.UsernameAttributes=c;if(l&&l.length>0)I.Properties.AutoVerifiedAttributes=l;if(f)I.Properties.EmailConfiguration={EmailSendingAccount:f.emailSendingAccount,From:f.from,ReplyToEmailAddress:f.replyToEmailAddress,SourceArn:f.sourceArn,ConfigurationSet:f.configurationSet};if(S)I.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(A)I.Properties.LambdaConfig={PreSignUp:A.preSignUp,PostConfirmation:A.postConfirmation,PreAuthentication:A.preAuthentication,PostAuthentication:A.postAuthentication,CustomMessage:A.customMessage,DefineAuthChallenge:A.defineAuthChallenge,CreateAuthChallenge:A.createAuthChallenge,VerifyAuthChallengeResponse:A.verifyAuthChallengeResponse,PreTokenGeneration:A.preTokenGeneration,UserMigration:A.userMigration};if(v)I.Properties.UserPoolAddOns={AdvancedSecurityMode:v.advancedSecurityMode};if(C)I.Properties.AccountRecoverySetting={RecoveryMechanisms:C.recoveryMechanisms};return{userPool:I,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:f,tokenValidityUnits:S,readAttributes:A,writeAttributes:v,explicitAuthFlows:C,preventUserExistenceErrors:P,enableTokenRevocation:E,callbackURLs:I,logoutURLs:D,allowedOAuthFlows:x,allowedOAuthScopes:O,allowedOAuthFlowsUserPoolClient:w,supportedIdentityProviders:B}=i,_=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),K=t(_);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:_,UserPoolId:N.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:f,TokenValidityUnits:S,ReadAttributes:A,WriteAttributes:v,ExplicitAuthFlows:C,PreventUserExistenceErrors:P,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:D,AllowedOAuthFlows:x,AllowedOAuthScopes:O,AllowedOAuthFlowsUserPoolClient:w,SupportedIdentityProviders:B}},logicalId:K}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:f}=n,S=o||r({slug:i,environment:s,resourceType:"identity-pool"}),A=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:f}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),f=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(n),Roles:S,RoleMappings:u}},logicalId:f}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=V.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:V.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=V.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...V.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...V.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=V.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:V.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=V.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...V.AuthFlows.standard]}),{identityPool:u,logicalId:h}=V.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(o,"ProviderName")}]}),{role:f,logicalId:S}=V.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:A,logicalId:v}=V.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:f,authRoleId:S,attachment:A,attachmentId:v}}}}import{createHash as Ar}from"node:crypto";import{copyFileSync as Cr,existsSync as Rt,readdirSync as vr,readFileSync as tt,statSync as Tr,writeFileSync as nt}from"node:fs";import{basename as Rr,dirname as pn,extname as gn,join as Ue}from"node:path";class q{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:f,autoRollbackConfiguration:S,alarmConfiguration:A,loadBalancerInfo:v,blueGreenDeploymentConfiguration:C}=i,P=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(P);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(n),DeploymentGroupName:P,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((D)=>({Key:D.key,Value:D.value,Type:D.type})),DeploymentConfigName:f,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:A?{Enabled:A.enabled,Alarms:A.alarms?.map((D)=>({Name:D.name})),IgnorePollAlarmFailure:A.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:v?{TargetGroupInfoList:v.targetGroupInfoList?.map((D)=>({Name:D.name})),ElbInfoList:v.elbInfoList?.map((D)=>({Name:D.name}))}:void 0,BlueGreenDeploymentConfiguration:C?{TerminateBlueInstancesOnDeploymentSuccess:C.terminateBlueInstancesOnDeploymentSuccess?{Action:C.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:C.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:C.deploymentReadyOption?{ActionOnTimeout:C.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:C.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:C.greenFleetProvisioningOption?{Action:C.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=q.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=q.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=q.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:f}=q.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:q.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:A}=q.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:N.Ref(f),autoRollbackConfiguration:q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:f,deploymentGroup:S,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=q.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=q.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:q.BlueGreenConfigs.standard(),autoRollbackConfiguration:q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class k{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=tt(n);return Ar(i).update(s).digest("hex")}static computeShortHash(n){return k.computeFileHash(n).slice(0,8)}static getContentType(n){let i=gn(n).toLowerCase();return k.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...k.NoHashPatterns,...i||[]].some((o)=>o.test(n))}static generateHashedFilename(n,i){let s=gn(n),o=Rr(n,s),c=pn(n);if(c===".")return`${o}.${i}${s}`;return Ue(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Rt(n))return s;let c=vr(n,{withFileTypes:!0});for(let l of c){let u=Ue(n,l.name);if(l.isDirectory())s.push(...k.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=k.collectFiles(i),h=[],f={};for(let A of u){let v=A.replace(i,"").replace(/^[/\\]/,""),C=k.shouldHashFile(v,o),P=Tr(A),E=C?k.computeFileHash(A,c).slice(0,8):"",I=C?k.generateHashedFilename(v,E):v,D={originalPath:v,hashedPath:I,hash:E,size:P.size,contentType:k.getContentType(A)};if(h.push(D),f[v]=I,s){let x=Ue(s,I),O=pn(x);if(!Rt(O)){let{mkdirSync:w}=he("node:fs");w(O,{recursive:!0})}if(C||l)Cr(A,x)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:f};if(s){let A=Ue(s,"asset-manifest.json");nt(A,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=k.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=tt(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=[new RegExp(`(src|href)=["']${o}/?${k.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(h)}["']?\\)`,"g")];for(let A of S)u=u.replace(A,(v)=>v.replace(h,f))}nt(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=k.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=tt(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${f})`)}nt(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return k.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((u)=>{let h=u.hash!=="",f=u.contentType==="text/html",S=c.unhashed||"public, max-age=3600";if(f)S=c.html||"public, max-age=0, must-revalidate";else if(h)S=c.hashed||"public, max-age=31536000, immutable";return{localPath:Ue(i,u.originalPath),s3Key:s?`${s}/${u.hashedPath}`:u.hashedPath,contentType:u.contentType,cacheControl:S,hash:u.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Rt(n))return null;try{let i=tt(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){nt(i,JSON.stringify(n,null,2))}}class $i{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,f=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(f),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:c,SecretString:l,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},...h?Object.entries(h).map(([v,C])=>({Key:v,Value:C})):[]]}};if(u)A.Properties.KmsKeyId=u;return{secret:A,logicalId:S}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:f,excludeUppercase:S,passwordLength:A,requireEachIncludedType:v,kmsKeyId:C,tags:P}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),I=t(E),D={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:f,ExcludeUppercase:S,PasswordLength:A||32,RequireEachIncludedType:v!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...P?Object.entries(P).map(([x,O])=>({Key:x,Value:O})):[]]}};if(C)D.Properties.KmsKeyId=C;return{secret:D,logicalId:I}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:f,kmsKeyId:S}=n,A=o||r({slug:i,environment:s,resourceType:"db-secret"}),v=t(A),C={username:c};if(l)C.dbname=l;if(u)C.engine=u;if(h)C.host=h;if(f)C.port=f;let P={Type:"AWS::SecretsManager::Secret",Properties:{Name:A,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(C),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(S)P.Properties.KmsKeyId=S;return{secret:P,logicalId:v}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:f,vpcSubnetIds:S}=n,A=r({slug:i,environment:s,resourceType:"secret-rotation"}),v=t(A),C={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)C.Properties.RotationLambdaARN=c;else if(u)C.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:f,VpcSubnetIds:S};return{rotation:C,logicalId:v}}static SecretTypes={apiKey:(n,i,s)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class T{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:f}=n,S=o||r({slug:i,environment:s,resourceType:"parameter"}),A=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:s,...f}}},logicalId:A}}static createString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>T.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>T.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>T.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>T.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>T.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=T.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=T.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=T.createString(n,i,"smtp-username",s,"SMTP username"),h=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),f=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:f,port:S}},redisUrl:(n,i,s)=>T.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>T.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>T.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class Jt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:f="gp3",dedicatedMaster:S=!1,dedicatedMasterType:A,dedicatedMasterCount:v=3,multiAz:C=!1,availabilityZoneCount:P=2,vpc:E,encryption:I,enforceHttps:D=!0,tlsSecurityPolicy:x="Policy-Min-TLS-1-2-2019-07",advancedSecurity:O,autoSnapshotHour:w=0,autoTune:B=!0,tags:_={}}=n,K=o||r({slug:i,environment:s,resourceType:"search"}),Z=t(K);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:K,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:A||l,DedicatedMasterCount:v},ZoneAwarenessEnabled:C,...C&&{ZoneAwarenessConfig:{AvailabilityZoneCount:P}}},EBSOptions:{EBSEnabled:!0,VolumeType:f,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:D,TLSSecurityPolicy:x},SnapshotOptions:{AutomatedSnapshotStartHour:w},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...I&&{EncryptionAtRestOptions:{Enabled:I.atRest??!0,...I.kmsKeyId&&{KmsKeyId:I.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:I.nodeToNode??!0}},...O&&{AdvancedSecurityOptions:{Enabled:O.enabled,InternalUserDatabaseEnabled:O.internalUserDatabase??!0,...O.masterUserName&&O.masterUserPassword&&{MasterUserOptions:{MasterUserName:O.masterUserName,MasterUserPassword:O.masterUserPassword}},...O.masterUserArn&&{MasterUserOptions:{MasterUserARN:O.masterUserArn}}}},...B&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:K},{Key:"Environment",Value:s},...Object.entries(_).map(([Y,X])=>({Key:Y,Value:X}))]}},logicalId:Z}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>Jt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>Jt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>Jt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>Jt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class bt{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),f=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},A={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:A,logicalId:h,policyLogicalId:f}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=bt.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
2281
+ | limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return Eo.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:f="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:f}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class V{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:f,smsConfiguration:S,lambdaTriggers:A,userPoolAddOns:v,accountRecoverySetting:C}=n,P=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(P),I={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:P,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)I.Properties.UsernameAttributes=c;if(l&&l.length>0)I.Properties.AutoVerifiedAttributes=l;if(f)I.Properties.EmailConfiguration={EmailSendingAccount:f.emailSendingAccount,From:f.from,ReplyToEmailAddress:f.replyToEmailAddress,SourceArn:f.sourceArn,ConfigurationSet:f.configurationSet};if(S)I.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(A)I.Properties.LambdaConfig={PreSignUp:A.preSignUp,PostConfirmation:A.postConfirmation,PreAuthentication:A.preAuthentication,PostAuthentication:A.postAuthentication,CustomMessage:A.customMessage,DefineAuthChallenge:A.defineAuthChallenge,CreateAuthChallenge:A.createAuthChallenge,VerifyAuthChallengeResponse:A.verifyAuthChallengeResponse,PreTokenGeneration:A.preTokenGeneration,UserMigration:A.userMigration};if(v)I.Properties.UserPoolAddOns={AdvancedSecurityMode:v.advancedSecurityMode};if(C)I.Properties.AccountRecoverySetting={RecoveryMechanisms:C.recoveryMechanisms};return{userPool:I,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:f,tokenValidityUnits:S,readAttributes:A,writeAttributes:v,explicitAuthFlows:C,preventUserExistenceErrors:P,enableTokenRevocation:E,callbackURLs:I,logoutURLs:D,allowedOAuthFlows:x,allowedOAuthScopes:O,allowedOAuthFlowsUserPoolClient:w,supportedIdentityProviders:B}=i,_=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),W=t(_);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:_,UserPoolId:N.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:f,TokenValidityUnits:S,ReadAttributes:A,WriteAttributes:v,ExplicitAuthFlows:C,PreventUserExistenceErrors:P,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:D,AllowedOAuthFlows:x,AllowedOAuthScopes:O,AllowedOAuthFlowsUserPoolClient:w,SupportedIdentityProviders:B}},logicalId:W}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:f}=n,S=o||r({slug:i,environment:s,resourceType:"identity-pool"}),A=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:f}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),f=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(n),Roles:S,RoleMappings:u}},logicalId:f}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=V.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:V.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=V.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...V.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...V.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=V.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:V.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=V.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...V.AuthFlows.standard]}),{identityPool:u,logicalId:h}=V.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(o,"ProviderName")}]}),{role:f,logicalId:S}=V.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:A,logicalId:v}=V.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:f,authRoleId:S,attachment:A,attachmentId:v}}}}import{createHash as Ar}from"node:crypto";import{copyFileSync as Cr,existsSync as Rt,readdirSync as vr,readFileSync as tt,statSync as Tr,writeFileSync as nt}from"node:fs";import{basename as Rr,dirname as pn,extname as gn,join as Ve}from"node:path";class q{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:f,autoRollbackConfiguration:S,alarmConfiguration:A,loadBalancerInfo:v,blueGreenDeploymentConfiguration:C}=i,P=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(P);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(n),DeploymentGroupName:P,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((D)=>({Key:D.key,Value:D.value,Type:D.type})),DeploymentConfigName:f,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:A?{Enabled:A.enabled,Alarms:A.alarms?.map((D)=>({Name:D.name})),IgnorePollAlarmFailure:A.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:v?{TargetGroupInfoList:v.targetGroupInfoList?.map((D)=>({Name:D.name})),ElbInfoList:v.elbInfoList?.map((D)=>({Name:D.name}))}:void 0,BlueGreenDeploymentConfiguration:C?{TerminateBlueInstancesOnDeploymentSuccess:C.terminateBlueInstancesOnDeploymentSuccess?{Action:C.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:C.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:C.deploymentReadyOption?{ActionOnTimeout:C.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:C.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:C.greenFleetProvisioningOption?{Action:C.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=q.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=q.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=q.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:f}=q.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:q.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:A}=q.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:N.Ref(f),autoRollbackConfiguration:q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:f,deploymentGroup:S,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=q.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=q.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:q.BlueGreenConfigs.standard(),autoRollbackConfiguration:q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class k{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=tt(n);return Ar(i).update(s).digest("hex")}static computeShortHash(n){return k.computeFileHash(n).slice(0,8)}static getContentType(n){let i=gn(n).toLowerCase();return k.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...k.NoHashPatterns,...i||[]].some((o)=>o.test(n))}static generateHashedFilename(n,i){let s=gn(n),o=Rr(n,s),c=pn(n);if(c===".")return`${o}.${i}${s}`;return Ve(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Rt(n))return s;let c=vr(n,{withFileTypes:!0});for(let l of c){let u=Ve(n,l.name);if(l.isDirectory())s.push(...k.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=k.collectFiles(i),h=[],f={};for(let A of u){let v=A.replace(i,"").replace(/^[/\\]/,""),C=k.shouldHashFile(v,o),P=Tr(A),E=C?k.computeFileHash(A,c).slice(0,8):"",I=C?k.generateHashedFilename(v,E):v,D={originalPath:v,hashedPath:I,hash:E,size:P.size,contentType:k.getContentType(A)};if(h.push(D),f[v]=I,s){let x=Ve(s,I),O=pn(x);if(!Rt(O)){let{mkdirSync:w}=Xe("node:fs");w(O,{recursive:!0})}if(C||l)Cr(A,x)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:f};if(s){let A=Ve(s,"asset-manifest.json");nt(A,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=k.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=tt(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=[new RegExp(`(src|href)=["']${o}/?${k.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(h)}["']?\\)`,"g")];for(let A of S)u=u.replace(A,(v)=>v.replace(h,f))}nt(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=k.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=tt(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${f})`)}nt(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return k.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((u)=>{let h=u.hash!=="",f=u.contentType==="text/html",S=c.unhashed||"public, max-age=3600";if(f)S=c.html||"public, max-age=0, must-revalidate";else if(h)S=c.hashed||"public, max-age=31536000, immutable";return{localPath:Ve(i,u.originalPath),s3Key:s?`${s}/${u.hashedPath}`:u.hashedPath,contentType:u.contentType,cacheControl:S,hash:u.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Rt(n))return null;try{let i=tt(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){nt(i,JSON.stringify(n,null,2))}}class $i{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,f=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(f),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:c,SecretString:l,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},...h?Object.entries(h).map(([v,C])=>({Key:v,Value:C})):[]]}};if(u)A.Properties.KmsKeyId=u;return{secret:A,logicalId:S}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:f,excludeUppercase:S,passwordLength:A,requireEachIncludedType:v,kmsKeyId:C,tags:P}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),I=t(E),D={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:f,ExcludeUppercase:S,PasswordLength:A||32,RequireEachIncludedType:v!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...P?Object.entries(P).map(([x,O])=>({Key:x,Value:O})):[]]}};if(C)D.Properties.KmsKeyId=C;return{secret:D,logicalId:I}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:f,kmsKeyId:S}=n,A=o||r({slug:i,environment:s,resourceType:"db-secret"}),v=t(A),C={username:c};if(l)C.dbname=l;if(u)C.engine=u;if(h)C.host=h;if(f)C.port=f;let P={Type:"AWS::SecretsManager::Secret",Properties:{Name:A,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(C),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(S)P.Properties.KmsKeyId=S;return{secret:P,logicalId:v}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:f,vpcSubnetIds:S}=n,A=r({slug:i,environment:s,resourceType:"secret-rotation"}),v=t(A),C={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)C.Properties.RotationLambdaARN=c;else if(u)C.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:f,VpcSubnetIds:S};return{rotation:C,logicalId:v}}static SecretTypes={apiKey:(n,i,s)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>$i.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class T{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:f}=n,S=o||r({slug:i,environment:s,resourceType:"parameter"}),A=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:s,...f}}},logicalId:A}}static createString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>T.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>T.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>T.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>T.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>T.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=T.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=T.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=T.createString(n,i,"smtp-username",s,"SMTP username"),h=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),f=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:f,port:S}},redisUrl:(n,i,s)=>T.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>T.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>T.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class Jt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:f="gp3",dedicatedMaster:S=!1,dedicatedMasterType:A,dedicatedMasterCount:v=3,multiAz:C=!1,availabilityZoneCount:P=2,vpc:E,encryption:I,enforceHttps:D=!0,tlsSecurityPolicy:x="Policy-Min-TLS-1-2-2019-07",advancedSecurity:O,autoSnapshotHour:w=0,autoTune:B=!0,tags:_={}}=n,W=o||r({slug:i,environment:s,resourceType:"search"}),Z=t(W);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:W,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:A||l,DedicatedMasterCount:v},ZoneAwarenessEnabled:C,...C&&{ZoneAwarenessConfig:{AvailabilityZoneCount:P}}},EBSOptions:{EBSEnabled:!0,VolumeType:f,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:D,TLSSecurityPolicy:x},SnapshotOptions:{AutomatedSnapshotStartHour:w},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...I&&{EncryptionAtRestOptions:{Enabled:I.atRest??!0,...I.kmsKeyId&&{KmsKeyId:I.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:I.nodeToNode??!0}},...O&&{AdvancedSecurityOptions:{Enabled:O.enabled,InternalUserDatabaseEnabled:O.internalUserDatabase??!0,...O.masterUserName&&O.masterUserPassword&&{MasterUserOptions:{MasterUserName:O.masterUserName,MasterUserPassword:O.masterUserPassword}},...O.masterUserArn&&{MasterUserOptions:{MasterUserARN:O.masterUserArn}}}},...B&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:s},...Object.entries(_).map(([Y,X])=>({Key:Y,Value:X}))]}},logicalId:Z}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>Jt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>Jt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>Jt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>Jt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class bt{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),f=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},A={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:A,logicalId:h,policyLogicalId:f}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=bt.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
2305
2282
  const request = event.request;
2306
2283
  const uri = request.uri;
2307
2284
  const querystring = request.querystring;
@@ -2453,7 +2430,7 @@ exports.handler = async (event) => {
2453
2430
  console.log('Receive SMS:', JSON.stringify(event, null, 2));
2454
2431
  // Process inbound SMS, handle opt-out keywords
2455
2432
  return { statusCode: 200 };
2456
- };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},Wr={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},gI={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 yn(n,i){if(i.type==="http")Pr(n,i);else if(i.type==="rest")Er(n,i);else if(i.type==="websocket")Ir(n,i)}function Pr(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)wr(n,"HttpApi",i.authorizer);if(i.customDomain)Pt(n,"HttpApi",i.customDomain,"HTTP");n.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Er(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Pt(n,"RestApi",i.customDomain,"REST");n.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)rt(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)rt(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)rt(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{rt(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Pt(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function rt(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),l=n.toLogicalId(`${s}-function`);n.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Pt(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Dr(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function wr(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function Dr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function hn(n,i){if(i.redis)Nr(n,i.redis);if(i.memcached)xr(n,i.memcached);if(i.elasticache)kr(n,i.elasticache)}function Nr(n,i){if(!i)return;if(n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function xr(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),n.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function kr(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function fn(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.origins.forEach((u,h)=>{let f={Id:u.id,DomainName:u.domainName};if(u.originPath)f.OriginPath=u.originPath;if(u.domainName.includes("s3"))f.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(s.push(f),h>0||u.pathPattern)o.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)l.CacheBehaviors=o;if(i.customDomain)l.Aliases=[i.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)l.CustomErrorResponses=Object.entries(i.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Mr(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function Mr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Sn(n,i){if(i.server)Lr(n,i.server);if(i.fargate)bn(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")bn(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function Lr(n,i){if(!i)return;n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),n.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2433
+ };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},Wr={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},CI={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 yn(n,i){if(i.type==="http")Pr(n,i);else if(i.type==="rest")Er(n,i);else if(i.type==="websocket")Ir(n,i)}function Pr(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)wr(n,"HttpApi",i.authorizer);if(i.customDomain)Pt(n,"HttpApi",i.customDomain,"HTTP");n.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Er(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Pt(n,"RestApi",i.customDomain,"REST");n.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)rt(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)rt(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)rt(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{rt(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Pt(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function rt(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),l=n.toLogicalId(`${s}-function`);n.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Pt(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Dr(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function wr(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function Dr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function hn(n,i){if(i.redis)Nr(n,i.redis);if(i.memcached)xr(n,i.memcached);if(i.elasticache)kr(n,i.elasticache)}function Nr(n,i){if(!i)return;if(n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function xr(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),n.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function kr(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function fn(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.origins.forEach((u,h)=>{let f={Id:u.id,DomainName:u.domainName};if(u.originPath)f.OriginPath=u.originPath;if(u.domainName.includes("s3"))f.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(s.push(f),h>0||u.pathPattern)o.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)l.CacheBehaviors=o;if(i.customDomain)l.Aliases=[i.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)l.CustomErrorResponses=Object.entries(i.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Mr(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function Mr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Sn(n,i){if(i.server)Lr(n,i.server);if(i.fargate)bn(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")bn(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function Lr(n,i){if(!i)return;n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),n.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2457
2434
  set -e
2458
2435
  # Update system
2459
2436
  yum update -y || apt-get update -y
@@ -2474,30 +2451,30 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2474
2451
  };`},Environment:i.environment?{Variables:i.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(s!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(n.addResource(o,"AWS::Lambda::Function",l,{dependsOn:c}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${i.name}`),RetentionInDays:14}),i.events)i.events.forEach((u,h)=>{Fr(n,o,u,h)});n.addOutputs({[`${o}Arn`]:{Description:`${i.name} function ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-function-arn`)}}})}function Fr(n,i,s,o){let c=`${i}EventSource${o}`;switch(s.type){case"http":break;case"s3":if(s.bucket){let l=n.toLogicalId(`${s.bucket}-bucket`);n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:Wr.s3Bucket(e.ref(l))},{dependsOn:[i,l]})}break;case"sqs":if(s.queueName){let l=n.toLogicalId(`${s.queueName}-queue`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||10},{dependsOn:[i,l]})}break;case"kinesis":if(s.streamName){let l=n.toLogicalId(`${s.streamName}-stream`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST",ParallelizationFactor:s.parallelizationFactor||1},{dependsOn:[i,l]})}break;case"dynamodb-stream":if(s.tableName){let l=n.toLogicalId(`${s.tableName}-table`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"StreamArn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST"},{dependsOn:[i,l]})}break;case"schedule":if(s.expression)n.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:s.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(i,"Arn"),Id:`${i}Target`}]},{dependsOn:i}),n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[i,`${c}Rule`]});break}}function Gr(n){let i=[];if(!n)return i;if(n.forEach((s)=>{switch(s.type){case"s3":i.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:s.bucket?`arn:aws:s3:::${s.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":i.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:s.queueName?Wr.sqs(s.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":i.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:s.streamName?Wr.kinesis(s.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":i.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:s.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),i.length===0)i.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return i}function Tn(n,i){if(i.topics)i.topics.forEach((s)=>{_r(n,s)})}function _r(n,i){let s=n.toLogicalId(`${i.name}-topic`);if(n.addResource(s,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${i.name}`),DisplayName:i.displayName||i.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]}),n.addResource(`${s}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:e.ref(s)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(s)}]}},{dependsOn:s}),i.subscriptions)i.subscriptions.forEach((o,c)=>{let l=`${s}Subscription${c+1}`,u={Protocol:o.protocol,TopicArn:e.ref(s),Endpoint:o.endpoint};if(o.filterPolicy)u.FilterPolicy=o.filterPolicy;if(o.protocol==="sqs"){let h=n.toLogicalId(`${o.endpoint}-queue`);u.Endpoint=e.getAtt(h,"Arn")}if(o.protocol==="lambda"){let h=n.toLogicalId(o.endpoint);u.Endpoint=e.getAtt(h,"Arn"),n.addResource(`${l}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(h),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(s)},{dependsOn:[h,s]})}n.addResource(l,"AWS::SNS::Subscription",u,{dependsOn:s})});n.addOutputs({[`${s}Arn`]:{Description:`${i.name} topic ARN`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-topic-arn`)}}})}function Rn(n,i){if(i.alarms&&i.alarms.length>0)n.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),i.alarms.forEach((s,o)=>{Vr(n,s,o)});if(i.dashboard)Ur(n,i.dashboard);if(i.logs?.groups)i.logs.groups.forEach((s)=>{Hr(n,s,i.logs?.retention)})}function Vr(n,i,s){let o=n.toLogicalId(`alarm-${i.name||i.metric}-${s}`),c={AlarmName:i.name||e.sub(`\${AWS::StackName}-${i.metric}`),AlarmDescription:`Alarm for ${i.metric}`,MetricName:i.metric,Namespace:i.namespace||Et(i.metric,i.service),Statistic:i.statistic||"Average",Period:i.period||300,EvaluationPeriods:i.evaluationPeriods||1,Threshold:i.threshold,ComparisonOperator:i.comparisonOperator||"GreaterThanThreshold",TreatMissingData:i.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(i.dimensions)c.Dimensions=Object.entries(i.dimensions).map(([l,u])=>({Name:l,Value:u}));else if(i.service)c.Dimensions=jr(i.service);n.addResource(o,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function Ur(n,i){if(!i)return;let s=[],o=0,c=0;i.widgets?.forEach((l)=>{let u=l.width||12,h=l.height||6;if(l.type==="metric"&&l.metrics){let f=l.metrics.map((S)=>{if(typeof S==="string")return[Et(S),S];else return[Et(S.metric,S.service),S.metric]});s.push({type:"metric",x:o,y:c,width:u,height:h,properties:{metrics:f,period:300,stat:"Average",region:e.ref("AWS::Region"),title:l.metrics.length>1?"Multiple Metrics":typeof l.metrics[0]==="string"?l.metrics[0]:l.metrics[0].metric}})}else if(l.type==="log"&&l.logGroup)s.push({type:"log",x:o,y:c,width:u,height:h,properties:{query:`SOURCE '${l.logGroup}'
2475
2452
  | fields @timestamp, @message
2476
2453
  | sort @timestamp desc
2477
- | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)s.push({type:"text",x:o,y:c,width:u,height:h,properties:{markdown:l.text}});if(o+=u,o>=24)o=0,c+=h}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function Hr(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function Et(n,i){if(i)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function jr(n){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[n.toLowerCase()]||[]}function Pn(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let v=0;v<o;v++){let C=`PublicSubnet${v+1}`;h.push(C),n.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(v,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(v,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${v+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let f=[];for(let v=0;v<o;v++){let C=`PrivateSubnet${v+1}`;f.push(C),n.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(v+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(v,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${v+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let S=[];for(let v=0;v<c;v++){let C=`NatEIP${v+1}`;S.push(C),n.addResource(C,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${v+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let A=[];for(let v=0;v<c;v++){let C=`NatGateway${v+1}`;A.push(C);let P=v%o;n.addResource(C,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(S[v],"AllocationId"),SubnetId:e.ref(h[P]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${v+1}`)}]},{dependsOn:[S[v],h[P]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((v,C)=>{n.addResource(`PublicSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(v),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[v,"PublicRouteTable"]})}),f.forEach((v,C)=>{let P=`PrivateRouteTable${C+1}`,E=C%c;n.addResource(P,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${C+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${C+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(P),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(A[E])},{dependsOn:[P,A[E]]}),n.addResource(`PrivateSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(v),RouteTableId:e.ref(P)},{dependsOn:[v,P]})}),n.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:o},(v,C)=>e.ref(`PrivateRouteTable${C+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((v)=>e.ref(v))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",f.map((v)=>e.ref(v))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function En(n,i){for(let[s,o]of Object.entries(i))qr(n,s,o)}function qr(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,l;if(s.deadLetterQueue){let h=`${o}DLQ`;n.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",u,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function In(n,i){if(i.certificate)Qr(n,i.certificate);if(i.waf?.enabled)ei(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))ti(n,s,o)}function Qr(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ei(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function ti(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=s.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function wn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){ri(n,s,o);continue}ni(n,s,o)}}function ni(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[Wr.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function ri(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)n.addResource(`${o}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${u+1}`]});n.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class Xp{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((o)=>this.resourceDependencies.get(n).add(o))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let l of c)s(l);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){Pn(this,n)}addStorageResources(n){wn(this,n)}addComputeResources(n){Sn(this,n)}addDatabaseResources(n){Cn(this,n)}addFunctionResources(n){vn(this,n)}addCacheResources(n){hn(this,n)}addQueueResources(n){En(this,n)}addMessagingResources(n){Tn(this,n)}addCDNResources(n){fn(this,n)}addApiGatewayResources(n){yn(this,n)}addMonitoringResources(n){Rn(this,n)}addSecurityResources(n){In(this,n)}}function qd(n){return new Xp(n).build()}function pI(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function mI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function fI(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${s}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${s}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function hI(n){let{name:i,slug:s,entry:o,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:f,assets:S,queues:A=!0,scheduler:v="on",region:C="us-east-1"}=n;return{project:{name:i,slug:s,region:C},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:o,memory:u,build:h,deploy:f,assets:S,queues:A,scheduler:v,domain:c}}}}}function jd(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function yI(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${s}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${o}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function SI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function II(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function bI(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[o],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function CI(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${s}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${s}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${s}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${s}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${s}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function EI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${s}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${s}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function vI(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${s}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function TI(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:l="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${s}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function wI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:f="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
2454
+ | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)s.push({type:"text",x:o,y:c,width:u,height:h,properties:{markdown:l.text}});if(o+=u,o>=24)o=0,c+=h}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function Hr(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function Et(n,i){if(i)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function jr(n){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[n.toLowerCase()]||[]}function Pn(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let v=0;v<o;v++){let C=`PublicSubnet${v+1}`;h.push(C),n.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(v,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(v,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${v+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let f=[];for(let v=0;v<o;v++){let C=`PrivateSubnet${v+1}`;f.push(C),n.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(v+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(v,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${v+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let S=[];for(let v=0;v<c;v++){let C=`NatEIP${v+1}`;S.push(C),n.addResource(C,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${v+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let A=[];for(let v=0;v<c;v++){let C=`NatGateway${v+1}`;A.push(C);let P=v%o;n.addResource(C,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(S[v],"AllocationId"),SubnetId:e.ref(h[P]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${v+1}`)}]},{dependsOn:[S[v],h[P]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((v,C)=>{n.addResource(`PublicSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(v),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[v,"PublicRouteTable"]})}),f.forEach((v,C)=>{let P=`PrivateRouteTable${C+1}`,E=C%c;n.addResource(P,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${C+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${C+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(P),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(A[E])},{dependsOn:[P,A[E]]}),n.addResource(`PrivateSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(v),RouteTableId:e.ref(P)},{dependsOn:[v,P]})}),n.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:o},(v,C)=>e.ref(`PrivateRouteTable${C+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((v)=>e.ref(v))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",f.map((v)=>e.ref(v))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function En(n,i){for(let[s,o]of Object.entries(i))qr(n,s,o)}function qr(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,l;if(s.deadLetterQueue){let h=`${o}DLQ`;n.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",u,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function In(n,i){if(i.certificate)Qr(n,i.certificate);if(i.waf?.enabled)ei(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))ti(n,s,o)}function Qr(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ei(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function ti(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=s.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function wn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){ri(n,s,o);continue}ni(n,s,o)}}function ni(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[Wr.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function ri(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)n.addResource(`${o}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${u+1}`]});n.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class nm{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((o)=>this.resourceDependencies.get(n).add(o))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let l of c)s(l);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){Pn(this,n)}addStorageResources(n){wn(this,n)}addComputeResources(n){Sn(this,n)}addDatabaseResources(n){Cn(this,n)}addFunctionResources(n){vn(this,n)}addCacheResources(n){hn(this,n)}addQueueResources(n){En(this,n)}addMessagingResources(n){Tn(this,n)}addCDNResources(n){fn(this,n)}addApiGatewayResources(n){yn(this,n)}addMonitoringResources(n){Rn(this,n)}addSecurityResources(n){In(this,n)}}function zd(n){return new nm(n).build()}function EI(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function vI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function TI(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${s}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${s}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function wI(n){let{name:i,slug:s,entry:o,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:f,assets:S,queues:A=!0,scheduler:v="on",region:C="us-east-1"}=n;return{project:{name:i,slug:s,region:C},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:o,memory:u,build:h,deploy:f,assets:S,queues:A,scheduler:v,domain:c}}}}}function Kd(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function RI(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${s}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${o}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function DI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function PI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function NI(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[o],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function kI(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${s}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${s}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${s}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${s}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${s}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function BI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${s}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${s}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function xI(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${s}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function OI(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:l="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${s}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function _I(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:f="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,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
2478
2455
  # Install Node.js or PHP/Python based on app needs
2479
2456
  # Configure application server (PM2, Nginx, Apache)
2480
2457
  # Mount EFS for shared file storage
2481
- `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="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:f==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...f==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function RI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:h=s.replace(/-/g,"_"),databasePassword:f,sslEmail:S,deployStrategy:A="push",provider:v="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:v},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:f}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:l,repository:{...c,strategy:A},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:S}}}}}function DI(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:f,deploy:S=["migrate --force"],cache:A="dynamodb",scheduler:v="on",region:C="us-east-1"}=n;return{project:{name:i,slug:s,region:C},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:f,deploy:S,assets:"public",queues:!0,scheduler:v,cache:{driver:A},domain:o}}}}}function PI(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var wA=Nd,RA="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function ii(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function si(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var DA=20000,PA=12000;function NA(n){return DA+si(n)%PA}function Dn(n,i){let s=ii(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function Nn(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")s.push(u);else if(Array.isArray(u))s.push(...u.filter((h)=>typeof h==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function kA(n,i,s){if(s)return s;let o=Nn(n,i),c=o[0];if(!c)return null;return Dn(c,o)}function BA(n,i,s){if(s)return[s];let o=Nn(n,i),c=[];for(let l of o){let u=Dn(l,o);if(!c.includes(u))c.push(u)}return c}function Xt(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return Jr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var Yp="dashboard-";function Zp(n){return Yp+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function Jr(n){return n==="dashboard"||n.startsWith(Yp)}function Mi(n,i,s){if(Xt(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let u=kA(n,i,s.domain);if(!u)return[];let h=s.port??NA(u),f=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,S={root:s.uiRoot,deploy:"server",domain:u,preStart:["bun install --production --no-save"],start:`bun ${RA} --box --host 127.0.0.1 --port ${h}`,port:h,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...f?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:f.password}:{}},zeroDowntime:!1,sharedPaths:[wA],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Zp(u),site:S}]}return BA(n,i,s.domain).map((u)=>({name:Zp(u),site:{root:s.uiRoot,deploy:"server",type:"static",domain:u,ssl:{provider:"letsencrypt"},...c,...o}}))}function NI(n,i,s){return Mi(n,i,s)[0]??null}function wt(n,i){let s={...n};for(let o in i){let c=i[o],l=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))s[o]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))s[o]=wt(l,c);else s[o]=c}return s}function em(n,i){return wt(n,i)}function kI(...n){return n.reduce((i,s)=>wt(i,s),{})}function BI(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return em(o,i(o,s));return em(o,i)}}function Xr(n){return{infrastructure:n}}function xI(n){return Xr({monitoring:n})}function OI(n){return Xr({security:n})}function _I(n){return Xr({databases:n})}function LI(n){return Xr({cache:n})}function $I(n){return Xr({cdn:n})}function MI(n){return Xr({queues:n})}import{existsSync as xn,readFileSync as Dt}from"node:fs";import{homedir as kn}from"node:os";import{join as Mn}from"node:path";function xA(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function OA(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||Mn(kn(),".aws","credentials");if(!xn(s))return null;try{let o=Dt(s,"utf-8");return ai(o,i)}catch{return null}}function ai(n,i){let s=n.split(`
2482
- `),o=null,c,l,u;for(let h of s){let f=h.trim();if(!f||f.startsWith("#")||f.startsWith(";"))continue;let S=f.match(/^\[([^\]]+)\]$/);if(S){if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};o=S[1],c=void 0,l=void 0,u=void 0;continue}if(o===i){let[A,...v]=f.split("="),C=v.join("=").trim();switch(A.trim().toLowerCase()){case"aws_access_key_id":c=C;break;case"aws_secret_access_key":l=C;break;case"aws_session_token":u=C;break}}}if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function _A(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await je("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),l=await je("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!l.ok)return null;let u=(await l.text()).trim(),h=await je(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function LA(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await je(c,{headers:l},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function $A(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let l=Dt(s,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,f=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),S=await je(`${h}/?${f.toString()}`,{method:"POST"},i);if(!S.ok)return null;let A=await S.text(),v=He(A,"AccessKeyId"),C=He(A,"SecretAccessKey"),P=He(A,"SessionToken"),E=He(A,"Expiration");if(!v||!C)return null;return{accessKeyId:v,secretAccessKey:C,sessionToken:P??void 0,expiration:E?new Date(E):void 0}}catch{return null}}async function Fi(n){let i=xA();if(i)return i;let s=OA(n);if(s)return s;let o=await $A(n);if(o)return o;let c=await LA(n);if(c)return c;let l=await _A(n);if(l)return l;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 FI(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=Fi(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function je(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let l=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function He(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function vo(n){return Fi({profile:n})}function MA(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=Mn(kn(),".aws","config");if(xn(s))try{let o=Dt(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=o.split(`
2483
- `),h=!1;for(let f of u){let S=f.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,A]=S.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function tm(n){let i=n||await Fi(),s=MA(),{signRequest:o}=await import("./chunk-fz62nas4.js"),c=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,l="Action=GetCallerIdentity&Version=2011-06-15",u=o({method:"POST",url:c,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),h=await fetch(u.url,{method:u.method,headers:u.headers,body:u.body});if(!h.ok)throw Error(`Failed to get account ID: ${await h.text()}`);let f=await h.text(),S=He(f,"Account");if(!S)throw Error("Failed to parse account ID from response");return S}var oi=5242880,Nt=5242880;var ci=5242880;class xt{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Fi(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=R({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok&&f.status!==304){let S=await f.text();throw new M(`Failed to get object: ${S}`,f.status,n,i)}return f}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Nt});if(c>ci){let u=di(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Nt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||Ln(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,P]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=P;let f;if(typeof s==="string")f=s;else if(s instanceof Blob)f=await s.text();else f=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=R({method:"PUT",url:u,headers:h,body:f,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:s});if(!A.ok){let C=await A.text();throw new M(`Failed to put object: ${C}`,A.status,n,i)}return{etag:(A.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=R({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new M(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,l=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((E)=>`<Object><Key>${ui(E)}</Key></Object>`).join("")}</Delete>`,u=R({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:l,...s,service:"s3",region:this.region}),h=await fetch(u.url,{method:u.method,headers:u.headers,body:l});if(!h.ok){let E=await h.text();throw new M(`Failed to delete objects: ${E}`,h.status,n)}let f=await h.text(),S=[],A=[],v=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=v.exec(f))!==null)S.push(C[1]);let P=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=P.exec(f))!==null)A.push({key:C[1],error:`${C[2]}: ${C[3]}`});return{deleted:S,errors:A}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=R({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new M(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return li(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=R({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new M(`Failed to head object: ${h}`,l.status,n,i)}let u={};return l.headers.forEach((h,f)=>{if(f.toLowerCase().startsWith("x-amz-meta-"))u[f.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[P,E]of Object.entries(c.metadata))h[`x-amz-meta-${P.toLowerCase()}`]=E;let f=R({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers});if(!S.ok){let P=await S.text();throw new M(`Failed to copy object: ${P}`,S.status,s,o)}let v=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:v?v[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return Oo({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Nt,oi),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let A=new Blob([s]);u=A.stream(),h=A.size}let{uploadId:f,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,S,f,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,f,A)}catch(A){throw await this.abortMultipartUpload(n,i,f,S).catch(()=>{}),A}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||Ln(i)};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.metadata)for(let[C,P]of Object.entries(s.metadata))u[`x-amz-meta-${C.toLowerCase()}`]=P;let h=R({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok){let C=await f.text();throw new M(`Failed to initiate multipart upload: ${C}`,f.status,n,i)}let A=(await f.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new M("Failed to parse upload ID from response",0,n,i);let v=c;if(f.url)try{let C=new URL(f.url);C.search="",v=C.toString()}catch{}return{uploadId:A[1],baseUrl:v}}async uploadParts(n,i,s,o,c,l,u,h,f,S){let A=[],v=c.getReader(),C=1,P=new Uint8Array(0),E=0,I=h?Math.ceil(h/l):void 0,D=new Map,x=async(w,B)=>{let _=`${s}?partNumber=${B}&uploadId=${encodeURIComponent(o)}`,K={"Content-Length":String(w.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=R({method:"PUT",url:_,headers:K,...u,service:"s3",region:this.region}),J=await fetch(Z.url,{method:Z.method,headers:Z.headers,body:w,redirect:"error"});if(!J.ok){let X=await J.text();throw new M(`Failed to upload part ${B}: ${X}`,J.status,n,i)}let Y=(J.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new M(`Missing ETag for part ${B}`,J.status,n,i);return{partNumber:B,etag:Y}},O=async()=>{let w=await Promise.race(D.values());D.delete(w.partNumber),A.push(w)};while(!0){let{done:w,value:B}=await v.read();if(B){let _=new Uint8Array(P.length+B.length);_.set(P),_.set(B,P.length),P=_}while(P.length>=l||w&&P.length>0){let _=P.slice(0,l);P=P.slice(l);let K=C++;if(D.size>=f)await O();if(D.set(K,x(_,K)),E+=_.byteLength,S)S({loaded:E,total:h||E,part:K,totalParts:I||K})}if(w)break}while(D.size>0)await O();return A.sort((w,B)=>w.partNumber-B.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,f=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((E)=>`<Part><PartNumber>${E.partNumber}</PartNumber><ETag>"${E.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,S=R({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:f,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:f});if(!A.ok){let E=await A.text();throw new M(`Failed to complete multipart upload: ${E}`,A.status,n,i)}let C=(await A.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:C?C[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=R({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let s=[];for await(let u of this.listAll(n,{}))if(s.push(u.key),s.length>=1000)await this.deleteMany(n,s),s=[];if(s.length>0)await this.deleteMany(n,s);let o=await this.getCredentials(),c=this.buildUrl(n),l=R({method:"DELETE",url:c,...o,service:"s3",region:this.region});await fetch(l.url,{method:l.method,headers:l.headers})}}class M extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i;this.bucket=s;this.key=o;this.name="S3Error"}}function li(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function ui(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ln(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function di(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function FA(n){return new xt(n)}class Je extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i;this.solution=s;this.details=o;this.name="CloudError",Error.captureStackTrace?.(this,Je)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2458
+ `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="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:f==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...f==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function LI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:h=s.replace(/-/g,"_"),databasePassword:f,sslEmail:S,deployStrategy:A="push",provider:v="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:v},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:f}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:l,repository:{...c,strategy:A},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:S}}}}}function $I(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:f,deploy:S=["migrate --force"],cache:A="dynamodb",scheduler:v="on",region:C="us-east-1"}=n;return{project:{name:i,slug:s,region:C},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:f,deploy:S,assets:"public",queues:!0,scheduler:v,cache:{driver:A},domain:o}}}}}function MI(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var _A=Bd,LA="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function ii(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function si(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var $A=20000,MA=12000;function FA(n){return $A+si(n)%MA}function Dn(n,i){let s=ii(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function Nn(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")s.push(u);else if(Array.isArray(u))s.push(...u.filter((h)=>typeof h==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function UA(n,i,s){if(s)return s;let o=Nn(n,i),c=o[0];if(!c)return null;return Dn(c,o)}function QA(n,i,s){if(s)return[s];let o=Nn(n,i),c=[];for(let l of o){let u=Dn(l,o);if(!c.includes(u))c.push(u)}return c}function Xt(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return Jr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var im="dashboard-";function sm(n){return im+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function Jr(n){return n==="dashboard"||n.startsWith(im)}function Mi(n,i,s){if(Xt(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let u=UA(n,i,s.domain);if(!u)return[];let h=s.port??FA(u),f=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,S={root:s.uiRoot,deploy:"server",domain:u,preStart:["bun install --production --no-save"],start:`bun ${LA} --box --host 127.0.0.1 --port ${h}`,port:h,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...f?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:f.password}:{}},zeroDowntime:!1,sharedPaths:[_A],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:sm(u),site:S}]}return QA(n,i,s.domain).map((u)=>({name:sm(u),site:{root:s.uiRoot,deploy:"server",type:"static",domain:u,ssl:{provider:"letsencrypt"},...c,...o}}))}function FI(n,i,s){return Mi(n,i,s)[0]??null}function wt(n,i){let s={...n};for(let o in i){let c=i[o],l=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))s[o]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))s[o]=wt(l,c);else s[o]=c}return s}function om(n,i){return wt(n,i)}function UI(...n){return n.reduce((i,s)=>wt(i,s),{})}function QI(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return om(o,i(o,s));return om(o,i)}}function Xr(n){return{infrastructure:n}}function HI(n){return Xr({monitoring:n})}function GI(n){return Xr({security:n})}function VI(n){return Xr({databases:n})}function qI(n){return Xr({cache:n})}function jI(n){return Xr({cdn:n})}function zI(n){return Xr({queues:n})}import{existsSync as xn,readFileSync as Dt}from"node:fs";import{homedir as kn}from"node:os";import{join as Mn}from"node:path";function HA(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function GA(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||Mn(kn(),".aws","credentials");if(!xn(s))return null;try{let o=Dt(s,"utf-8");return ai(o,i)}catch{return null}}function ai(n,i){let s=n.split(`
2459
+ `),o=null,c,l,u;for(let h of s){let f=h.trim();if(!f||f.startsWith("#")||f.startsWith(";"))continue;let S=f.match(/^\[([^\]]+)\]$/);if(S){if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};o=S[1],c=void 0,l=void 0,u=void 0;continue}if(o===i){let[A,...v]=f.split("="),C=v.join("=").trim();switch(A.trim().toLowerCase()){case"aws_access_key_id":c=C;break;case"aws_secret_access_key":l=C;break;case"aws_session_token":u=C;break}}}if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function VA(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await He("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),l=await He("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!l.ok)return null;let u=(await l.text()).trim(),h=await He(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function qA(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await He(c,{headers:l},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function jA(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let l=Dt(s,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,f=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),S=await He(`${h}/?${f.toString()}`,{method:"POST"},i);if(!S.ok)return null;let A=await S.text(),v=Ue(A,"AccessKeyId"),C=Ue(A,"SecretAccessKey"),P=Ue(A,"SessionToken"),E=Ue(A,"Expiration");if(!v||!C)return null;return{accessKeyId:v,secretAccessKey:C,sessionToken:P??void 0,expiration:E?new Date(E):void 0}}catch{return null}}async function Fi(n){let i=HA();if(i)return i;let s=GA(n);if(s)return s;let o=await jA(n);if(o)return o;let c=await qA(n);if(c)return c;let l=await VA(n);if(l)return l;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 KI(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=Fi(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function He(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let l=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Ue(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function vo(n){return Fi({profile:n})}function zA(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=Mn(kn(),".aws","config");if(xn(s))try{let o=Dt(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=o.split(`
2460
+ `),h=!1;for(let f of u){let S=f.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,A]=S.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function am(n){let i=n||await Fi(),s=zA(),{signRequest:o}=await import("./chunk-s20830hg.js"),c=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,l="Action=GetCallerIdentity&Version=2011-06-15",u=o({method:"POST",url:c,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),h=await fetch(u.url,{method:u.method,headers:u.headers,body:u.body});if(!h.ok)throw Error(`Failed to get account ID: ${await h.text()}`);let f=await h.text(),S=Ue(f,"Account");if(!S)throw Error("Failed to parse account ID from response");return S}var oi=5242880,Nt=5242880;var ci=5242880;class xt{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Fi(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=R({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok&&f.status!==304){let S=await f.text();throw new M(`Failed to get object: ${S}`,f.status,n,i)}return f}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Nt});if(c>ci){let u=di(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Nt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||Ln(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,P]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=P;let f;if(typeof s==="string")f=s;else if(s instanceof Blob)f=await s.text();else f=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=R({method:"PUT",url:u,headers:h,body:f,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:s});if(!A.ok){let C=await A.text();throw new M(`Failed to put object: ${C}`,A.status,n,i)}return{etag:(A.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=R({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new M(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,l=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((E)=>`<Object><Key>${ui(E)}</Key></Object>`).join("")}</Delete>`,u=R({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:l,...s,service:"s3",region:this.region}),h=await fetch(u.url,{method:u.method,headers:u.headers,body:l});if(!h.ok){let E=await h.text();throw new M(`Failed to delete objects: ${E}`,h.status,n)}let f=await h.text(),S=[],A=[],v=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=v.exec(f))!==null)S.push(C[1]);let P=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=P.exec(f))!==null)A.push({key:C[1],error:`${C[2]}: ${C[3]}`});return{deleted:S,errors:A}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=R({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new M(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return li(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=R({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new M(`Failed to head object: ${h}`,l.status,n,i)}let u={};return l.headers.forEach((h,f)=>{if(f.toLowerCase().startsWith("x-amz-meta-"))u[f.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[P,E]of Object.entries(c.metadata))h[`x-amz-meta-${P.toLowerCase()}`]=E;let f=R({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers});if(!S.ok){let P=await S.text();throw new M(`Failed to copy object: ${P}`,S.status,s,o)}let v=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:v?v[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return Oo({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Nt,oi),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let A=new Blob([s]);u=A.stream(),h=A.size}let{uploadId:f,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,S,f,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,f,A)}catch(A){throw await this.abortMultipartUpload(n,i,f,S).catch(()=>{}),A}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||Ln(i)};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.metadata)for(let[C,P]of Object.entries(s.metadata))u[`x-amz-meta-${C.toLowerCase()}`]=P;let h=R({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok){let C=await f.text();throw new M(`Failed to initiate multipart upload: ${C}`,f.status,n,i)}let A=(await f.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new M("Failed to parse upload ID from response",0,n,i);let v=c;if(f.url)try{let C=new URL(f.url);C.search="",v=C.toString()}catch{}return{uploadId:A[1],baseUrl:v}}async uploadParts(n,i,s,o,c,l,u,h,f,S){let A=[],v=c.getReader(),C=1,P=new Uint8Array(0),E=0,I=h?Math.ceil(h/l):void 0,D=new Map,x=async(w,B)=>{let _=`${s}?partNumber=${B}&uploadId=${encodeURIComponent(o)}`,W={"Content-Length":String(w.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=R({method:"PUT",url:_,headers:W,...u,service:"s3",region:this.region}),J=await fetch(Z.url,{method:Z.method,headers:Z.headers,body:w,redirect:"error"});if(!J.ok){let X=await J.text();throw new M(`Failed to upload part ${B}: ${X}`,J.status,n,i)}let Y=(J.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new M(`Missing ETag for part ${B}`,J.status,n,i);return{partNumber:B,etag:Y}},O=async()=>{let w=await Promise.race(D.values());D.delete(w.partNumber),A.push(w)};while(!0){let{done:w,value:B}=await v.read();if(B){let _=new Uint8Array(P.length+B.length);_.set(P),_.set(B,P.length),P=_}while(P.length>=l||w&&P.length>0){let _=P.slice(0,l);P=P.slice(l);let W=C++;if(D.size>=f)await O();if(D.set(W,x(_,W)),E+=_.byteLength,S)S({loaded:E,total:h||E,part:W,totalParts:I||W})}if(w)break}while(D.size>0)await O();return A.sort((w,B)=>w.partNumber-B.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,f=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((E)=>`<Part><PartNumber>${E.partNumber}</PartNumber><ETag>"${E.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,S=R({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:f,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:f});if(!A.ok){let E=await A.text();throw new M(`Failed to complete multipart upload: ${E}`,A.status,n,i)}let C=(await A.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:C?C[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=R({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let s=[];for await(let u of this.listAll(n,{}))if(s.push(u.key),s.length>=1000)await this.deleteMany(n,s),s=[];if(s.length>0)await this.deleteMany(n,s);let o=await this.getCredentials(),c=this.buildUrl(n),l=R({method:"DELETE",url:c,...o,service:"s3",region:this.region});await fetch(l.url,{method:l.method,headers:l.headers})}}class M extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i;this.bucket=s;this.key=o;this.name="S3Error"}}function li(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function ui(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ln(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function di(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function KA(n){return new xt(n)}class We extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i;this.solution=s;this.details=o;this.name="CloudError",Error.captureStackTrace?.(this,We)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2484
2461
 
2485
2462
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){n+=`
2486
2463
 
2487
2464
  Details:`;for(let[i,s]of Object.entries(this.details))n+=`
2488
- ${i}: ${JSON.stringify(s)}`}return n}}class To extends Je{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class Ct extends Je{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class UA extends Je{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class rm extends Je{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class QA extends Je{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var HA={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2465
+ ${i}: ${JSON.stringify(s)}`}return n}}class To extends We{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class Ct extends We{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class WA extends We{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class cm extends We{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class JA extends We{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var XA={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2489
2466
  1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
2490
2467
  2. Create ~/.aws/credentials file with your credentials
2491
2468
  3. Use an IAM role (for EC2 instances)
2492
- 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 GA(n){return HA[n]}function nm(n,i){let s=GA(n);return new Je(s.message,n,s.solution,i)}class F{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof Je)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2493
- Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function UI(n){if(!n)throw nm("MISSING_CONFIG");if(!n.project)throw new To("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new To("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new To("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new rm("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(n.project.region))throw nm("INVALID_REGION",{region:n.project.region})}F.success("Configuration validation passed")}function QI(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function HI(n="default"){try{F.verbose("Resolving AWS credentials...");let i=await vo(n);if(!i.accessKeyId||!i.secretAccessKey)throw new Ct("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");F.verbose("Credentials resolved successfully"),F.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),F.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await tm(i),F.verbose("Credentials are valid"),F.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new Ct("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new Ct("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new Ct("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Ct(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof Ct)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function GI(n,i){return{allowed:i,denied:[]}}function VA(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function VI(n){let i=VA(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var z={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 qI(n){let i=[];if(F.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:z.ec2["Running On-Demand Instances"],percentage:o/z.ec2["Running On-Demand Instances"]*100,warning:o>z.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:z.ec2.VPCs,percentage:1/z.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:z.rds["DB Instances"],percentage:1/z.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:z.s3.Buckets,percentage:o/z.s3.Buckets*100,warning:o>z.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:z.dynamodb.Tables,percentage:o/z.dynamodb.Tables*100,warning:o>z.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){F.warn("Service quota warnings detected:");for(let o of s)F.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else F.verbose("All service quotas are within limits");return i}function jI(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2469
+ 4. Run 'aws configure' if you have AWS CLI installed`},INVALID_CREDENTIALS:{message:"AWS credentials are invalid",solution:"Verify your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are correct. Run: aws sts get-caller-identity"},EXPIRED_CREDENTIALS:{message:"AWS credentials have expired",solution:"Refresh your AWS credentials. If using temporary credentials, generate new ones."},MISSING_CONFIG:{message:"Configuration file not found",solution:"Create a cloud.config.ts file in your project root. Use: cloud init"},INVALID_CONFIG:{message:"Configuration is invalid",solution:"Check your cloud.config.ts file for syntax errors. Use: cloud config:validate"},MISSING_REQUIRED_FIELD:{message:"Required configuration field is missing",solution:"Add the missing field to your cloud.config.ts file"},INVALID_REGION:{message:"AWS region is invalid",solution:"Use a valid AWS region like us-east-1, us-west-2, eu-west-1, etc."},STACK_ALREADY_EXISTS:{message:"CloudFormation stack already exists",solution:"Use: cloud deploy --update to update the existing stack, or cloud destroy to delete it first"},STACK_IN_PROGRESS:{message:"Stack operation already in progress",solution:"Wait for the current operation to complete, or cancel it in the AWS Console"},INSUFFICIENT_PERMISSIONS:{message:"Insufficient IAM permissions",solution:"Ensure your IAM user/role has the necessary permissions for CloudFormation and the resources you're deploying"},RESOURCE_LIMIT_EXCEEDED:{message:"AWS service limit exceeded",solution:"Request a service limit increase in the AWS Console, or clean up unused resources"},ROLLBACK_COMPLETE:{message:"Stack creation failed and rolled back",solution:"Check the CloudFormation events to see which resource failed. Fix the issue and try again."},CIRCULAR_DEPENDENCY:{message:"Circular dependency detected in resources",solution:"Review your resource dependencies and remove the circular reference"},INVALID_RESOURCE_NAME:{message:"Resource name contains invalid characters",solution:"Use only alphanumeric characters and hyphens in resource names"},DUPLICATE_RESOURCE:{message:"Duplicate resource name detected",solution:"Ensure all resource names are unique in your configuration"},VPC_CIDR_CONFLICT:{message:"VPC CIDR block conflicts with existing VPC",solution:"Use a different CIDR block that doesn't overlap with existing VPCs"},SUBNET_CIDR_INVALID:{message:"Subnet CIDR block is invalid or outside VPC range",solution:"Ensure subnet CIDR is within the VPC CIDR range and properly sized"},DB_INSTANCE_LIMIT:{message:"RDS instance limit reached",solution:"Delete unused RDS instances or request a limit increase"},INVALID_DB_NAME:{message:"Database name contains invalid characters",solution:"Use only alphanumeric characters and underscores, starting with a letter"},BUCKET_ALREADY_EXISTS:{message:"S3 bucket name already exists globally",solution:"S3 bucket names must be globally unique. Try a different name with your organization prefix"},INVALID_BUCKET_NAME:{message:"S3 bucket name is invalid",solution:"Use lowercase letters, numbers, and hyphens. Must start/end with letter/number. 3-63 characters."},TEMPLATE_TOO_LARGE:{message:"CloudFormation template exceeds size limit",solution:"Split your infrastructure into multiple stacks or use nested stacks"},INVALID_TEMPLATE:{message:"CloudFormation template is invalid",solution:"Validate your template with: cloud config:validate"},PARAMETER_NOT_FOUND:{message:"CloudFormation parameter not found",solution:"Check that all referenced parameters are defined in your template"}};function YA(n){return XA[n]}function dm(n,i){let s=YA(n);return new We(s.message,n,s.solution,i)}class F{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof We)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2470
+ Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function WI(n){if(!n)throw dm("MISSING_CONFIG");if(!n.project)throw new To("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new To("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new To("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new cm("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(n.project.region))throw dm("INVALID_REGION",{region:n.project.region})}F.success("Configuration validation passed")}function JI(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function XI(n="default"){try{F.verbose("Resolving AWS credentials...");let i=await vo(n);if(!i.accessKeyId||!i.secretAccessKey)throw new Ct("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");F.verbose("Credentials resolved successfully"),F.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),F.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await am(i),F.verbose("Credentials are valid"),F.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new Ct("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new Ct("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new Ct("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Ct(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof Ct)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function YI(n,i){return{allowed:i,denied:[]}}function ZA(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function ZI(n){let i=ZA(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var z={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 eb(n){let i=[];if(F.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:z.ec2["Running On-Demand Instances"],percentage:o/z.ec2["Running On-Demand Instances"]*100,warning:o>z.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:z.ec2.VPCs,percentage:1/z.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:z.rds["DB Instances"],percentage:1/z.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:z.s3.Buckets,percentage:o/z.s3.Buckets*100,warning:o>z.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:z.dynamodb.Tables,percentage:o/z.dynamodb.Tables*100,warning:o>z.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){F.warn("Service quota warnings detected:");for(let o of s)F.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else F.verbose("All service quotas are within limits");return i}function tb(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2494
2471
 
2495
2472
  `,s=n.reduce((o,c)=>{if(!o[c.service])o[c.service]=[];return o[c.service].push(c),o},{});for(let[o,c]of Object.entries(s)){i+=`${o}:
2496
2473
  `;for(let l of c){let u=l.warning?"⚠":"✓";i+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
2497
2474
  `}i+=`
2498
- `}return i}function zI(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}import{createHash as Bn}from"node:crypto";import{existsSync as it,mkdirSync as mi,readdirSync as On,readFileSync as $n,unlinkSync as qe,writeFileSync as pi}from"node:fs";import{join as kt}from"node:path";class zd{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!it(this.cacheDir))mi(this.cacheDir,{recursive:!0})}getCachePath(n){let i=Bn("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!it(i))return;try{let s=$n(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){qe(i);return}return o.value}catch{qe(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};pi(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!it(this.cacheDir))return;let n=On(this.cacheDir);for(let i of n)qe(kt(this.cacheDir,i))}prune(){if(!it(this.cacheDir))return;let n=On(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=$n(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)qe(o)}catch{qe(o)}}}}class Kd{cache;constructor(n=L("cache","templates")){this.cache=new zd(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return Bn("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Mt=null;function qA(){if(!Mt)Mt=new Kd;return Mt}import{createHash as Lt}from"node:crypto";import{createReadStream as gi,readdirSync as yi,statSync as st}from"node:fs";import{join as hi,relative as fi}from"node:path";async function im(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Lt(s),h=gi(n,{highWaterMark:o});h.on("data",(f)=>u.update(f)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function sm(n,i="sha256"){return Lt(i).update(n).digest("hex")}function KI(n,i="sha256"){return Lt(i).update(n).digest("hex")}async function WI(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",zr()],o=[];async function c(l){let u=yi(l,{withFileTypes:!0});for(let h of u){let f=hi(l,h.name),S=fi(n,f);if(s.some((A)=>S.includes(A)))continue;if(h.isDirectory())await c(f);else if(h.isFile()){let A=st(f),v=await im(f,i);o.push({path:S,hash:v,size:A.size,mtime:A.mtimeMs})}}}return await c(n),o}function JI(n){let s=[...n].sort((o,c)=>o.path.localeCompare(c.path)).map((o)=>`${o.path}:${o.hash}`).join(`
2499
- `);return sm(s)}function XI(n){let i=st(n);return sm(`${n}:${i.size}:${i.mtimeMs}`)}function YI(n,i){let s=new Map(n.map((h)=>[h.path,h])),o=new Map(i.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,f]of o){let S=s.get(h);if(!S)c.push(f);else if(S.hash!==f.hash)l.push(f)}for(let[h,f]of s)if(!o.has(h))u.push(f);return{added:c,modified:l,deleted:u}}class jA{cache;constructor(){this.cache=new Map}get(n){let i=st(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=st(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await im(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Wd(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...n],f=[];async function S(C,P){try{let E=await C();c[P]=E}catch(E){let I=E instanceof Error?E:Error(String(E));if(l.push(I),o)throw h.length=0,I}}let A=0;while(h.length>0||f.length>0){while(f.length<s&&h.length>0){let C=h.shift(),P=A++,E=S(C,P);f.push(E)}if(f.length>0){await Promise.race(f);for(let C=f.length-1;C>=0;C--)if(await Promise.race([f[C].then(()=>!0),Promise.resolve(!1)]))f.splice(C,1)}if(o&&l.length>0)break}let v=Date.now()-u;return{results:c.filter((C)=>C!==void 0),errors:l,duration:v}}async function ZI(n,i,s={}){let o=n.map((c)=>()=>i(c));return Wd(o,s)}async function eb(n,i,s=5){let o=n.map((l,u)=>()=>i(l,u)),c=await Wd(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function tb(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((l)=>async()=>{let u;for(let h=0;h<=s;h++)try{return await l()}catch(f){if(u=f instanceof Error?f:Error(String(f)),h<s)await Fn(o*(h+1))}throw u});return Wd(c,i)}async function rb(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Fn(n){return new Promise((i)=>setTimeout(i,n))}async function nb(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class zA{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n;this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Fn(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function KA(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function ib(n,i,s){let o=KA(n,i),c=[];for(let l of o){let u=await s(l);c.push(...u)}return c}function sb(n,i){let s=[],o=[],c=[],l=[],u=n.Resources||{},h=i.Resources||{},f=new Set(Object.keys(u)),S=new Set(Object.keys(h));for(let C of S)if(!f.has(C))s.push(C);for(let C of f)if(!S.has(C))c.push(C);for(let C of S)if(f.has(C)){let P=u[C],E=h[C];if(JSON.stringify(P)!==JSON.stringify(E))o.push(C);else l.push(C)}let A=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),v=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:l,parametersChanged:A,outputsChanged:v,hasChanges:s.length>0||o.length>0||c.length>0||A||v}}function ob(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2500
- `)}function ab(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=bi(l.Type);for(let h of u){let f=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(f)!==JSON.stringify(S))return!0}}return!1}function bi(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function cb(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function db(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function lb(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var WA={$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 ub(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var om={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Jd(){return om}function gb(){return om.enabled}function pb(n){let i=Jd();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function mb(){let n=Jd();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function fb(){let n=Jd();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class am{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class cm{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((o)=>({Key:o,Size:i.get(o).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class dm{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function hb(n){return{cloudformation:new am,s3:new cm,dynamodb:new dm}}class Xd{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),f=this.generatePreviewName(i,s),S=`preview-${f}`,A=new Date,v=new Date(A.getTime()+c*60*60*1000),C={id:h,name:f,branch:i,pr:s,commitSha:o,createdAt:A,expiresAt:v,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,C);try{let P=this.createPreviewConfig(l,f);return C.status="active",C.url=`https://${f}.preview.example.com`,C}catch(P){throw C.status="failed",P}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((f,S)=>S.createdAt.getTime()-f.createdAt.getTime());for(let f=0;f<h.length;f++){let S=h[f];if(S.status!=="active")continue;let A=!1;if(S.expiresAt<u)A=!0;if(i){if((u.getTime()-S.createdAt.getTime())/3600000>i)A=!0}if(s&&f>=s)A=!0;if(A)if(o)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(v){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var JA=new Xd;function XA(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
2475
+ `}return i}function rb(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}import{createHash as Bn}from"node:crypto";import{existsSync as it,mkdirSync as mi,readdirSync as On,readFileSync as $n,unlinkSync as qe,writeFileSync as pi}from"node:fs";import{join as kt}from"node:path";class Wd{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!it(this.cacheDir))mi(this.cacheDir,{recursive:!0})}getCachePath(n){let i=Bn("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!it(i))return;try{let s=$n(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){qe(i);return}return o.value}catch{qe(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};pi(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!it(this.cacheDir))return;let n=On(this.cacheDir);for(let i of n)qe(kt(this.cacheDir,i))}prune(){if(!it(this.cacheDir))return;let n=On(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=$n(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)qe(o)}catch{qe(o)}}}}class Jd{cache;constructor(n=L("cache","templates")){this.cache=new Wd(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return Bn("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Mt=null;function ey(){if(!Mt)Mt=new Jd;return Mt}import{createHash as Lt}from"node:crypto";import{createReadStream as gi,readdirSync as yi,statSync as st}from"node:fs";import{join as hi,relative as fi}from"node:path";async function lm(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Lt(s),h=gi(n,{highWaterMark:o});h.on("data",(f)=>u.update(f)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function um(n,i="sha256"){return Lt(i).update(n).digest("hex")}function nb(n,i="sha256"){return Lt(i).update(n).digest("hex")}async function ib(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",zr()],o=[];async function c(l){let u=yi(l,{withFileTypes:!0});for(let h of u){let f=hi(l,h.name),S=fi(n,f);if(s.some((A)=>S.includes(A)))continue;if(h.isDirectory())await c(f);else if(h.isFile()){let A=st(f),v=await lm(f,i);o.push({path:S,hash:v,size:A.size,mtime:A.mtimeMs})}}}return await c(n),o}function sb(n){let s=[...n].sort((o,c)=>o.path.localeCompare(c.path)).map((o)=>`${o.path}:${o.hash}`).join(`
2476
+ `);return um(s)}function ob(n){let i=st(n);return um(`${n}:${i.size}:${i.mtimeMs}`)}function ab(n,i){let s=new Map(n.map((h)=>[h.path,h])),o=new Map(i.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,f]of o){let S=s.get(h);if(!S)c.push(f);else if(S.hash!==f.hash)l.push(f)}for(let[h,f]of s)if(!o.has(h))u.push(f);return{added:c,modified:l,deleted:u}}class ty{cache;constructor(){this.cache=new Map}get(n){let i=st(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=st(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await lm(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Xd(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...n],f=[];async function S(C,P){try{let E=await C();c[P]=E}catch(E){let I=E instanceof Error?E:Error(String(E));if(l.push(I),o)throw h.length=0,I}}let A=0;while(h.length>0||f.length>0){while(f.length<s&&h.length>0){let C=h.shift(),P=A++,E=S(C,P);f.push(E)}if(f.length>0){await Promise.race(f);for(let C=f.length-1;C>=0;C--)if(await Promise.race([f[C].then(()=>!0),Promise.resolve(!1)]))f.splice(C,1)}if(o&&l.length>0)break}let v=Date.now()-u;return{results:c.filter((C)=>C!==void 0),errors:l,duration:v}}async function cb(n,i,s={}){let o=n.map((c)=>()=>i(c));return Xd(o,s)}async function db(n,i,s=5){let o=n.map((l,u)=>()=>i(l,u)),c=await Xd(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function lb(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((l)=>async()=>{let u;for(let h=0;h<=s;h++)try{return await l()}catch(f){if(u=f instanceof Error?f:Error(String(f)),h<s)await Fn(o*(h+1))}throw u});return Xd(c,i)}async function ub(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Fn(n){return new Promise((i)=>setTimeout(i,n))}async function gb(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class ry{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n;this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Fn(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function ny(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function pb(n,i,s){let o=ny(n,i),c=[];for(let l of o){let u=await s(l);c.push(...u)}return c}function mb(n,i){let s=[],o=[],c=[],l=[],u=n.Resources||{},h=i.Resources||{},f=new Set(Object.keys(u)),S=new Set(Object.keys(h));for(let C of S)if(!f.has(C))s.push(C);for(let C of f)if(!S.has(C))c.push(C);for(let C of S)if(f.has(C)){let P=u[C],E=h[C];if(JSON.stringify(P)!==JSON.stringify(E))o.push(C);else l.push(C)}let A=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),v=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:l,parametersChanged:A,outputsChanged:v,hasChanges:s.length>0||o.length>0||c.length>0||A||v}}function fb(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2477
+ `)}function hb(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=bi(l.Type);for(let h of u){let f=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(f)!==JSON.stringify(S))return!0}}return!1}function bi(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function Ab(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function yb(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function Sb(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var iy={$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 Ib(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var gm={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Yd(){return gm}function bb(){return gm.enabled}function Cb(n){let i=Yd();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function Eb(){let n=Yd();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function vb(){let n=Yd();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class pm{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class mm{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((o)=>({Key:o,Size:i.get(o).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class fm{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function Tb(n){return{cloudformation:new pm,s3:new mm,dynamodb:new fm}}class Zd{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),f=this.generatePreviewName(i,s),S=`preview-${f}`,A=new Date,v=new Date(A.getTime()+c*60*60*1000),C={id:h,name:f,branch:i,pr:s,commitSha:o,createdAt:A,expiresAt:v,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,C);try{let P=this.createPreviewConfig(l,f);return C.status="active",C.url=`https://${f}.preview.example.com`,C}catch(P){throw C.status="failed",P}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((f,S)=>S.createdAt.getTime()-f.createdAt.getTime());for(let f=0;f<h.length;f++){let S=h[f];if(S.status!=="active")continue;let A=!1;if(S.expiresAt<u)A=!0;if(i){if((u.getTime()-S.createdAt.getTime())/3600000>i)A=!0}if(s&&f>=s)A=!0;if(A)if(o)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(v){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var sy=new Zd;function oy(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
2501
2478
 
2502
2479
  on:
2503
2480
  ${s}:
@@ -2631,7 +2608,7 @@ jobs:
2631
2608
  run: |
2632
2609
  # Clean up environments older than TTL
2633
2610
  bun run cloud env:cleanup --max-age=\${{ env.TTL_HOURS }}
2634
- `}function YA(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2611
+ `}function ay(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2635
2612
 
2636
2613
  on:
2637
2614
  schedule:
@@ -2676,7 +2653,7 @@ jobs:
2676
2653
  - name: Report cleanup results
2677
2654
  run: |
2678
2655
  bun run cloud env:list --status=destroyed
2679
- `}function ZA(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2656
+ `}function cy(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2680
2657
 
2681
2658
  on:
2682
2659
  schedule:
@@ -2725,15 +2702,15 @@ jobs:
2725
2702
  curl -X POST -H 'Content-type: application/json' \\
2726
2703
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2727
2704
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2728
- `}class Yd{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var ey=new Yd;function Ab(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:l=!1,maxWidth:u}=n;if(s.length===0)return"No data to display";let h=i.map((S)=>{let A=S.label.length,v=Math.max(...s.map((P)=>(S.formatter?S.formatter(P[S.key]):String(P[S.key]||"")).length)),C=S.width||Math.max(A,v);if(u&&C>u)C=u;return C}),f=[];if(o)f.push(Ot(h,"top",l));if(c){if(f.push(Gn(i.map((S)=>S.label),h,i.map((S)=>S.align||"left"),o)),o)f.push(Ot(h,"middle",l))}for(let S of s){let A=i.map((v)=>{let C=v.formatter?v.formatter(S[v.key]):String(S[v.key]||"");return Ci(C,h[i.indexOf(v)])});f.push(Gn(A,h,i.map((v)=>v.align||"left"),o))}if(o)f.push(Ot(h,"bottom",l));return f.join(`
2729
- `)}function Gn(n,i,s,o){let c=n.map((l,u)=>{let h=i[u],f=s[u];return Ai(l,h,f)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Ot(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",l=i==="top"?"┬":i==="middle"?"┼":"┴",u="─";if(s)return o+n.map((h)=>"─".repeat(h+2)).join(l)+c;return o+n.map((h)=>"─".repeat(h+2)).join(l)+c}function Ai(n,i,s){let o=_n(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+n+" ".repeat(u)}default:return n+" ".repeat(c)}}function Ci(n,i){if(_n(n).length<=i)return n;return n.substring(0,i-1)+"…"}function _n(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function yb(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function l(u,h,f){let A=h+(f?"└─ ":"├─ ")+u.label;if(c.push(A),o&&u.metadata){let v=h+(f?" ":"│ ");for(let[C,P]of Object.entries(u.metadata))c.push(`${v}${C}: ${P}`)}if(u.children&&u.children.length>0){let v=h+(f?" ":"│ ");u.children.forEach((C,P)=>{l(C,v,P===u.children.length-1)})}}return n.forEach((u,h)=>{l(u,"",h===n.length-1)}),c.join(`
2730
- `)}function Sb(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=n,h=Math.min(100,Math.max(0,s/i*100)),f=Math.floor(o*s/i),S=o-f,A=l.repeat(f)+u.repeat(S);return c.replace(":bar",A).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function Ib(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,l)).toFixed(o))} ${c[l]}`}function bb(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),l=s%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function Cb(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2731
- `)}function Eb(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((l)=>l.length));return Object.entries(n).map(([l,u])=>{let h=l.padEnd(c);return`${s}${h}${o}${u}`}).join(`
2732
- `)}class ty{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),l=s%24;return l>0?`${c}d ${l}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,l=`${this.current}/${this.total}`,u=this.showETA?`ETA: ${this.getETAFormatted()}`:"",h=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?l:"").replace(":eta",u).replace(":current",String(this.current)).replace(":total",String(this.total));return h=h.replace(/\s+/g," ").trim(),h}isComplete(){return this.current>=this.total}}class ry{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let o=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)o+=` - ${i.message}`;if(i.error)o+=`
2705
+ `}class el{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var dy=new el;function wb(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:l=!1,maxWidth:u}=n;if(s.length===0)return"No data to display";let h=i.map((S)=>{let A=S.label.length,v=Math.max(...s.map((P)=>(S.formatter?S.formatter(P[S.key]):String(P[S.key]||"")).length)),C=S.width||Math.max(A,v);if(u&&C>u)C=u;return C}),f=[];if(o)f.push(Ot(h,"top",l));if(c){if(f.push(Gn(i.map((S)=>S.label),h,i.map((S)=>S.align||"left"),o)),o)f.push(Ot(h,"middle",l))}for(let S of s){let A=i.map((v)=>{let C=v.formatter?v.formatter(S[v.key]):String(S[v.key]||"");return Ci(C,h[i.indexOf(v)])});f.push(Gn(A,h,i.map((v)=>v.align||"left"),o))}if(o)f.push(Ot(h,"bottom",l));return f.join(`
2706
+ `)}function Gn(n,i,s,o){let c=n.map((l,u)=>{let h=i[u],f=s[u];return Ai(l,h,f)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Ot(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",l=i==="top"?"┬":i==="middle"?"┼":"┴",u="─";if(s)return o+n.map((h)=>"─".repeat(h+2)).join(l)+c;return o+n.map((h)=>"─".repeat(h+2)).join(l)+c}function Ai(n,i,s){let o=_n(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+n+" ".repeat(u)}default:return n+" ".repeat(c)}}function Ci(n,i){if(_n(n).length<=i)return n;return n.substring(0,i-1)+"…"}function _n(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function Rb(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function l(u,h,f){let A=h+(f?"└─ ":"├─ ")+u.label;if(c.push(A),o&&u.metadata){let v=h+(f?" ":"│ ");for(let[C,P]of Object.entries(u.metadata))c.push(`${v}${C}: ${P}`)}if(u.children&&u.children.length>0){let v=h+(f?" ":"│ ");u.children.forEach((C,P)=>{l(C,v,P===u.children.length-1)})}}return n.forEach((u,h)=>{l(u,"",h===n.length-1)}),c.join(`
2707
+ `)}function Db(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=n,h=Math.min(100,Math.max(0,s/i*100)),f=Math.floor(o*s/i),S=o-f,A=l.repeat(f)+u.repeat(S);return c.replace(":bar",A).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function Pb(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,l)).toFixed(o))} ${c[l]}`}function Nb(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),l=s%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function kb(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2708
+ `)}function Bb(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((l)=>l.length));return Object.entries(n).map(([l,u])=>{let h=l.padEnd(c);return`${s}${h}${o}${u}`}).join(`
2709
+ `)}class ly{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),l=s%24;return l>0?`${c}d ${l}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,l=`${this.current}/${this.total}`,u=this.showETA?`ETA: ${this.getETAFormatted()}`:"",h=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?l:"").replace(":eta",u).replace(":current",String(this.current)).replace(":total",String(this.total));return h=h.replace(/\s+/g," ").trim(),h}isComplete(){return this.current>=this.total}}class uy{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let o=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)o+=` - ${i.message}`;if(i.error)o+=`
2733
2710
  Error: ${i.error}`;n.push(o)}return n.join(`
2734
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class ny{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class iy{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let o=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)o+=`
2711
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class gy{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class py{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let o=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)o+=`
2735
2712
  ${i.output}`;n.push(o)}return n.join(`
2736
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function vi(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Ti(n,i){let s=vi(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function lm(n,i,s=0.5){return i.map((c)=>({command:c,score:Ti(n,c)})).filter((c)=>c.score>=s).sort((c,l)=>l.score-c.score).map((c)=>c.command).slice(0,5)}function vb(n,i){if(i.length===0)return`Unknown command: '${n}'
2713
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function vi(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Ti(n,i){let s=vi(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function hm(n,i,s=0.5){return i.map((c)=>({command:c,score:Ti(n,c)})).filter((c)=>c.score>=s).sort((c,l)=>l.score-c.score).map((c)=>c.command).slice(0,5)}function xb(n,i){if(i.length===0)return`Unknown command: '${n}'
2737
2714
 
2738
2715
  Run 'ts-cloud --help' to see available commands.`;if(i.length===1)return`Unknown command: '${n}'
2739
2716
 
@@ -2741,17 +2718,17 @@ Did you mean: ${i[0]}?`;return`Unknown command: '${n}'
2741
2718
 
2742
2719
  Did you mean one of these?
2743
2720
  ${i.map((s)=>` • ${s}`).join(`
2744
- `)}`}function Tb(n,i){return lm(n,i,0.7).length>0}function wb(n,i){let s=i.find((l)=>l.commands.some((u)=>u.name===n||u.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let l of s.commands)if(o.push(` ${l.name.padEnd(20)} ${l.description}`),l.aliases&&l.aliases.length>0)o.push(` Aliases: ${l.aliases.join(", ")}`);let c=s.commands.find((l)=>l.name===n||l.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let l of c.examples)o.push(` ${l}`)}return o.join(`
2745
- `)}function Rb(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let l of c.commands){let u=l.name.toLowerCase().includes(o),h=l.description.toLowerCase().includes(o),f=l.aliases?.some((S)=>S.toLowerCase().includes(o));if(u||h||f)s.push({command:l,category:c.name})}return s}function Db(n,i,s=10){let o=n.toLowerCase(),c=i.filter((u)=>u.toLowerCase().startsWith(o)),l=i.filter((u)=>u.toLowerCase().includes(o)&&!u.toLowerCase().startsWith(o));return[...c,...l].slice(0,s)}function Pb(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),l=o.alias?.toLowerCase().includes(s);return c||l})}function Nb(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2746
- `)}function kb(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2747
- `)}function Bb(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...l]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let u=lm(c,i);if(u.length>0)o.suggestions.push(...u)}for(let u of s)if(!l.some((h)=>h===`--${u}`||h.startsWith(`--${u}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${u}`);return o}class sy{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let l of c.aliases)if(l.startsWith(n))i.push(l)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2721
+ `)}`}function Ob(n,i){return hm(n,i,0.7).length>0}function _b(n,i){let s=i.find((l)=>l.commands.some((u)=>u.name===n||u.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let l of s.commands)if(o.push(` ${l.name.padEnd(20)} ${l.description}`),l.aliases&&l.aliases.length>0)o.push(` Aliases: ${l.aliases.join(", ")}`);let c=s.commands.find((l)=>l.name===n||l.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let l of c.examples)o.push(` ${l}`)}return o.join(`
2722
+ `)}function Lb(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let l of c.commands){let u=l.name.toLowerCase().includes(o),h=l.description.toLowerCase().includes(o),f=l.aliases?.some((S)=>S.toLowerCase().includes(o));if(u||h||f)s.push({command:l,category:c.name})}return s}function $b(n,i,s=10){let o=n.toLowerCase(),c=i.filter((u)=>u.toLowerCase().startsWith(o)),l=i.filter((u)=>u.toLowerCase().includes(o)&&!u.toLowerCase().startsWith(o));return[...c,...l].slice(0,s)}function Mb(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),l=o.alias?.toLowerCase().includes(s);return c||l})}function Fb(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2723
+ `)}function Ub(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2724
+ `)}function Qb(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...l]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let u=hm(c,i);if(u.length>0)o.suggestions.push(...u)}for(let u of s)if(!l.some((h)=>h===`--${u}`||h.startsWith(`--${u}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${u}`);return o}class my{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let l of c.aliases)if(l.startsWith(n))i.push(l)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2748
2725
  `).filter((s)=>s.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises");await n.writeFile(this.options.historyFile,this.history.commands.join(`
2749
- `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class oy{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class ay{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class cy{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((h)=>h.success).length,s=this.entries.filter((h)=>!h.success).length,o=this.entries.filter((h)=>h.duration!==void 0),c=o.length>0?o.reduce((h,f)=>h+(f.duration||0),0)/o.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((s)=>[s.timestamp.toISOString(),`"${s.command.replace(/"/g,'""')}"`,s.success,s.duration||""].join(","))].join(`
2750
- `)}importJSON(n){let s=JSON.parse(n).map((o)=>({...o,timestamp:new Date(o.timestamp)}));if(this.entries.push(...s),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),l=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(l,(i.get(l)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function xb(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let l=n[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),f=l.success?"✓":"✗",S=l.command;if(S.length>s-30)S=S.substring(0,s-33)+"...";let A=`${u} ${h} ${f} ${S}`;if(l.duration)A+=` (${l.duration}ms)`;o.push(A)}return o.join(`
2751
- `)}function Ob(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2752
- `)}class um{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((u)=>u.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let l=i.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(n,u,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};o.push(u)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((o)=>o.status==="deployed").map((o,c)=>{let l=i.regions[c];return{id:`origin-${o.region}`,domainName:o.outputs?.endpoint,weight:l?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,l)=>i.regions[l]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var _b=new um;class gm{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((c)=>c.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class pm{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class mm{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class fm{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let l=`${c.name}:${c.region}`;if(i.has(l))return;i.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)o({name:h.dependsOnStack,region:h.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let l=`${o}:${c}`;if(i.has(l))return!0;if(n.has(l))return!1;n.add(l),i.add(l);let u=this.getDependencies(o,c);for(let h of u)if(s(h.dependsOnStack,h.dependsOnRegion))return!0;return i.delete(l),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var Lb=new gm,$b=new pm,Mb=new mm,Fb=new fm;var ke=[{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(n){return ke.find((i)=>i.code===n)}function Ub(){return ke}function Qb(n){let i=n.toLowerCase();return ke.filter((s)=>s.location.toLowerCase().includes(i))}function Hb(n){return ke.filter((i)=>i.compliance.includes(n))}function Gb(n){return ke.filter((i)=>i.pricing.tier===n)}function Vb(n){return ke.some((i)=>i.code===n)}function qb(n){if(n.continent==="North America")return Ui("us-east-1");if(n.continent==="Europe")return Ui("eu-west-1");if(n.continent==="Asia")return Ui("ap-southeast-1");return Ui("us-east-1")}function jb(n){let i=[...ke];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function zb(n){let i=Ui(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of ke){if(o.code===n)continue;let c=Ri(i,o),l=Pi(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:l})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function Ri(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=Qe(n.location),c=Qe(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Pi(n,i){return Qe(n.location)===Qe(i.location)}function Qe(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function dy(n){return`${n.name} (${n.code})`}function Kb(n){return n.map((i)=>dy(i)).join(`
2753
- `)}function Wb(){let n={total:ke.length,byContinent:{},byPricingTier:{}};for(let i of ke){let s=Qe(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class hm{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let s of this.accounts.values())n[s.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((s,o)=>s+o,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Am{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var Jb=new hm,Xb=new Am;var ly={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"}]}},Yb={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"]}}}]}}},Zb={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 eC(n){return ly[n]}function tC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function rC(n){let i=[],s=[],o=n.accounts.filter((f)=>f.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((f)=>f.email),l=c.filter((f,S)=>c.indexOf(f)!==S);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((f)=>f.alias),h=u.filter((f,S)=>u.indexOf(f)!==S);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((f)=>f.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((f)=>f.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function nC(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2754
- `)}function iC(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:f="bun run cloud deploy",testCommand:S="bun test",buildCommand:A="bun run build"}=n,v=!!u;return`name: ${i}
2726
+ `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class fy{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class hy{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class Ay{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((h)=>h.success).length,s=this.entries.filter((h)=>!h.success).length,o=this.entries.filter((h)=>h.duration!==void 0),c=o.length>0?o.reduce((h,f)=>h+(f.duration||0),0)/o.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((s)=>[s.timestamp.toISOString(),`"${s.command.replace(/"/g,'""')}"`,s.success,s.duration||""].join(","))].join(`
2727
+ `)}importJSON(n){let s=JSON.parse(n).map((o)=>({...o,timestamp:new Date(o.timestamp)}));if(this.entries.push(...s),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),l=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(l,(i.get(l)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function Hb(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let l=n[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),f=l.success?"✓":"✗",S=l.command;if(S.length>s-30)S=S.substring(0,s-33)+"...";let A=`${u} ${h} ${f} ${S}`;if(l.duration)A+=` (${l.duration}ms)`;o.push(A)}return o.join(`
2728
+ `)}function Gb(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2729
+ `)}class Am{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((u)=>u.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let l=i.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(n,u,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};o.push(u)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((o)=>o.status==="deployed").map((o,c)=>{let l=i.regions[c];return{id:`origin-${o.region}`,domainName:o.outputs?.endpoint,weight:l?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,l)=>i.regions[l]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var Vb=new Am;class ym{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((c)=>c.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class Sm{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class Im{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class bm{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let l=`${c.name}:${c.region}`;if(i.has(l))return;i.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)o({name:h.dependsOnStack,region:h.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let l=`${o}:${c}`;if(i.has(l))return!0;if(n.has(l))return!1;n.add(l),i.add(l);let u=this.getDependencies(o,c);for(let h of u)if(s(h.dependsOnStack,h.dependsOnRegion))return!0;return i.delete(l),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var qb=new ym,jb=new Sm,zb=new Im,Kb=new bm;var Ne=[{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(n){return Ne.find((i)=>i.code===n)}function Wb(){return Ne}function Jb(n){let i=n.toLowerCase();return Ne.filter((s)=>s.location.toLowerCase().includes(i))}function Xb(n){return Ne.filter((i)=>i.compliance.includes(n))}function Yb(n){return Ne.filter((i)=>i.pricing.tier===n)}function Zb(n){return Ne.some((i)=>i.code===n)}function eC(n){if(n.continent==="North America")return Ui("us-east-1");if(n.continent==="Europe")return Ui("eu-west-1");if(n.continent==="Asia")return Ui("ap-southeast-1");return Ui("us-east-1")}function tC(n){let i=[...Ne];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function rC(n){let i=Ui(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of Ne){if(o.code===n)continue;let c=Ri(i,o),l=Pi(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:l})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function Ri(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=Qe(n.location),c=Qe(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Pi(n,i){return Qe(n.location)===Qe(i.location)}function Qe(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function yy(n){return`${n.name} (${n.code})`}function nC(n){return n.map((i)=>yy(i)).join(`
2730
+ `)}function iC(){let n={total:Ne.length,byContinent:{},byPricingTier:{}};for(let i of Ne){let s=Qe(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class Cm{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let s of this.accounts.values())n[s.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((s,o)=>s+o,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Em{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var sC=new Cm,oC=new Em;var Sy={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"}]}},aC={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"]}}}]}}},cC={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 dC(n){return Sy[n]}function lC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function uC(n){let i=[],s=[],o=n.accounts.filter((f)=>f.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((f)=>f.email),l=c.filter((f,S)=>c.indexOf(f)!==S);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((f)=>f.alias),h=u.filter((f,S)=>u.indexOf(f)!==S);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((f)=>f.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((f)=>f.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function gC(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2731
+ `)}function pC(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:f="bun run cloud deploy",testCommand:S="bun test",buildCommand:A="bun run build"}=n,v=!!u;return`name: ${i}
2755
2732
 
2756
2733
  on:
2757
2734
  ${s}:
@@ -2820,7 +2797,7 @@ jobs:
2820
2797
 
2821
2798
  - name: Post-deployment tests
2822
2799
  run: bun run cloud test:smoke
2823
- `}function sC(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2800
+ `}function mC(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2824
2801
 
2825
2802
  on:
2826
2803
  push:
@@ -2876,7 +2853,7 @@ ${i.map((l,u)=>` ${u>0?"elif":"if"} [[ "\${{ github.ref }}" == "refs/he
2876
2853
 
2877
2854
  - name: Deploy
2878
2855
  run: bun run cloud deploy --env=\${{ needs.determine-environment.outputs.environment }}
2879
- `}function oC(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2856
+ `}function fC(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2880
2857
 
2881
2858
  on:
2882
2859
  pull_request:
@@ -2981,7 +2958,7 @@ jobs:
2981
2958
  bun run cloud env:preview --destroy \\
2982
2959
  --branch=\${{ github.head_ref }} \\
2983
2960
  --pr=\${{ github.event.pull_request.number }}
2984
- `}function aC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2961
+ `}function hC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2985
2962
 
2986
2963
  on:
2987
2964
  schedule:
@@ -3023,7 +3000,7 @@ jobs:
3023
3000
 
3024
3001
  - name: Deploy
3025
3002
  run: bun run cloud deploy --env=\${{ env.ENVIRONMENT }}
3026
- `}function cC(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3003
+ `}function AC(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3027
3004
 
3028
3005
  on:
3029
3006
  workflow_dispatch:
@@ -3070,7 +3047,7 @@ ${i.map((c)=>` - environment: ${c.environment}
3070
3047
 
3071
3048
  - name: Deploy to \${{ matrix.environment }} (\${{ matrix.region }})
3072
3049
  run: bun run cloud deploy --env=\${{ matrix.environment }} --region=\${{ matrix.region }}
3073
- `}function dC(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:l="bun run cloud deploy",testCommand:u="bun test",buildCommand:h="bun run build"}=n;return`stages:
3050
+ `}function yC(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:l="bun run cloud deploy",testCommand:u="bun test",buildCommand:h="bun run build"}=n;return`stages:
3074
3051
  ${i.map((f)=>` - ${f}`).join(`
3075
3052
  `)}
3076
3053
 
@@ -3118,7 +3095,7 @@ deploy:
3118
3095
  only:
3119
3096
  - main
3120
3097
  when: manual
3121
- `}function lC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3098
+ `}function SC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3122
3099
  deploy:${c.name}:
3123
3100
  stage: deploy
3124
3101
  script:
@@ -3159,7 +3136,7 @@ build:
3159
3136
  paths:
3160
3137
  - dist/
3161
3138
  ${o}
3162
- `}function uC(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3139
+ `}function IC(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3163
3140
  - build
3164
3141
  - deploy
3165
3142
  - cleanup
@@ -3204,7 +3181,7 @@ cleanup:preview:
3204
3181
  when: manual
3205
3182
  only:
3206
3183
  - merge_requests
3207
- `}function gC(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3184
+ `}function bC(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3208
3185
  - deploy
3209
3186
 
3210
3187
  variables:
@@ -3223,7 +3200,7 @@ deploy:scheduled:
3223
3200
  name: \${ENVIRONMENT}
3224
3201
  only:
3225
3202
  - schedules
3226
- `}function pC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3203
+ `}function CC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3227
3204
  deploy:${c}:
3228
3205
  stage: deploy
3229
3206
  script:
@@ -3244,7 +3221,7 @@ variables:
3244
3221
  default:
3245
3222
  image: oven/bun:latest
3246
3223
  ${o}
3247
- `}function mC(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:l="bun run build",workflows:u=!0}=n;return`version: 2.1
3224
+ `}function EC(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:l="bun run build",workflows:u=!0}=n;return`version: 2.1
3248
3225
 
3249
3226
  orbs:
3250
3227
  aws-cli: circleci/aws-cli@4.0
@@ -3327,7 +3304,7 @@ ${u?`workflows:
3327
3304
  branches:
3328
3305
  only: main
3329
3306
  `:""}
3330
- `}function fC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3307
+ `}function vC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3331
3308
  deploy-${l.name}:
3332
3309
  executor: bun-executor
3333
3310
  steps:
@@ -3403,7 +3380,7 @@ workflows:
3403
3380
  requires:
3404
3381
  - test
3405
3382
  ${c}
3406
- `}function hC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3383
+ `}function TC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3407
3384
 
3408
3385
  orbs:
3409
3386
  aws-cli: circleci/aws-cli@4.0
@@ -3440,7 +3417,7 @@ workflows:
3440
3417
  only: main
3441
3418
  jobs:
3442
3419
  - deploy
3443
- `}function AC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3420
+ `}function wC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3444
3421
  deploy-${l}:
3445
3422
  executor: bun-executor
3446
3423
  steps:
@@ -3516,7 +3493,7 @@ workflows:
3516
3493
  requires:
3517
3494
  - test
3518
3495
  ${c}
3519
- `}function yC(n){let{regions:i,environment:s}=n,o=i.map((l)=>`
3496
+ `}function RC(n){let{regions:i,environment:s}=n,o=i.map((l)=>`
3520
3497
  deploy-${l.replace(/-/g,"_")}:
3521
3498
  executor: bun-executor
3522
3499
  environment:
@@ -3585,7 +3562,7 @@ workflows:
3585
3562
  requires:
3586
3563
  - test
3587
3564
  ${c}
3588
- `}class Zd{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var uy=new Zd;class el{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:l=60,rpo:u=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+n,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+i,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(n){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let u of s.runbook.steps){if(console.log(`Step ${u.order}: ${u.name}`),console.log(` ${u.description}`),console.log(` Action: ${u.action}`),console.log(` Estimated: ${u.estimatedDuration} minutes`),i)console.log(" [SKIPPED - DRY RUN]");else if(u.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let l={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(l)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let l of n.resources){if(!l.replicationEnabled)i.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")i.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var gy=new el;class tl{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(n=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:n},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var py=new tl;class rl{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var my=new rl;class nl{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var fy=new nl;class Yt{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Yt.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Yt.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Yt.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Yt.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:n.map((i)=>({value:i,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var hy=new Yt;class il{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let l=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=l,!l){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=o.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((f)=>setTimeout(f,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Ay=new il;class Qi{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=Qi.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=Qi.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let l=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-l.trafficPercentage,s.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(s,l,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:l}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&o.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var yy=new Qi;class sl{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((u)=>u.id===i);if(!c)throw Error(`Variant not found: ${i}`);let l=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${l}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let S of i.variants){let A=i.metrics.variants[S.id];if(A&&A.conversionRate>o)o=A.conversionRate,s=S}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],l=i.metrics.variants[s.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,f=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:n,winningVariant:s.name,confidence:f?95:75,improvement:u,statisticalSignificance:f,metrics:i.metrics,recommendation:this.generateRecommendation(u,f,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;i[o.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3565
+ `}class tl{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var Iy=new tl;class rl{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:l=60,rpo:u=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+n,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+i,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(n){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let u of s.runbook.steps){if(console.log(`Step ${u.order}: ${u.name}`),console.log(` ${u.description}`),console.log(` Action: ${u.action}`),console.log(` Estimated: ${u.estimatedDuration} minutes`),i)console.log(" [SKIPPED - DRY RUN]");else if(u.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let l={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(l)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let l of n.resources){if(!l.replicationEnabled)i.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")i.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var by=new rl;class nl{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(n=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:n},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var Cy=new nl;class il{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var Ey=new il;class sl{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var vy=new sl;class Yt{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Yt.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Yt.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Yt.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Yt.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:n.map((i)=>({value:i,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var Ty=new Yt;class ol{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let l=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=l,!l){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=o.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((f)=>setTimeout(f,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var wy=new ol;class Qi{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=Qi.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=Qi.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let l=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-l.trafficPercentage,s.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(s,l,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:l}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&o.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Ry=new Qi;class al{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((u)=>u.id===i);if(!c)throw Error(`Variant not found: ${i}`);let l=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${l}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let S of i.variants){let A=i.metrics.variants[S.id];if(A&&A.conversionRate>o)o=A.conversionRate,s=S}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],l=i.metrics.variants[s.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,f=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:n,winningVariant:s.name,confidence:f?95:75,improvement:u,statisticalSignificance:f,metrics:i.metrics,recommendation:this.generateRecommendation(u,f,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;i[o.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3589
3566
 
3590
3567
  exports.handler = (event, _context, _callback) => {
3591
3568
  const request = event.Records[0].cf.request;
@@ -3632,7 +3609,7 @@ exports.handler = (event, _context, _callback) => {
3632
3609
  }`).join(" else ")}
3633
3610
 
3634
3611
  callback(null, request);
3635
- };`}clear(){this.tests.clear(),this.testCounter=0}}var Sy=new sl;class ol{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,l={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,l),l}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var Iy=new ol;class ym{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var SC=new ym;class Sm{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var IC=new Sm;class al{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(c),c}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(c),c}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3612
+ };`}clear(){this.tests.clear(),this.testCounter=0}}var Dy=new al;class cl{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,l={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,l),l}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var Py=new cl;class vm{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var DC=new vm;class Tm{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var PC=new Tm;class dl{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(c),c}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(c),c}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3636
3613
  | filter @message like /ERROR/
3637
3614
  | stats count() by bin(5m)
3638
3615
  | sort @timestamp desc`,logGroupNames:n})}createLatencyAnalysisQuery(n){return this.createInsightsQuery({name:"Latency Analysis",description:"Analyze request latency patterns",query:`fields @timestamp, @duration
@@ -3642,7 +3619,7 @@ exports.handler = (event, _context, _callback) => {
3642
3619
  | filter @message like /ERROR/
3643
3620
  | stats count() as error_count by @message
3644
3621
  | sort error_count desc
3645
- | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((l)=>{this.createMetricFilter(c.id,{name:l.metric,filterPattern:l.pattern,metricTransformations:[{metricName:l.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var by=new al;class Zt{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3622
+ | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((l)=>{this.createMetricFilter(c.id,{name:l.metric,filterPattern:l.pattern,metricTransformations:[{metricName:l.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var Ny=new dl;class Zt{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3646
3623
  const synthetics = require('Synthetics');
3647
3624
  const log = require('SyntheticsLogger');
3648
3625
 
@@ -3733,35 +3710,35 @@ const workflowCheck = async function () {
3733
3710
  exports.handler = async () => {
3734
3711
  return await workflowCheck();
3735
3712
  };
3736
- `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:Zt.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var Cy=new Zt;class Im{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],l=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3713
+ `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:Zt.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var ky=new Zt;class wm{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],l=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3737
3714
  `),s.backupBeforeMigration&&!i)console.log("Creating database backup before migration...");for(let h of s.migrations)try{if(console.log(`Applying migration: ${h.version} - ${h.name}`),!i){if(this.generateChecksum(h.up+h.down)!==h.checksum)throw Error("Migration checksum mismatch - migration has been modified");let S=Date.now();h.appliedAt=new Date,h.executionTimeMs=Date.now()-S,console.log(`✓ Applied in ${h.executionTimeMs}ms
3738
3715
  `)}else console.log(`[SKIPPED - DRY RUN]
3739
3716
  `);c.push(h.version)}catch(f){if(console.error(`✗ Failed: ${f instanceof Error?f.message:String(f)}
3740
3717
  `),l.push(h.version),!i)return console.log("Rolling back previously applied migrations..."),await this.rollbackMigrations(c.reverse(),s),{success:!1,version:h.version,appliedMigrations:[],failedMigrations:l,executionTimeMs:Date.now()-o,error:f instanceof Error?f.message:String(f),rollbackPerformed:!0}}let u=Date.now()-o;return console.log(`${i?"[DRY RUN] ":""}Migration plan completed successfully`),console.log(`Total time: ${u}ms`),{success:!0,version:s.migrations[s.migrations.length-1]?.version||"unknown",appliedMigrations:c,failedMigrations:l,executionTimeMs:u}}async rollbackMigrations(n,i){for(let s of n){let o=i.migrations.find((c)=>c.version===s);if(o)console.log(`Rolling back: ${o.version} - ${o.name}`),o.rolledBackAt=new Date,console.log(`✓ Rolled back
3741
3718
  `)}}getMigrationStatus(n){let i=this.plans.get(n);if(!i)throw Error(`Migration plan not found: ${n}`);let s=i.migrations.filter((c)=>c.appliedAt&&!c.rolledBackAt),o=i.migrations.filter((c)=>!c.appliedAt);return{currentVersion:s[s.length-1]?.version||"0.0.0",pendingMigrations:o,appliedMigrations:s,lastMigration:s[s.length-1]}}generateSchemaSQL(n,i,s="postgres"){let o=[],c=[];for(let l of n)switch(l.type){case"add_column":o.push(`ALTER TABLE ${i} ADD COLUMN ${l.columnName} ${l.columnType}${l.nullable===!1?" NOT NULL":""}${l.defaultValue?` DEFAULT ${l.defaultValue}`:""}; `),c.push(`ALTER TABLE ${i} DROP COLUMN ${l.columnName};`);break;case"drop_column":o.push(`ALTER TABLE ${i} DROP COLUMN ${l.columnName};`),c.push(`-- Cannot restore dropped column ${l.columnName}`);break;case"modify_column":if(s==="postgres")o.push(`ALTER TABLE ${i} ALTER COLUMN ${l.columnName} TYPE ${l.newType};`);else o.push(`ALTER TABLE ${i} MODIFY COLUMN ${l.columnName} ${l.newType};`);c.push(`-- Reverting ${l.columnName} type change requires manual intervention`);break;case"add_index":o.push(`CREATE INDEX ${l.indexName} ON ${i} (${(l.columns??[]).join(", ")});`),c.push(`DROP INDEX ${l.indexName};`);break;case"drop_index":o.push(`DROP INDEX ${l.indexName};`),c.push(`-- Cannot restore index ${l.indexName} without schema details`);break}return{up:o.join(`
3742
3719
  `),down:c.reverse().join(`
3743
- `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var bC=new Im;class cl{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3720
+ `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var NC=new wm;class ll{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3744
3721
  1. Checking replication lag...`),i.replicationLag&&i.replicationLag>5000)return{success:!1,message:`Replication lag too high: ${i.replicationLag}ms`};return console.log(` Replication lag: ${i.replicationLag||0}ms (acceptable)`),console.log(`
3745
3722
  2. Promoting replica to standalone instance...`),console.log(`
3746
3723
  3. Updating DNS records...`),console.log(`
3747
3724
  4. Updating application configuration...`),console.log(`
3748
- ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var Ey=new cl;class bm{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((f,S)=>S.executionCount-f.executionCount).slice(0,10),l=o.filter((f)=>f.avgExecutionTime>1000).sort((f,S)=>S.avgExecutionTime-f.avgExecutionTime).slice(0,10),u=this.generateRecommendations(s,l),h={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(i,h),h}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var CC=new bm;class Cm{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let l=s.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((l)=>l.database===o.database&&l.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((l)=>l.database===o.database&&l.table===o.table);if(c!==-1){let l=s.privileges[c];if(l.privileges=l.privileges.filter((u)=>!o.privileges.includes(u)),l.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),l=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${l} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3749
- `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var EC=new Cm;class Em{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3725
+ ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var By=new ll;class Rm{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((f,S)=>S.executionCount-f.executionCount).slice(0,10),l=o.filter((f)=>f.avgExecutionTime>1000).sort((f,S)=>S.avgExecutionTime-f.avgExecutionTime).slice(0,10),u=this.generateRecommendations(s,l),h={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(i,h),h}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var kC=new Rm;class Dm{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let l=s.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((l)=>l.database===o.database&&l.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((l)=>l.database===o.database&&l.table===o.table);if(c!==-1){let l=s.privileges[c];if(l.privileges=l.privileges.filter((u)=>!o.privileges.includes(u)),l.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),l=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${l} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3726
+ `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var BC=new Dm;class Pm{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3750
3727
  Executing rotation for secret: ${i.secretId}`),console.log(`Secret type: ${i.secretType}`),console.log(`Rotation interval: ${i.rotationDays} days`);try{console.log(`
3751
3728
  Rotation steps:`),console.log("1. Creating new secret version...");let s=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let o=i.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),i.lastRotated=new Date,i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),console.log(`
3752
3729
  ✓ Rotation completed successfully`),console.log(` New version: ${s}`),console.log(` Next rotation: ${i.nextRotation.toISOString()}`),{success:!0,secretId:i.secretId,oldVersion:o,newVersion:s,rotatedAt:new Date}}catch(s){return console.error(`
3753
- ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var vC=new Em;class dl{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var vy=new dl;class vm{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3730
+ ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var xC=new Pm;class ul{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var xy=new ul;class Nm{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3754
3731
  Renewing certificate: ${s.domainName}`),console.log(`Certificate ARN: ${s.arn}`);try{return console.log(`
3755
3732
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),s.issuedAt=new Date,s.expiresAt=new Date(Date.now()+31536000000),i.lastRenewal=new Date,i.renewalStatus="success",i.nextRenewal=new Date(s.expiresAt.getTime()-i.renewBeforeDays*24*60*60*1000),console.log(`
3756
- ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var TC=new vm;class Tm{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3733
+ ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var OC=new Nm;class km{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3757
3734
  Executing security scan: ${i.name}`),console.log(`Scan type: ${i.scanType}`),console.log(`Target: ${i.target.type} - ${i.target.identifier}`),i.status="running",i.startedAt=new Date;try{console.log(`
3758
3735
  Scanning...`);let s=this.simulateFindings(i);return i.findings=s,i.status="completed",i.completedAt=new Date,i.summary={totalFindings:s.length,criticalCount:s.filter((o)=>o.severity==="CRITICAL").length,highCount:s.filter((o)=>o.severity==="HIGH").length,mediumCount:s.filter((o)=>o.severity==="MEDIUM").length,lowCount:s.filter((o)=>o.severity==="LOW").length,infoCount:s.filter((o)=>o.severity==="INFO").length,executionTime:i.completedAt.getTime()-i.startedAt.getTime()},console.log(`
3759
- ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((f)=>f.status==="PASS").length,c=s.length,l=c>0?Math.round(o/c*100):0,u;if(l>=90)u="A";else if(l>=80)u="B";else if(l>=70)u="C";else if(l>=60)u="D";else u="F";let h={id:i,accountId:n.accountId,region:n.region,score:l,grade:u,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,h),h}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var wC=new Tm;class wm{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3736
+ ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((f)=>f.status==="PASS").length,c=s.length,l=c>0?Math.round(o/c*100):0,u;if(l>=90)u="A";else if(l>=80)u="B";else if(l>=70)u="C";else if(l>=60)u="D";else u="F";let h={id:i,accountId:n.accountId,region:n.region,score:l,grade:u,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,h),h}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var _C=new km;class Bm{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3760
3737
  Scanning image: ${s}`),console.log(`Scanner: ${i.scanner}`);let o=`scan-result-${Date.now()}-${this.resultCounter++}`,c=this.simulateVulnerabilities(i),l={total:c.length,critical:c.filter((f)=>f.severity==="CRITICAL").length,high:c.filter((f)=>f.severity==="HIGH").length,medium:c.filter((f)=>f.severity==="MEDIUM").length,low:c.filter((f)=>f.severity==="LOW").length,unknown:c.filter((f)=>f.severity==="UNKNOWN").length},u=this.evaluateScanResult(i,l),h={id:o,imageUri:s,scannerType:i.scanner,scanDate:new Date,vulnerabilities:c,summary:l,passed:u};return this.results.set(o,h),console.log(`
3761
- Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var RC=new wm;class Rm{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,l]of Object.entries(o.env))s.push(`ENV ${c}=${l}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3738
+ Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var LC=new Bm;class xm{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,l]of Object.entries(o.env))s.push(`ENV ${c}=${l}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3762
3739
  `)}analyzeImage(n,i){let s=`analysis-${Date.now()}-${this.analysisCounter++}`,o=i.map((h)=>({...h,cacheable:this.isLayerCacheable(h.command)})),c=o.reduce((h,f)=>h+f.size,0),l=o.filter((h)=>!h.cacheable&&h.size>100).length,u={id:s,imageId:n,layers:o,totalSize:c,unnecessaryLayers:l};return this.analyses.set(s,u),u}isLayerCacheable(n){let i=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],s=["CMD","ENTRYPOINT","LABEL"];for(let o of i)if(n.startsWith(o))return!0;for(let o of s)if(n.startsWith(o))return!1;return!1}generateOptimizations(n){let i=this.analyses.get(n);if(!i)throw Error(`Analysis not found: ${n}`);let s=`optimization-${Date.now()}-${this.optimizationCounter++}`,o=[],c=i.layers.filter((S)=>S.command.startsWith("RUN"));if(c.length>5)o.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${c.length} RUN commands found. Combine them to reduce layers.`,example:"RUN apt-get update && apt-get install -y package1 package2",impact:"Reduce image size by 20-30% and improve build time"});let l=i.layers[0];if(l.command.includes("ubuntu")||l.command.includes("debian"))o.push({type:"base_image",priority:"medium",title:"Use Alpine base image",description:"Switch to Alpine Linux for smaller image size",example:"FROM node:18-alpine",impact:"Reduce image size by 50-70%"});let u=i.layers.filter((S)=>S.command.startsWith("COPY"));if(u.length>0&&u[0].index>3)o.push({type:"cache_optimization",priority:"high",title:"Copy dependencies first",description:"Copy package files before source code to leverage layer caching",example:`COPY package*.json ./
3763
3740
  RUN npm install
3764
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},f={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,f),f}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var DC=new Rm;class ll{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var Ty=new ll;class ul{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var wy=new ul;class Dm{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var PC=new Dm;class Pm{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var NC=new Pm;class Nm{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var kC=new Nm;class km{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var BC=new km;class Bm{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((f)=>f.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((f)=>f.vpcId===s?.vpcId).map((f)=>f.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var xC=new Bm;class xm{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let o=Array.from(this.messages.values()).filter((c)=>c.functionName===i.functionName).slice(0,n.maxMessages||10).map((c)=>this.reprocessMessage(c.id));return Promise.all(o)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var OC=new xm;class gl{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let c=n.childHealthChecks.filter((l)=>this.healthChecks.get(l)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=c>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var Ry=new gl;class Om{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let i="";for(let s=0;s<256;s++)i+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return i}generateDigest(n){let s="";for(let o=0;o<64;o++)s+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return s}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var _C=new Om;class _m{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var LC=new _m;class Lm{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((A)=>A.timestamp>=n&&A.timestamp<=i),o=s.length,c=s.filter((A)=>A.bounceType==="Permanent").length,l=s.filter((A)=>A.bounceType==="Transient").length,u=o*10,h=o/u*100,f=new Map;for(let A of s)f.set(A.recipient,(f.get(A.recipient)||0)+1);let S=Array.from(f.entries()).map(([A,v])=>({email:A,count:v})).sort((A,v)=>v.count-A.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((f)=>f.timestamp>=n&&f.timestamp<=i),o=s.length,c=new Set;for(let f of s)for(let S of f.recipients)c.add(S);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var $C=new Lm;class $m{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((w)=>{let B=w.timestamp>=n.startDate&&w.timestamp<=n.endDate,_=!n.campaignId||w.tags?.campaignId===n.campaignId;return B&&_}),o=s.filter((w)=>w.eventType==="send").length,c=s.filter((w)=>w.eventType==="delivery").length,l=s.filter((w)=>w.eventType==="open").length,u=s.filter((w)=>w.eventType==="click").length,h=s.filter((w)=>w.eventType==="bounce").length,f=s.filter((w)=>w.eventType==="complaint").length,S=o>0?c/o*100:0,A=c>0?l/c*100:0,v=c>0?u/c*100:0,C=l>0?u/l*100:0,P=o>0?h/o*100:0,E=c>0?f/c*100:0,I=new Map;for(let w of s)if(w.eventType==="click"){let B=w;I.set(B.link,(I.get(B.link)||0)+1)}let D=Array.from(I.entries()).map(([w,B])=>({link:w,clicks:B})).sort((w,B)=>B.clicks-w.clicks).slice(0,10),x={desktop:0,mobile:0,tablet:0,unknown:0};for(let w of s)if(w.eventType==="open"||w.eventType==="click"){let B=w.userAgent.toLowerCase();if(B.includes("mobile"))x.mobile++;else if(B.includes("tablet"))x.tablet++;else if(B.includes("mozilla"))x.desktop++;else x.unknown++}let O={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:f,deliveryRate:S,openRate:A,clickRate:v,clickToOpenRate:C,bounceRate:P,complaintRate:E,topLinks:D,deviceBreakdown:x,locationBreakdown:{}};return this.reports.set(i,O),O}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var MC=new $m;class Mm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((i)=>({listName:i,listed:Math.random()>0.95,delistUrl:`https://www.${i.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,f=Math.max(0,100-l*10-u*100+h*0.2),S={id:i,domain:n.domain,reputationScore:f,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,S),S}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var FC=new Mm;class Fm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3741
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},f={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,f),f}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var $C=new xm;class gl{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var Oy=new gl;class pl{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var _y=new pl;class Om{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var MC=new Om;class _m{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var FC=new _m;class Lm{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var UC=new Lm;class $m{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var QC=new $m;class Mm{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((f)=>f.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((f)=>f.vpcId===s?.vpcId).map((f)=>f.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var HC=new Mm;class Fm{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let o=Array.from(this.messages.values()).filter((c)=>c.functionName===i.functionName).slice(0,n.maxMessages||10).map((c)=>this.reprocessMessage(c.id));return Promise.all(o)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var GC=new Fm;class ml{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let c=n.childHealthChecks.filter((l)=>this.healthChecks.get(l)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=c>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var Ly=new ml;class Um{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let i="";for(let s=0;s<256;s++)i+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return i}generateDigest(n){let s="";for(let o=0;o<64;o++)s+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return s}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var VC=new Um;class Qm{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var qC=new Qm;class Hm{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((A)=>A.timestamp>=n&&A.timestamp<=i),o=s.length,c=s.filter((A)=>A.bounceType==="Permanent").length,l=s.filter((A)=>A.bounceType==="Transient").length,u=o*10,h=o/u*100,f=new Map;for(let A of s)f.set(A.recipient,(f.get(A.recipient)||0)+1);let S=Array.from(f.entries()).map(([A,v])=>({email:A,count:v})).sort((A,v)=>v.count-A.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((f)=>f.timestamp>=n&&f.timestamp<=i),o=s.length,c=new Set;for(let f of s)for(let S of f.recipients)c.add(S);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var jC=new Hm;class Gm{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((w)=>{let B=w.timestamp>=n.startDate&&w.timestamp<=n.endDate,_=!n.campaignId||w.tags?.campaignId===n.campaignId;return B&&_}),o=s.filter((w)=>w.eventType==="send").length,c=s.filter((w)=>w.eventType==="delivery").length,l=s.filter((w)=>w.eventType==="open").length,u=s.filter((w)=>w.eventType==="click").length,h=s.filter((w)=>w.eventType==="bounce").length,f=s.filter((w)=>w.eventType==="complaint").length,S=o>0?c/o*100:0,A=c>0?l/c*100:0,v=c>0?u/c*100:0,C=l>0?u/l*100:0,P=o>0?h/o*100:0,E=c>0?f/c*100:0,I=new Map;for(let w of s)if(w.eventType==="click"){let B=w;I.set(B.link,(I.get(B.link)||0)+1)}let D=Array.from(I.entries()).map(([w,B])=>({link:w,clicks:B})).sort((w,B)=>B.clicks-w.clicks).slice(0,10),x={desktop:0,mobile:0,tablet:0,unknown:0};for(let w of s)if(w.eventType==="open"||w.eventType==="click"){let B=w.userAgent.toLowerCase();if(B.includes("mobile"))x.mobile++;else if(B.includes("tablet"))x.tablet++;else if(B.includes("mozilla"))x.desktop++;else x.unknown++}let O={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:f,deliveryRate:S,openRate:A,clickRate:v,clickToOpenRate:C,bounceRate:P,complaintRate:E,topLinks:D,deviceBreakdown:x,locationBreakdown:{}};return this.reports.set(i,O),O}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var zC=new Gm;class Vm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((i)=>({listName:i,listed:Math.random()>0.95,delistUrl:`https://www.${i.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,f=Math.max(0,100-l*10-u*100+h*0.2),S={id:i,domain:n.domain,reputationScore:f,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,S),S}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var KC=new Vm;class qm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3765
3742
  <html>
3766
3743
  <body>
3767
3744
  <h1>Welcome, {{userName}}!</h1>
@@ -3781,7 +3758,7 @@ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={si
3781
3758
  <p>If you didn't request this, please ignore this email.</p>
3782
3759
  </body>
3783
3760
  </html>
3784
- `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let s={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},o=this.versions.get(n.templateId)||[];return o.push(s),this.versions.set(n.templateId,o),s}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(l,u)=>{let h=u.trim();return i[h]!==void 0?String(i[h]):l});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let c=(this.versions.get(n)||[]).find((l)=>l.version===i);if(!c)throw Error(`Version ${i} not found for template ${n}`);return s.subject=c.subject,s.htmlPart=c.htmlPart,s.textPart=c.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var UC=new Fm;var Um={};tn(Um,{EmailAnalyticsModule:()=>Ye,EmailRules:()=>_t,EmailScheduling:()=>Ft,EmailSearch:()=>$t,EmailTemplates:()=>we,EmailThreading:()=>Bt,SharedMailboxes:()=>Gt});class $t{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:l=1,ebsVolumeSize:u=10,masterUserName:h="admin",masterUserPassword:f}=n,S=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:S,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:l,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:u},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:h,MasterUserPassword:f||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${S}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:$t.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3761
+ `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let s={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},o=this.versions.get(n.templateId)||[];return o.push(s),this.versions.set(n.templateId,o),s}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(l,u)=>{let h=u.trim();return i[h]!==void 0?String(i[h]):l});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let c=(this.versions.get(n)||[]).find((l)=>l.version===i);if(!c)throw Error(`Version ${i} not found for template ${n}`);return s.subject=c.subject,s.htmlPart=c.htmlPart,s.textPart=c.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var WC=new qm;var jm={};tn(jm,{EmailAnalyticsModule:()=>Ye,EmailRules:()=>_t,EmailScheduling:()=>Ft,EmailSearch:()=>$t,EmailTemplates:()=>Ie,EmailThreading:()=>Bt,SharedMailboxes:()=>Gt});class $t{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:l=1,ebsVolumeSize:u=10,masterUserName:h="admin",masterUserPassword:f}=n,S=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:S,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:l,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:u},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:h,MasterUserPassword:f||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${S}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:$t.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3785
3762
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3786
3763
  const https = require('https');
3787
3764
 
@@ -4353,7 +4330,7 @@ catch (error) {
4353
4330
 
4354
4331
  return { statusCode: 200 };
4355
4332
  };
4356
- `;static createAnalyticsTable(n){return{[`${n.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(n){return{[`${n.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createClickTrackingLambda(n){return{[`${n.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createSesEventProcessorLambda(n){return{[`${n.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ye.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static injectTracking(n){let{html:i,messageId:s,trackingDomain:o}=n,c=`<img src="https://${o}/track/open/${s}" width="1" height="1" style="display:none" alt="" />`,l=i.replace("</body>",`${c}</body>`);return l=l.replace(/href="(https?:\/\/[^"]+)"/g,(u,h)=>{let f=encodeURIComponent(h);return`href="https://${o}/track/click/${s}?url=${f}"`}),l}static calculateMetrics(n){let i=n.filter((f)=>f.sent).length,s=n.filter((f)=>f.delivered).length,o=n.filter((f)=>f.opened).length,c=n.filter((f)=>f.clicked).length,l=n.filter((f)=>f.bounced).length,u=n.filter((f)=>f.complained).length,h=n.filter((f)=>f.unsubscribed).length;return{period:new Date().toISOString(),sent:i,delivered:s,opened:o,clicked:c,bounced:l,complained:u,unsubscribed:h,deliveryRate:i>0?s/i*100:0,openRate:s>0?o/s*100:0,clickRate:o>0?c/o*100:0,bounceRate:i>0?l/i*100:0,complaintRate:s>0?u/s*100:0}}}class we{static TemplateRendererCode=`
4333
+ `;static createAnalyticsTable(n){return{[`${n.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(n){return{[`${n.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createClickTrackingLambda(n){return{[`${n.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createSesEventProcessorLambda(n){return{[`${n.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ye.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static injectTracking(n){let{html:i,messageId:s,trackingDomain:o}=n,c=`<img src="https://${o}/track/open/${s}" width="1" height="1" style="display:none" alt="" />`,l=i.replace("</body>",`${c}</body>`);return l=l.replace(/href="(https?:\/\/[^"]+)"/g,(u,h)=>{let f=encodeURIComponent(h);return`href="https://${o}/track/click/${s}?url=${f}"`}),l}static calculateMetrics(n){let i=n.filter((f)=>f.sent).length,s=n.filter((f)=>f.delivered).length,o=n.filter((f)=>f.opened).length,c=n.filter((f)=>f.clicked).length,l=n.filter((f)=>f.bounced).length,u=n.filter((f)=>f.complained).length,h=n.filter((f)=>f.unsubscribed).length;return{period:new Date().toISOString(),sent:i,delivered:s,opened:o,clicked:c,bounced:l,complained:u,unsubscribed:h,deliveryRate:i>0?s/i*100:0,openRate:s>0?o/s*100:0,clickRate:o>0?c/o*100:0,bounceRate:i>0?l/i*100:0,complaintRate:s>0?u/s*100:0}}}class Ie{static TemplateRendererCode=`
4357
4334
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4358
4335
 
4359
4336
  const s3 = new S3Client({});
@@ -4608,7 +4585,7 @@ The {{appName}} Team`,variables:["appName","userName","resetUrl","expiresIn"],ca
4608
4585
 
4609
4586
  <p>Best regards,<br>The {{appName}} Team</p>
4610
4587
  </body>
4611
- </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(n){return{[`${n.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(n){return{[`${n.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:we.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:n.templateBucket}}}}}}static render(n,i){if(!n||!i)return n;let s=n;return s=s.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(o,c)=>{let l=we.getNestedValue(i,c);return l!==void 0?String(l):o}),s=s.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(o,c,l)=>we.getNestedValue(i,c)?l:""),s=s.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(o,c,l)=>!we.getNestedValue(i,c)?l:""),s=s.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(o,c,l)=>{let u=we.getNestedValue(i,c);if(!Array.isArray(u))return"";return u.map((h,f)=>{let S=l;if(S=S.replace(/\{\{this\}\}/g,String(h)),S=S.replace(/\{\{@index\}\}/g,String(f)),typeof h==="object")Object.entries(h).forEach(([A,v])=>{S=S.replace(new RegExp(`\\{\\{\\s*${A}\\s*\\}\\}`,"g"),String(v))});return S}).join("")}),s}static getNestedValue(n,i){return i.split(".").reduce((s,o)=>s?.[o],n)}static extractVariables(n){let i=new Set,s=n.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of s)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))i.add(c[1].split(".")[0]);let o=n.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of o)i.add(c[1].split(".")[0]);return Array.from(i)}}class Gt{static SharedMailboxLambdaCode=`
4588
+ </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(n){return{[`${n.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(n){return{[`${n.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ie.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:n.templateBucket}}}}}}static render(n,i){if(!n||!i)return n;let s=n;return s=s.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(o,c)=>{let l=Ie.getNestedValue(i,c);return l!==void 0?String(l):o}),s=s.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(o,c,l)=>Ie.getNestedValue(i,c)?l:""),s=s.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(o,c,l)=>!Ie.getNestedValue(i,c)?l:""),s=s.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(o,c,l)=>{let u=Ie.getNestedValue(i,c);if(!Array.isArray(u))return"";return u.map((h,f)=>{let S=l;if(S=S.replace(/\{\{this\}\}/g,String(h)),S=S.replace(/\{\{@index\}\}/g,String(f)),typeof h==="object")Object.entries(h).forEach(([A,v])=>{S=S.replace(new RegExp(`\\{\\{\\s*${A}\\s*\\}\\}`,"g"),String(v))});return S}).join("")}),s}static getNestedValue(n,i){return i.split(".").reduce((s,o)=>s?.[o],n)}static extractVariables(n){let i=new Set,s=n.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of s)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))i.add(c[1].split(".")[0]);let o=n.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of o)i.add(c[1].split(".")[0]);return Array.from(i)}}class Gt{static SharedMailboxLambdaCode=`
4612
4589
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4613
4590
  const { DynamoDBClient, GetItemCommand, PutItemCommand, QueryCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4614
4591
 
@@ -5152,7 +5129,7 @@ async function invokeLambda(functionName, metadata) {
5152
5129
  Payload: JSON.stringify(metadata),
5153
5130
  }));
5154
5131
  }
5155
- `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:_t.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var Qm={};tn(Qm,{default:()=>Ii,handler:()=>Ei});var Ei=`
5132
+ `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:_t.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var zm={};tn(zm,{default:()=>Ii,handler:()=>Ei});var Ei=`
5156
5133
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5157
5134
  const s3 = new S3Client({});
5158
5135
 
@@ -5468,7 +5445,7 @@ catch (error) {
5468
5445
 
5469
5446
  return { statusCode: 200, body: 'OK' };
5470
5447
  };
5471
- `;var Hm={};tn(Hm,{CallAnalytics:()=>Ut,CallRecording:()=>Vt,Callbacks:()=>at,IVRBuilder:()=>Me});class Vt{static RecordingProcessorCode=`
5448
+ `;var Km={};tn(Km,{CallAnalytics:()=>Ut,CallRecording:()=>Vt,Callbacks:()=>at,IVRBuilder:()=>ke});class Vt{static RecordingProcessorCode=`
5472
5449
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
5473
5450
  const { TranscribeClient, StartTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
5474
5451
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -5660,7 +5637,7 @@ else if (jobStatus === 'FAILED') {
5660
5637
 
5661
5638
  return { statusCode: 200 };
5662
5639
  };
5663
- `;static createRecordingsTable(n){return{[`${n.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(n){return{[`${n.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Vt.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:n.recordingBucket,RECORDINGS_TABLE:n.recordingsTable}}}}}}}class Me{nodes=[];connections=[];startNodeId="";static create(n){return new Me}start(){let n={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.startNodeId=n.id,this}playPrompt(n,i){let s={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:n,textType:i?.ssml?"ssml":"text",voice:i?.voice||"Joanna"}};return this.nodes.push(s),this.connectToLast(s.id),this}getInput(n,i){let s={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:n,maxDigits:i?.maxDigits||1,timeout:i?.timeout||5,errorPrompt:i?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(s),this.connectToLast(s.id),this}menu(n,i){let s={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:n,options:i}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToQueue(n,i){let s={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:n,priority:i?.priority||5}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToPhone(n){let i={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:n}};return this.nodes.push(i),this.connectToLast(i.id),this}invokeLambda(n,i){let s={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:n,timeout:i?.timeout||8}};return this.nodes.push(s),this.connectToLast(s.id),this}setAttribute(n,i){let s={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:n,value:i}};return this.nodes.push(s),this.connectToLast(s.id),this}checkHours(n){let i={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:n}};return this.nodes.push(i),this.connectToLast(i.id),this}recordVoicemail(n){let i={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:n?.maxDuration||120,greeting:n?.greeting||"Please leave a message after the beep.",beep:n?.beep!==!1}};return this.nodes.push(i),this.connectToLast(i.id),this}wait(n){let i={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:n}};return this.nodes.push(i),this.connectToLast(i.id),this}disconnect(){let n={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.connectToLast(n.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let n=[],i=new Map(this.nodes.map((o)=>[o.id,o]));for(let o of this.nodes){let c=this.nodeToAction(o,i);if(c)n.push(c)}let s={Version:"2019-10-30",StartAction:this.startNodeId,Actions:n};return JSON.stringify(s,null,2)}nodeToAction(n,i){let s=this.getNextNodeId(n.id),o={NextAction:s||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(n.type){case"start":return null;case"play-prompt":return{Identifier:n.id,Type:"MessageParticipant",Parameters:{Text:n.config.text,TextType:n.config.textType},Transitions:o};case"get-input":return{Identifier:n.id,Type:"GetParticipantInput",Parameters:{Text:n.config.prompt,InputTimeLimitSeconds:n.config.timeout,MaxDigits:n.config.maxDigits},Transitions:{...o,Conditions:[]}};case"transfer-queue":return{Identifier:n.id,Type:"TransferToQueue",Parameters:{QueueId:n.config.queueArn},Transitions:o};case"transfer-phone":return{Identifier:n.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:n.config.phoneNumber},Transitions:o};case"invoke-lambda":return{Identifier:n.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.config.functionArn,InvocationTimeLimitSeconds:n.config.timeout},Transitions:o};case"set-attribute":return{Identifier:n.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[n.config.key]:n.config.value}},Transitions:o};case"check-hours":return{Identifier:n.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:n.config.hoursOfOperationArn},Transitions:{NextAction:s,Conditions:[{NextAction:s,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:n.id,Type:"Wait",Parameters:{Seconds:n.config.seconds},Transitions:o};case"disconnect":return{Identifier:n.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(n){if(this.nodes.length>1){let i=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:i.id,targetNodeId:n,sourcePort:"default"})}}getNextNodeId(n){return this.connections.find((s)=>s.sourceNodeId===n)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>Me.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"}),afterHours:(n)=>Me.create("After Hours").start().playPrompt(n).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect(),callbackRequest:(n)=>Me.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(n).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}class Ut{static MetricsAggregatorCode=`
5640
+ `;static createRecordingsTable(n){return{[`${n.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(n){return{[`${n.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Vt.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:n.recordingBucket,RECORDINGS_TABLE:n.recordingsTable}}}}}}}class ke{nodes=[];connections=[];startNodeId="";static create(n){return new ke}start(){let n={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.startNodeId=n.id,this}playPrompt(n,i){let s={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:n,textType:i?.ssml?"ssml":"text",voice:i?.voice||"Joanna"}};return this.nodes.push(s),this.connectToLast(s.id),this}getInput(n,i){let s={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:n,maxDigits:i?.maxDigits||1,timeout:i?.timeout||5,errorPrompt:i?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(s),this.connectToLast(s.id),this}menu(n,i){let s={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:n,options:i}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToQueue(n,i){let s={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:n,priority:i?.priority||5}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToPhone(n){let i={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:n}};return this.nodes.push(i),this.connectToLast(i.id),this}invokeLambda(n,i){let s={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:n,timeout:i?.timeout||8}};return this.nodes.push(s),this.connectToLast(s.id),this}setAttribute(n,i){let s={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:n,value:i}};return this.nodes.push(s),this.connectToLast(s.id),this}checkHours(n){let i={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:n}};return this.nodes.push(i),this.connectToLast(i.id),this}recordVoicemail(n){let i={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:n?.maxDuration||120,greeting:n?.greeting||"Please leave a message after the beep.",beep:n?.beep!==!1}};return this.nodes.push(i),this.connectToLast(i.id),this}wait(n){let i={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:n}};return this.nodes.push(i),this.connectToLast(i.id),this}disconnect(){let n={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.connectToLast(n.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let n=[],i=new Map(this.nodes.map((o)=>[o.id,o]));for(let o of this.nodes){let c=this.nodeToAction(o,i);if(c)n.push(c)}let s={Version:"2019-10-30",StartAction:this.startNodeId,Actions:n};return JSON.stringify(s,null,2)}nodeToAction(n,i){let s=this.getNextNodeId(n.id),o={NextAction:s||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(n.type){case"start":return null;case"play-prompt":return{Identifier:n.id,Type:"MessageParticipant",Parameters:{Text:n.config.text,TextType:n.config.textType},Transitions:o};case"get-input":return{Identifier:n.id,Type:"GetParticipantInput",Parameters:{Text:n.config.prompt,InputTimeLimitSeconds:n.config.timeout,MaxDigits:n.config.maxDigits},Transitions:{...o,Conditions:[]}};case"transfer-queue":return{Identifier:n.id,Type:"TransferToQueue",Parameters:{QueueId:n.config.queueArn},Transitions:o};case"transfer-phone":return{Identifier:n.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:n.config.phoneNumber},Transitions:o};case"invoke-lambda":return{Identifier:n.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.config.functionArn,InvocationTimeLimitSeconds:n.config.timeout},Transitions:o};case"set-attribute":return{Identifier:n.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[n.config.key]:n.config.value}},Transitions:o};case"check-hours":return{Identifier:n.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:n.config.hoursOfOperationArn},Transitions:{NextAction:s,Conditions:[{NextAction:s,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:n.id,Type:"Wait",Parameters:{Seconds:n.config.seconds},Transitions:o};case"disconnect":return{Identifier:n.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(n){if(this.nodes.length>1){let i=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:i.id,targetNodeId:n,sourcePort:"default"})}}getNextNodeId(n){return this.connections.find((s)=>s.sourceNodeId===n)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>ke.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"}),afterHours:(n)=>ke.create("After Hours").start().playPrompt(n).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect(),callbackRequest:(n)=>ke.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(n).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}class Ut{static MetricsAggregatorCode=`
5664
5641
  const { DynamoDBClient, PutItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
5665
5642
 
5666
5643
  const dynamodb = new DynamoDBClient({});
@@ -6149,7 +6126,7 @@ catch (error) {
6149
6126
  return { statusCode: 500, error: error.message };
6150
6127
  }
6151
6128
  };
6152
- `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:at.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:at.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}var Gm={};tn(Gm,{AbTesting:()=>ve,LinkTracking:()=>Qt,MmsSupport:()=>qt,SmsAnalytics:()=>jt,SmsCampaigns:()=>Ht,SmsChatbot:()=>zt});class Ht{static CampaignManagerCode=`
6129
+ `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:at.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:at.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}var Wm={};tn(Wm,{AbTesting:()=>Ce,LinkTracking:()=>Qt,MmsSupport:()=>qt,SmsAnalytics:()=>jt,SmsCampaigns:()=>Ht,SmsChatbot:()=>zt});class Ht{static CampaignManagerCode=`
6153
6130
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6154
6131
 
6155
6132
  const dynamodb = new DynamoDBClient({});
@@ -7055,7 +7032,7 @@ function generateShortId() {
7055
7032
  }
7056
7033
  return id;
7057
7034
  }
7058
- `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Qt.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:n.replace(o,(h)=>{let f=`${s}-${l++}`,S=`https://${i}/l/${f}`;return c.push({original:h,short:S,id:f}),S}),links:c}}}class ve{static AbTestManagerCode=`
7035
+ `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Qt.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:n.replace(o,(h)=>{let f=`${s}-${l++}`,S=`https://${i}/l/${f}`;return c.push({original:h,short:S,id:f}),S}),links:c}}}class Ce{static AbTestManagerCode=`
7059
7036
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
7060
7037
 
7061
7038
  const dynamodb = new DynamoDBClient({});
@@ -7249,7 +7226,7 @@ function unmarshallTest(item) {
7249
7226
 
7250
7227
  return test;
7251
7228
  }
7252
- `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ve.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let o=ve.hashString(i+n.id)%100,c=0;for(let l=0;l<n.variants.length;l++)if(c+=n.trafficSplit[l],o<c)return n.variants[l];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=ve.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=ve.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=ve.getMetricValue(n,s)/100,u=ve.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),f=Math.sqrt(h*(1-h)*(1/o+1/c));if(f===0)return 0;let S=Math.abs(l-u)/f;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class Vm{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let s={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,s),s}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var QC=new Vm;class qm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),this.checkForAlerts(n,s),s}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((A)=>A.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((A,v)=>A+v.messagesReceived,0),u=o.reduce((A,v)=>A+v.messagesDeleted,0),h=o.reduce((A,v)=>A+v.messagesReprocessed,0),f=o.reduce((A,v)=>A+v.approximateAgeOfOldestMessage,0)/o.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:f,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var HC=new qm;class jm{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let o=[];for(let l=0;l<n.messageCount;l++)o.push({id:`msg-${i}-${l}`,messageId:`${i}-${l}`,body:`Message ${l}`,receiptHandle:`receipt-${i}-${l}`,attributes:{},status:"pending"});let c={id:i,configId:n.configId,messages:o,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,c),c}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((l)=>setTimeout(l,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,c=i.messages.filter((v)=>v.status==="success").map((v)=>v.processingTime||0).filter((v)=>v>0),l=c.length>0?c.reduce((v,C)=>v+C,0)/c.length:0,u=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,h=i.processedCount/u,f=i.messages.length>0?i.failedCount/i.messages.length*100:0,S={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:l,throughput:h,errorRate:f},A=this.metrics.get(n)||[];A.push(S),this.metrics.set(n,A)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var GC=new jm;class zm{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),s}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var VC=new zm;import{deflateRawSync as wi}from"node:zlib";var Di=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Ni(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Di[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function xi(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function ki(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function Xe(n){let i=[],s=[],o=0;for(let u of n){let h=xi(u.data),f=wi(h),S=Ni(h),A=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:v,date:C}=ki(u.date??new Date(0)),P=u.mode??420,E=Buffer.alloc(30+A.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(v,10),E.writeUInt16LE(C,12),E.writeUInt32LE(S,14),E.writeUInt32LE(f.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(A.length,26),E.writeUInt16LE(0,28),A.copy(E,30);let I=Buffer.alloc(46+A.length);I.writeUInt32LE(33639248,0),I.writeUInt16LE(798,4),I.writeUInt16LE(20,6),I.writeUInt16LE(0,8),I.writeUInt16LE(8,10),I.writeUInt16LE(v,12),I.writeUInt16LE(C,14),I.writeUInt32LE(S,16),I.writeUInt32LE(f.length,20),I.writeUInt32LE(h.length,24),I.writeUInt16LE(A.length,28),I.writeUInt16LE(0,30),I.writeUInt16LE(0,32),I.writeUInt16LE(0,34),I.writeUInt16LE(0,36),I.writeUInt32LE((P&65535)<<16,38),I.writeUInt32LE(o,42),A.copy(I,46),i.push(E,f),s.push(I),o+=E.length+f.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function Km(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7229
+ `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ce.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let o=Ce.hashString(i+n.id)%100,c=0;for(let l=0;l<n.variants.length;l++)if(c+=n.trafficSplit[l],o<c)return n.variants[l];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Ce.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=Ce.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=Ce.getMetricValue(n,s)/100,u=Ce.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),f=Math.sqrt(h*(1-h)*(1/o+1/c));if(f===0)return 0;let S=Math.abs(l-u)/f;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class Jm{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let s={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,s),s}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var JC=new Jm;class Xm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),this.checkForAlerts(n,s),s}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((A)=>A.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((A,v)=>A+v.messagesReceived,0),u=o.reduce((A,v)=>A+v.messagesDeleted,0),h=o.reduce((A,v)=>A+v.messagesReprocessed,0),f=o.reduce((A,v)=>A+v.approximateAgeOfOldestMessage,0)/o.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:f,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var XC=new Xm;class Ym{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let o=[];for(let l=0;l<n.messageCount;l++)o.push({id:`msg-${i}-${l}`,messageId:`${i}-${l}`,body:`Message ${l}`,receiptHandle:`receipt-${i}-${l}`,attributes:{},status:"pending"});let c={id:i,configId:n.configId,messages:o,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,c),c}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((l)=>setTimeout(l,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,c=i.messages.filter((v)=>v.status==="success").map((v)=>v.processingTime||0).filter((v)=>v>0),l=c.length>0?c.reduce((v,C)=>v+C,0)/c.length:0,u=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,h=i.processedCount/u,f=i.messages.length>0?i.failedCount/i.messages.length*100:0,S={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:l,throughput:h,errorRate:f},A=this.metrics.get(n)||[];A.push(S),this.metrics.set(n,A)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var YC=new Ym;class Zm{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),s}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var ZC=new Zm;import{deflateRawSync as wi}from"node:zlib";var Di=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Ni(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Di[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function xi(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function ki(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function Je(n){let i=[],s=[],o=0;for(let u of n){let h=xi(u.data),f=wi(h),S=Ni(h),A=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:v,date:C}=ki(u.date??new Date(0)),P=u.mode??420,E=Buffer.alloc(30+A.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(v,10),E.writeUInt16LE(C,12),E.writeUInt32LE(S,14),E.writeUInt32LE(f.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(A.length,26),E.writeUInt16LE(0,28),A.copy(E,30);let I=Buffer.alloc(46+A.length);I.writeUInt32LE(33639248,0),I.writeUInt16LE(798,4),I.writeUInt16LE(20,6),I.writeUInt16LE(0,8),I.writeUInt16LE(8,10),I.writeUInt16LE(v,12),I.writeUInt16LE(C,14),I.writeUInt32LE(S,16),I.writeUInt32LE(f.length,20),I.writeUInt32LE(h.length,24),I.writeUInt16LE(A.length,28),I.writeUInt16LE(0,30),I.writeUInt16LE(0,32),I.writeUInt16LE(0,34),I.writeUInt16LE(0,36),I.writeUInt32LE((P&65535)<<16,38),I.writeUInt32LE(o,42),A.copy(I,46),i.push(E,f),s.push(I),o+=E.length+f.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function ef(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7253
7230
  import * as __userModule from ${JSON.stringify(s)}
7254
7231
  import { resolveApp, createHandlers } from ${JSON.stringify(i)}
7255
7232
 
@@ -7259,9 +7236,9 @@ const __handlers = createHandlers(__app)
7259
7236
  export const http = __handlers.http
7260
7237
  export const queue = __handlers.queue
7261
7238
  export const cli = __handlers.cli
7262
- `}import{execSync as Oi}from"node:child_process";import{createHash as Bi}from"node:crypto";import{cpSync as Wi,mkdtempSync as Vi,rmSync as ji,writeFileSync as Ki}from"node:fs";import{tmpdir as qi}from"node:os";import{dirname as zi,isAbsolute as Ji,join as Le,resolve as Yi}from"node:path";import{fileURLToPath as Zi}from"node:url";var Xi=["adapter.ts","recursion.ts","auto-recursion.ts"];function es(){return Le(zi(Zi(import.meta.url)),"runtime")}function Dy(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Oi(o,{stdio:"inherit",cwd:i})}function wo(n){return Bi("sha256").update(n).digest("hex")}function pl(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function Yr(n){let i=Yi(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)Dy(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Ji(o)?o:Le(i,o),l=Vi(Le(qi(),"tscloud-pkg-"));try{for(let C of Xi)Wi(Le(es(),C),Le(l,C));let u=Le(l,"bootstrap.ts");Ki(u,Km({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let C=h.logs.map((P)=>String(P)).join(`
7239
+ `}import{execSync as Oi}from"node:child_process";import{createHash as Bi}from"node:crypto";import{cpSync as Wi,mkdtempSync as Vi,rmSync as ji,writeFileSync as Ki}from"node:fs";import{tmpdir as qi}from"node:os";import{dirname as zi,isAbsolute as Ji,join as Me,resolve as Yi}from"node:path";import{fileURLToPath as Zi}from"node:url";var Xi=["adapter.ts","recursion.ts","auto-recursion.ts"];function es(){return Me(zi(Zi(import.meta.url)),"runtime")}function $y(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Oi(o,{stdio:"inherit",cwd:i})}function wo(n){return Bi("sha256").update(n).digest("hex")}function fl(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function Yr(n){let i=Yi(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)$y(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Ji(o)?o:Me(i,o),l=Vi(Me(qi(),"tscloud-pkg-"));try{for(let C of Xi)Wi(Me(es(),C),Me(l,C));let u=Me(l,"bootstrap.ts");Ki(u,ef({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let C=h.logs.map((P)=>String(P)).join(`
7263
7240
  `);throw Error(`serverless app bundle failed:
7264
- ${C}`)}let f=h.outputs[0],S=Buffer.from(await f.arrayBuffer()),A="index",v=Xe([{name:`${A}.mjs`,data:S}]);return{zip:v,bundle:S,sha256:wo(v),handlerFile:A,handlers:{http:s.handlers?.http??`${A}.http`,queue:s.handlers?.queue??`${A}.queue`,cli:s.handlers?.cli??`${A}.cli`},bundleBytes:S.length}}finally{ji(l,{recursive:!0,force:!0})}}var Py=["18","20","22"];function ts(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Hi(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=ts(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&Py.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function er(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function ml(n,i,s){return er(n,i,s).map((o)=>o.name)}function fl(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Hi(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,f={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=er(i,c,s),A=S.map((W)=>W.name),v=A.length>0,C=i.logRetention??14,P=i.packaging==="image";if(P&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let E=(i.scheduler??"on")!=="off",I=(i.cache?.driver??"dynamodb")==="dynamodb",D=Boolean(i.assets),x=Li(c,s),O=i.tmpStorage??512,w={},B={},_=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${x}`),e.sub(`arn:aws:s3:::${x}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(v)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let K=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)K.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)K.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");w.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:K,Policies:_}};let Z=(W)=>({TSCLOUD_LAMBDA_MODE:W,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...I?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...v?{TSCLOUD_QUEUE:A[0]}:{},...i.env??{}}),J=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},X=Y.mountPath??"/mnt/local",ae=J&&!Y.accessPointArn,$e=Y.accessPointArn??(ae?e.getAtt("EfsAccessPoint","Arn"):void 0),le=i.vpc?.subnets??[],Re=le.length>0,oe=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||J;if(oe&&!Re)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let dt=Re?{VpcConfig:{SubnetIds:le,SecurityGroupIds:[...i.vpc?.securityGroups??[],...oe?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},mt=ae?le.map((W,ee)=>`EfsMountTarget${ee}`):[],pt=J?{FileSystemConfigs:[{Arn:$e,LocalMountPath:X}]}:{};if(J)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(W,ee,se,ie,de,gt,Fe,Ie=O){w[`${W}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ee}`,RetentionInDays:C}};let Ge=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],an=P?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[se]}}}:{Runtime:l,Handler:se,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Ge.length?{Layers:[...new Set(Ge)]}:{}};w[W]={Type:"AWS::Lambda::Function",DependsOn:[`${W}LogGroup`,...mt],Properties:{FunctionName:ee,Architectures:[u],MemorySize:de,Timeout:gt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:Z(ie)},EphemeralStorage:{Size:Ie},...an,...Fe!==void 0?{ReservedConcurrentExecutions:Fe}:{},...dt,...pt}}}if(pe("HttpFunction",f.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,O),pe("CliFunction",f.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??O),v)pe("QueueFunction",f.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??O);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...v?["QueueFunction"]:[]];if(ue)for(let W of ge)w[`${W}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(W)}},w[`${W}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(W),Name:"live",FunctionVersion:e.getAtt(`${W}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ue}}};let Ee=(W)=>ue?e.ref(`${W}Alias`):e.getAtt(W,"Arn"),ye=(W)=>ue?e.ref(`${W}Alias`):e.ref(W);w.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},w.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ee("HttpFunction"),PayloadFormatVersion:"2.0"}},w.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},w.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},w.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},B.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},B.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ae.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let W=i.certificateArn;if(!W)w.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ee)=>({DomainName:ee,HostedZoneId:i.hostedZoneId}))}},W=e.ref("HttpCertificate");Ae.forEach((ee,se)=>{let ie=`HttpDomain${se}`;if(w[ie]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ee,DomainNameConfigurations:[{CertificateArn:W,EndpointType:"REGIONAL"}]}},w[`HttpApiMapping${se}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(ie),Stage:"$default"}},i.hostedZoneId)w[`HttpDomainRecord${se}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ee,Type:"A",AliasTarget:{DNSName:e.getAtt(ie,"RegionalDomainName"),HostedZoneId:e.getAtt(ie,"RegionalHostedZoneId")}}};B[`CustomDomain${se}`]={Description:`Custom domain ${ee}`,Value:ee},B[`CustomDomainTarget${se}`]={Description:`Point ${ee} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(ie,"RegionalDomainName")}})}if(v)w.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((W,ee)=>{let se=`AppQueue${ee}`,ie=i.queueTimeout??120;w[se]={Type:"AWS::SQS::Queue",Properties:{QueueName:W.name,VisibilityTimeout:Math.min(43200,ie*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let de=W.concurrency??i.queueConcurrency;w[`${se}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(se,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...de?{ScalingConfig:{MaximumConcurrency:Math.max(2,de)}}:{}}},B[`QueueUrl${ee}`]={Description:`Queue URL: ${W.name}`,Value:e.ref(se)}});if(E)w.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ee("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},w.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let ee={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},se=(i.warmFunctions??["http"]).filter((ie)=>ie!=="queue"||v);for(let ie of se){let de=ie.charAt(0).toUpperCase()+ie.slice(1),gt=Math.ceil(i.warm/5),Fe=0;for(let Ie=0;Ie<gt;Ie++){let Ge=Math.min(5,i.warm-Fe);w[`Warmer${de}Rule${Ie}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${ie}-${Ie}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Ge},(an,nr)=>({Id:`warm-${ie}-${Ie}-${nr}`,Arn:e.getAtt(ee[ie],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Fe+=Ge}w[`Warmer${de}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ee[ie]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${ie}-*`)}}}}if(I)w.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},B.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(D){if(w.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:x,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},w.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},w.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="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 ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);w.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)w.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};B.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}w.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${x}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},B.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},B.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let W=[],ee=0;if(i.firewall.rateLimit)W.push({Name:"rate-limit",Priority:ee++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let se={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let ie of i.firewall.rules??[]){let de=se[ie];if(!de)continue;W.push({Name:`managed-${ie}`,Priority:ee++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:de}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${ie}`}})}w.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:W,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},B.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(Re&&oe){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");w.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ae)w.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},le.forEach((W,ee)=>{w[`EfsMountTarget${ee}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:W,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),w.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},B.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")w.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:le}},w.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},B.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")w.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:le}},w.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},w.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},w.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},B.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")w.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},w.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:le,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},w.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},B.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(B.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},B.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},v)B.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let xe={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:P?{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:w,Outputs:B},Be={};for(let W of Object.values(w))Be[W.Type]=(Be[W.Type]??0)+1;return{template:xe,functionNames:f,queueNames:A,resourceSummary:Be}}var Ny=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function ky(n){let i=`php${n.replace(".","")}`;return Ny.map((s)=>`${i}-php-${s}`)}function hl(n,i){let s=`php${n.replace(".","")}`,o=ky(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7241
+ ${C}`)}let f=h.outputs[0],S=Buffer.from(await f.arrayBuffer()),A="index",v=Je([{name:`${A}.mjs`,data:S}]);return{zip:v,bundle:S,sha256:wo(v),handlerFile:A,handlers:{http:s.handlers?.http??`${A}.http`,queue:s.handlers?.queue??`${A}.queue`,cli:s.handlers?.cli??`${A}.cli`},bundleBytes:S.length}}finally{ji(l,{recursive:!0,force:!0})}}var My=["18","20","22"];function ts(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Hi(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=ts(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&My.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function er(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function hl(n,i,s){return er(n,i,s).map((o)=>o.name)}function Al(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Hi(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,f={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=er(i,c,s),A=S.map((K)=>K.name),v=A.length>0,C=i.logRetention??14,P=i.packaging==="image";if(P&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let E=(i.scheduler??"on")!=="off",I=(i.cache?.driver??"dynamodb")==="dynamodb",D=Boolean(i.assets),x=Li(c,s),O=i.tmpStorage??512,w={},B={},_=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${x}`),e.sub(`arn:aws:s3:::${x}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(v)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let W=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)W.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)W.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");w.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:W,Policies:_}};let Z=(K)=>({TSCLOUD_LAMBDA_MODE:K,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...I?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...v?{TSCLOUD_QUEUE:A[0]}:{},...i.env??{}}),J=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},X=Y.mountPath??"/mnt/local",ae=J&&!Y.accessPointArn,Oe=Y.accessPointArn??(ae?e.getAtt("EfsAccessPoint","Arn"):void 0),le=i.vpc?.subnets??[],Te=le.length>0,oe=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||J;if(oe&&!Te)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let dt=Te?{VpcConfig:{SubnetIds:le,SecurityGroupIds:[...i.vpc?.securityGroups??[],...oe?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},mt=ae?le.map((K,ee)=>`EfsMountTarget${ee}`):[],pt=J?{FileSystemConfigs:[{Arn:Oe,LocalMountPath:X}]}:{};if(J)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(K,ee,se,ie,de,gt,Be,Ee=O){w[`${K}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ee}`,RetentionInDays:C}};let Fe=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],an=P?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[se]}}}:{Runtime:l,Handler:se,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Fe.length?{Layers:[...new Set(Fe)]}:{}};w[K]={Type:"AWS::Lambda::Function",DependsOn:[`${K}LogGroup`,...mt],Properties:{FunctionName:ee,Architectures:[u],MemorySize:de,Timeout:gt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:Z(ie)},EphemeralStorage:{Size:Ee},...an,...Be!==void 0?{ReservedConcurrentExecutions:Be}:{},...dt,...pt}}}if(pe("HttpFunction",f.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,O),pe("CliFunction",f.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??O),v)pe("QueueFunction",f.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??O);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...v?["QueueFunction"]:[]];if(ue)for(let K of ge)w[`${K}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(K)}},w[`${K}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(K),Name:"live",FunctionVersion:e.getAtt(`${K}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ue}}};let Re=(K)=>ue?e.ref(`${K}Alias`):e.getAtt(K,"Arn"),ye=(K)=>ue?e.ref(`${K}Alias`):e.ref(K);w.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},w.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Re("HttpFunction"),PayloadFormatVersion:"2.0"}},w.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},w.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},w.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},B.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},B.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Se=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Se.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let K=i.certificateArn;if(!K)w.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Se[0],...Se.length>1?{SubjectAlternativeNames:Se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Se.map((ee)=>({DomainName:ee,HostedZoneId:i.hostedZoneId}))}},K=e.ref("HttpCertificate");Se.forEach((ee,se)=>{let ie=`HttpDomain${se}`;if(w[ie]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ee,DomainNameConfigurations:[{CertificateArn:K,EndpointType:"REGIONAL"}]}},w[`HttpApiMapping${se}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(ie),Stage:"$default"}},i.hostedZoneId)w[`HttpDomainRecord${se}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ee,Type:"A",AliasTarget:{DNSName:e.getAtt(ie,"RegionalDomainName"),HostedZoneId:e.getAtt(ie,"RegionalHostedZoneId")}}};B[`CustomDomain${se}`]={Description:`Custom domain ${ee}`,Value:ee},B[`CustomDomainTarget${se}`]={Description:`Point ${ee} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(ie,"RegionalDomainName")}})}if(v)w.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((K,ee)=>{let se=`AppQueue${ee}`,ie=i.queueTimeout??120;w[se]={Type:"AWS::SQS::Queue",Properties:{QueueName:K.name,VisibilityTimeout:Math.min(43200,ie*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let de=K.concurrency??i.queueConcurrency;w[`${se}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(se,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...de?{ScalingConfig:{MaximumConcurrency:Math.max(2,de)}}:{}}},B[`QueueUrl${ee}`]={Description:`Queue URL: ${K.name}`,Value:e.ref(se)}});if(E)w.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},w.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let ee={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},se=(i.warmFunctions??["http"]).filter((ie)=>ie!=="queue"||v);for(let ie of se){let de=ie.charAt(0).toUpperCase()+ie.slice(1),gt=Math.ceil(i.warm/5),Be=0;for(let Ee=0;Ee<gt;Ee++){let Fe=Math.min(5,i.warm-Be);w[`Warmer${de}Rule${Ee}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${ie}-${Ee}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Fe},(an,nr)=>({Id:`warm-${ie}-${Ee}-${nr}`,Arn:e.getAtt(ee[ie],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Be+=Fe}w[`Warmer${de}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ee[ie]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${ie}-*`)}}}}if(I)w.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},B.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(D){if(w.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:x,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},w.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},w.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="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 ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);w.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)w.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};B.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}w.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${x}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},B.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},B.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let K=[],ee=0;if(i.firewall.rateLimit)K.push({Name:"rate-limit",Priority:ee++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let se={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let ie of i.firewall.rules??[]){let de=se[ie];if(!de)continue;K.push({Name:`managed-${ie}`,Priority:ee++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:de}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${ie}`}})}w.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:K,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},B.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(Te&&oe){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");w.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ae)w.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},le.forEach((K,ee)=>{w[`EfsMountTarget${ee}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:K,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),w.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},B.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")w.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:le}},w.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},B.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")w.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:le}},w.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},w.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},w.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},B.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")w.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},w.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:le,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},w.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},B.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(B.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},B.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},v)B.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let xe={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:P?{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:w,Outputs:B},$e={};for(let K of Object.values(w))$e[K.Type]=($e[K.Type]??0)+1;return{template:xe,functionNames:f,queueNames:A,resourceSummary:$e}}var Fy=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function Uy(n){let i=`php${n.replace(".","")}`;return Fy.map((s)=>`${i}-php-${s}`)}function yl(n,i){let s=`php${n.replace(".","")}`,o=Uy(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7265
7242
 
7266
7243
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7267
7244
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7301,9 +7278,9 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7301
7278
  # Runtime assets (bootstrap, runtime loops, fpm config) are added by the build
7302
7279
  # orchestrator after the image is produced. Export /opt as the layer payload.
7303
7280
  CMD ["true"]
7304
- `}function Wm(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7305
- ${hl(i)}`}function Al(n){if(n.kind==="php"){let s=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7306
- ${hl(s,"phpbuild")}
7281
+ `}function tf(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7282
+ ${yl(i)}`}function Sl(n){if(n.kind==="php"){let s=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7283
+ ${yl(s,"phpbuild")}
7307
7284
 
7308
7285
  FROM public.ecr.aws/lambda/provided:al2023
7309
7286
  # Bake the relocated PHP runtime from the build stage.
@@ -7322,7 +7299,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7322
7299
 
7323
7300
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7324
7301
  CMD [ "index.http" ]
7325
- `}import{execFileSync as ot}from"node:child_process";import{mkdtempSync as Wn,readFileSync as ct,rmSync as Vn}from"node:fs";import{tmpdir as Un}from"node:os";import{dirname as ns,join as Te}from"node:path";import{fileURLToPath as rs}from"node:url";function Hn(){return ns(rs(import.meta.url))}function Jm(){return ct(Te(Hn(),"runtime.mjs"),"utf-8")}function jn(n){return ct(Te(Hn(),`${n}-bootstrap`),"utf-8")}function qC(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Wn(Te(Un(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:is(o),h=`node-v${u}-linux-${s}`,f=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=Te(l,"node.tar.xz");Kn(f,S),c("extracting node binary"),ot("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let A=ct(Te(l,h,"bin","node"));c("packaging layer");let v=[{name:"bootstrap",data:jn("node"),mode:493},{name:"runtime.mjs",data:Jm(),mode:420},{name:"bin/node",data:A,mode:493}];return{zip:Xe(v),architecture:i,version:u,fileCount:v.length}}finally{Vn(l,{recursive:!0,force:!0})}}function jC(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Wn(Te(Un(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=Te(l,"bun.zip");Kn(u,h),c("extracting bun binary"),ot("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let f=ct(Te(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:jn("bun"),mode:493},{name:"runtime.mjs",data:Jm(),mode:420},{name:"bin/bun",data:f,mode:493}];return{zip:Xe(S),architecture:i,version:o||"latest",fileCount:S.length}}finally{Vn(l,{recursive:!0,force:!0})}}function Kn(n,i){ot("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function is(n){let i=ot("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),o=JSON.parse(i).find((c)=>c.version.startsWith(`v${n}.`));if(!o)throw Error(`No Node release found for major version ${n}`);return o.version.replace(/^v/,"")}import{createHash as ss}from"node:crypto";var Ro="x-ts-cloud-invoke-depth",Do="x-ts-cloud-invoke-chain",Po="x-ts-cloud-trace-id";function yl(n){return ss("sha256").update(n).digest("hex").slice(0,8)}var Zr={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function nn(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function Sl(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Il(n,i=Zr){let s=yl(n.functionId),o=Sl(nn(n.headers,Do)),c=n.traceId??nn(n.headers,Po)??crypto.randomUUID(),l=[...o,s],u=o.filter((v)=>v===s).length,h=o[o.length-1]===s,f=Number.parseInt(nn(n.headers,Ro)??"",10),S=Math.max(l.length,Number.isFinite(f)?f+1:0),A="ok";if(S>i.maxDepth)A="depth_exceeded";else if(u>=i.maxRepeats)A="cycle_detected";else if(h&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:S,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[Ro]:String(S),[Do]:l.join("."),[Po]:c}}}var qn={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 Gi{limits;clock;traces=new Map;breakers=new Map;constructor(n=Zr,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Il(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let l=this.breakers.get(n)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:l.openUntil})}return{...i,allowed:!1,reason:s,message:qn[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function No(n){return{...n.propagate}}function ko(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??qn[n.reason],depth:n.depth,traceId:n.traceId}}}import{AsyncLocalStorage as as}from"node:async_hooks";var Xm=new as;function zn(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function os(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function By(n){let i=n===!1?{enabled:!1}:n??{},s=zn("TS_CLOUD_RECURSION_PROTECTION"),o=zn("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...Zr,...i.limits},functionId:i.functionId??os()}}var De,Se;function xy(){let n=globalThis.fetch;if(!n||De===n)return()=>{};Se=n;let i=async(s,o)=>{let c=Xm.getStore();if(!c)return Se(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,h]of Object.entries(No(c)))l.set(u,h);if(s instanceof Request)return Se(new Request(s,{headers:l}),o);return Se(s,{...o,headers:l})};return Object.assign(i,n),globalThis.fetch=i,De=i,()=>{if(globalThis.fetch===De&&Se)globalThis.fetch=Se;De=void 0}}var lt,rn;function Oy(n){if(!lt||JSON.stringify(rn)!==JSON.stringify(n))lt=new Gi(n),rn=n;return lt}function zC(){if(lt=void 0,rn=void 0,De&&Se&&globalThis.fetch===De)globalThis.fetch=Se;De=void 0,Se=void 0}function Ym(n,i){let s=By(i);if(!s.enabled)return;let o=Oy(s.limits),c={functionId:s.functionId,headers:n},l=o.check(c);return{verdict:l,blocked:!l.allowed&&!s.detectionOnly,observed:!l.allowed&&s.detectionOnly}}function Zm(n,i){return xy(),Xm.run(n,i)}function KC(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var cs=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function ls(n){if(!n)return!0;return cs.test(n)}function us(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function _y(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[h,f]of Object.entries(n.headers??{}))if(f!==void 0)c.set(h,f);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let l=n.requestContext.http.method,u;if(n.body!==void 0&&l!=="GET"&&l!=="HEAD")u=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:l,headers:c,body:u})}async function ef(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let u of o)s.push(u);n.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;i[h]=u});let c=Buffer.from(await n.arrayBuffer()),l=ls(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function Ly(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=us(i);if(o.enabled){let u=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||u!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=Ym(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=ko(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=_y(s);if(!c){let u=await n(l);return ef(u)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return Zm(c.verdict,async()=>ef(await n(l)))}}function ds(n){try{return JSON.parse(n)}catch{return n}}function $y(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(ds(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function My(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function WC(n,i){return{http:Ly(n.fetch,i),queue:$y(n.queue),cli:My(n.cli)}}function tf(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7302
+ `}import{execFileSync as ot}from"node:child_process";import{mkdtempSync as Wn,readFileSync as ct,rmSync as Vn}from"node:fs";import{tmpdir as Un}from"node:os";import{dirname as ns,join as ve}from"node:path";import{fileURLToPath as rs}from"node:url";function Hn(){return ns(rs(import.meta.url))}function rf(){return ct(ve(Hn(),"runtime.mjs"),"utf-8")}function jn(n){return ct(ve(Hn(),`${n}-bootstrap`),"utf-8")}function eE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Wn(ve(Un(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:is(o),h=`node-v${u}-linux-${s}`,f=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=ve(l,"node.tar.xz");Kn(f,S),c("extracting node binary"),ot("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let A=ct(ve(l,h,"bin","node"));c("packaging layer");let v=[{name:"bootstrap",data:jn("node"),mode:493},{name:"runtime.mjs",data:rf(),mode:420},{name:"bin/node",data:A,mode:493}];return{zip:Je(v),architecture:i,version:u,fileCount:v.length}}finally{Vn(l,{recursive:!0,force:!0})}}function tE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Wn(ve(Un(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=ve(l,"bun.zip");Kn(u,h),c("extracting bun binary"),ot("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let f=ct(ve(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:jn("bun"),mode:493},{name:"runtime.mjs",data:rf(),mode:420},{name:"bin/bun",data:f,mode:493}];return{zip:Je(S),architecture:i,version:o||"latest",fileCount:S.length}}finally{Vn(l,{recursive:!0,force:!0})}}function Kn(n,i){ot("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function is(n){let i=ot("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),o=JSON.parse(i).find((c)=>c.version.startsWith(`v${n}.`));if(!o)throw Error(`No Node release found for major version ${n}`);return o.version.replace(/^v/,"")}import{createHash as ss}from"node:crypto";var Ro="x-ts-cloud-invoke-depth",Do="x-ts-cloud-invoke-chain",Po="x-ts-cloud-trace-id";function Il(n){return ss("sha256").update(n).digest("hex").slice(0,8)}var Zr={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function nn(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function bl(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Cl(n,i=Zr){let s=Il(n.functionId),o=bl(nn(n.headers,Do)),c=n.traceId??nn(n.headers,Po)??crypto.randomUUID(),l=[...o,s],u=o.filter((v)=>v===s).length,h=o[o.length-1]===s,f=Number.parseInt(nn(n.headers,Ro)??"",10),S=Math.max(l.length,Number.isFinite(f)?f+1:0),A="ok";if(S>i.maxDepth)A="depth_exceeded";else if(u>=i.maxRepeats)A="cycle_detected";else if(h&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:S,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[Ro]:String(S),[Do]:l.join("."),[Po]:c}}}var qn={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 Gi{limits;clock;traces=new Map;breakers=new Map;constructor(n=Zr,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Cl(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let l=this.breakers.get(n)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:l.openUntil})}return{...i,allowed:!1,reason:s,message:qn[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function No(n){return{...n.propagate}}function ko(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??qn[n.reason],depth:n.depth,traceId:n.traceId}}}import{AsyncLocalStorage as as}from"node:async_hooks";var nf=new as;function zn(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function os(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function Qy(n){let i=n===!1?{enabled:!1}:n??{},s=zn("TS_CLOUD_RECURSION_PROTECTION"),o=zn("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...Zr,...i.limits},functionId:i.functionId??os()}}var we,be;function Hy(){let n=globalThis.fetch;if(!n||we===n)return()=>{};be=n;let i=async(s,o)=>{let c=nf.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,h]of Object.entries(No(c)))l.set(u,h);if(s instanceof Request)return be(new Request(s,{headers:l}),o);return be(s,{...o,headers:l})};return Object.assign(i,n),globalThis.fetch=i,we=i,()=>{if(globalThis.fetch===we&&be)globalThis.fetch=be;we=void 0}}var lt,rn;function Gy(n){if(!lt||JSON.stringify(rn)!==JSON.stringify(n))lt=new Gi(n),rn=n;return lt}function rE(){if(lt=void 0,rn=void 0,we&&be&&globalThis.fetch===we)globalThis.fetch=be;we=void 0,be=void 0}function sf(n,i){let s=Qy(i);if(!s.enabled)return;let o=Gy(s.limits),c={functionId:s.functionId,headers:n},l=o.check(c);return{verdict:l,blocked:!l.allowed&&!s.detectionOnly,observed:!l.allowed&&s.detectionOnly}}function of(n,i){return Hy(),nf.run(n,i)}function nE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var cs=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function ls(n){if(!n)return!0;return cs.test(n)}function us(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function Vy(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[h,f]of Object.entries(n.headers??{}))if(f!==void 0)c.set(h,f);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let l=n.requestContext.http.method,u;if(n.body!==void 0&&l!=="GET"&&l!=="HEAD")u=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:l,headers:c,body:u})}async function af(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let u of o)s.push(u);n.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;i[h]=u});let c=Buffer.from(await n.arrayBuffer()),l=ls(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function qy(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=us(i);if(o.enabled){let u=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||u!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=sf(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=ko(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=Vy(s);if(!c){let u=await n(l);return af(u)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return of(c.verdict,async()=>af(await n(l)))}}function ds(n){try{return JSON.parse(n)}catch{return n}}function jy(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(ds(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function zy(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function iE(n,i){return{http:qy(n.fetch,i),queue:jy(n.queue),cli:zy(n.cli)}}function cf(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7326
7303
  [global]
7327
7304
  daemonize = no
7328
7305
  error_log = ${n.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7339,4 +7316,4 @@ decorate_workers_output = no
7339
7316
  php_admin_value[error_log] = /dev/stderr
7340
7317
  php_admin_flag[log_errors] = on
7341
7318
  clear_env = no
7342
- `}import{readFileSync as ms}from"node:fs";import{dirname as ps,join as Qn}from"node:path";import{fileURLToPath as gs}from"node:url";function ys(){return Qn(ps(gs(import.meta.url)),"runtime-assets")}function en(){let n=ys(),i=(s)=>ms(Qn(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:tf(),mode:420}]}function bl(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var rf=["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 ut}from"node:child_process";import{existsSync as hs,mkdirSync as fs,mkdtempSync as bs,readdirSync as Ss,readFileSync as As,rmSync as Cs,statSync as Jn,writeFileSync as vs}from"node:fs";import{tmpdir as Ts}from"node:os";import{join as Oe,relative as Rs}from"node:path";function*Yn(n){for(let i of Ss(n)){let s=Oe(n,i);if(Jn(s).isDirectory())yield*Yn(s);else yield s}}function JC(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=bs(Oe(Ts(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{vs(Oe(c,"Dockerfile"),Wm(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=Oe(c,"opt");fs(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,Oe(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!hs(Oe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let f=[];for(let C of Yn(h)){let P=Rs(h,C).replace(/\\/g,"/"),E=Jn(C).mode&73?493:420;f.push({name:P,data:As(C),mode:E})}o("Injecting runtime assets");let S=new Set(en().map((C)=>C.path)),A=f.filter((C)=>!S.has(C.name));for(let C of en())A.push({name:C.path,data:C.contents,mode:C.mode});return o("Packaging layer ZIP"),{zip:Xe(A),architecture:i,fileCount:A.length}}finally{Cs(c,{recursive:!0,force:!0})}}import{execSync as Ps}from"node:child_process";import{createHash as Es}from"node:crypto";import{readdirSync as Is,readFileSync as ws,statSync as Zn}from"node:fs";import{join as Ds,relative as Xn,resolve as sn}from"node:path";var Fy=[".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 Ns(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*tr(n,i,s){for(let o of Is(n)){let c=Ds(n,o),l=Xn(i,c).replace(/\\/g,"/");if(Ns(l,s))continue;if(Zn(c).isDirectory())yield*tr(c,i,s);else yield c}}function Bo(n){if(n.skipBuild)return;let i=sn(n.projectRoot??process.cwd()),s=n.app.build??rf;for(let o of s)n.onStep?.(`build: ${o}`),Ps(o,{stdio:"inherit",cwd:i})}function xo(n,i=[]){let s=sn(n),o=[...Fy,zr(),...i],c=[];for(let l of tr(s,s,o)){let u=Xn(s,l).replace(/\\/g,"/"),h=(Zn(l).mode&73)!==0;c.push({name:u,data:ws(l),mode:h?493:420})}return c}function Cl(n){let i=sn(n.projectRoot??process.cwd());Bo(n),n.onStep?.("packaging application tree");let s=xo(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=Xe(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:Es("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class nf{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var XC=new nf;class El{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var Uy=new El;class sf{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var YC=new sf;class of{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var ZC=new of;class af{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var eE=new af;export{YS,ZS,Nd,Mp,kd,Bd,zr,L,d,xd,Fp,U,Od,g,bA,_i,_d,Ld,me,$d,CA,r,t,eI,tI,p,rI,nI,iI,sI,oI,Kt,Md,Li,EA,aI,cI,Pe,ze,Fd,Up,Qp,dI,Hp,Gp,Vp,So,Ud,te,Kr,yt,Io,St,fe,vA,Qd,bo,qp,jp,zp,Kp,Hd,lI,Q,b,a,y,Ke,m,Wp,We,H,It,uI,Jp,G,Gd,Ne,Wt,Co,re,Vd,ne,TA,Eo,V,q,k,$i,T,Jt,bt,j,e,Wr,gI,Xp,qd,pI,mI,fI,hI,jd,yI,SI,II,bI,CI,EI,vI,TI,wI,RI,DI,PI,wA,RA,DA,PA,NA,kA,BA,Xt,Yp,Zp,Jr,Mi,NI,em,kI,BI,Xr,xI,OI,_I,LI,$I,MI,xA,OA,_A,LA,$A,Fi,FI,vo,MA,tm,M,FA,Je,To,Ct,UA,rm,QA,HA,GA,nm,F,UI,QI,HI,GI,VA,VI,z,qI,jI,zI,zd,Kd,qA,im,sm,KI,WI,JI,XI,YI,jA,Wd,ZI,eb,tb,rb,nb,zA,KA,ib,sb,ob,ab,cb,db,lb,WA,ub,om,Jd,gb,pb,mb,fb,am,cm,dm,hb,Xd,JA,XA,YA,ZA,Yd,ey,Ab,yb,Sb,Ib,bb,Cb,Eb,ty,ry,ny,iy,lm,vb,Tb,wb,Rb,Db,Pb,Nb,kb,Bb,sy,oy,ay,cy,xb,Ob,um,_b,gm,pm,mm,fm,Lb,$b,Mb,Fb,ke,Ui,Ub,Qb,Hb,Gb,Vb,qb,jb,zb,dy,Kb,Wb,hm,Am,Jb,Xb,ly,Yb,Zb,eC,tC,rC,nC,iC,sC,oC,aC,cC,dC,lC,uC,gC,pC,mC,fC,hC,AC,yC,Zd,uy,el,gy,tl,py,rl,my,nl,fy,Yt,hy,il,Ay,Qi,yy,sl,Sy,ol,Iy,ym,SC,Sm,IC,al,by,Zt,Cy,Im,bC,cl,Ey,bm,CC,Cm,EC,Em,vC,dl,vy,vm,TC,Tm,wC,wm,RC,Rm,DC,ll,Ty,ul,wy,Dm,PC,Pm,NC,Nm,kC,km,BC,Bm,xC,xm,OC,gl,Ry,Om,_C,_m,LC,Lm,$C,$m,MC,Mm,FC,Fm,UC,Um,Qm,Hm,Gm,Vm,QC,qm,HC,jm,GC,zm,VC,Xe,Km,Dy,wo,pl,Yr,Py,Hi,er,ml,fl,Ny,ky,hl,Wm,Al,Jm,qC,jC,Ro,Do,Po,yl,Zr,Sl,Il,Gi,No,ko,Xm,By,xy,Oy,zC,Ym,Zm,KC,_y,ef,Ly,$y,My,WC,tf,en,bl,rf,JC,Fy,Bo,xo,Cl,nf,XC,El,Uy,sf,YC,of,ZC,af,eE};
7319
+ `}import{readFileSync as ms}from"node:fs";import{dirname as ps,join as Qn}from"node:path";import{fileURLToPath as gs}from"node:url";function ys(){return Qn(ps(gs(import.meta.url)),"runtime-assets")}function en(){let n=ys(),i=(s)=>ms(Qn(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:cf(),mode:420}]}function El(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var df=["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 ut}from"node:child_process";import{existsSync as hs,mkdirSync as fs,mkdtempSync as bs,readdirSync as Ss,readFileSync as As,rmSync as Cs,statSync as Jn,writeFileSync as vs}from"node:fs";import{tmpdir as Ts}from"node:os";import{join as Le,relative as Rs}from"node:path";function*Yn(n){for(let i of Ss(n)){let s=Le(n,i);if(Jn(s).isDirectory())yield*Yn(s);else yield s}}function sE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=bs(Le(Ts(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{vs(Le(c,"Dockerfile"),tf(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=Le(c,"opt");fs(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,Le(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!hs(Le(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let f=[];for(let C of Yn(h)){let P=Rs(h,C).replace(/\\/g,"/"),E=Jn(C).mode&73?493:420;f.push({name:P,data:As(C),mode:E})}o("Injecting runtime assets");let S=new Set(en().map((C)=>C.path)),A=f.filter((C)=>!S.has(C.name));for(let C of en())A.push({name:C.path,data:C.contents,mode:C.mode});return o("Packaging layer ZIP"),{zip:Je(A),architecture:i,fileCount:A.length}}finally{Cs(c,{recursive:!0,force:!0})}}import{execSync as Ps}from"node:child_process";import{createHash as Es}from"node:crypto";import{readdirSync as Is,readFileSync as ws,statSync as Zn}from"node:fs";import{join as Ds,relative as Xn,resolve as sn}from"node:path";var Ky=[".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 Ns(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*tr(n,i,s){for(let o of Is(n)){let c=Ds(n,o),l=Xn(i,c).replace(/\\/g,"/");if(Ns(l,s))continue;if(Zn(c).isDirectory())yield*tr(c,i,s);else yield c}}function Bo(n){if(n.skipBuild)return;let i=sn(n.projectRoot??process.cwd()),s=n.app.build??df;for(let o of s)n.onStep?.(`build: ${o}`),Ps(o,{stdio:"inherit",cwd:i})}function xo(n,i=[]){let s=sn(n),o=[...Ky,zr(),...i],c=[];for(let l of tr(s,s,o)){let u=Xn(s,l).replace(/\\/g,"/"),h=(Zn(l).mode&73)!==0;c.push({name:u,data:ws(l),mode:h?493:420})}return c}function vl(n){let i=sn(n.projectRoot??process.cwd());Bo(n),n.onStep?.("packaging application tree");let s=xo(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=Je(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:Es("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class lf{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var oE=new lf;class Tl{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var Wy=new Tl;class uf{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var aE=new uf;class gf{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var cE=new gf;class pf{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var dE=new pf;export{aI,cI,Bd,Gp,xd,Od,zr,L,d,_d,Vp,U,Ld,g,DA,_i,$d,Md,me,Fd,PA,r,t,dI,lI,p,uI,gI,pI,mI,fI,Kt,Ud,Li,NA,hI,yI,De,je,Qd,qp,jp,SI,zp,Kp,Wp,So,Hd,te,Kr,yt,Io,St,fe,kA,Gd,bo,Jp,Xp,Yp,Zp,Vd,II,Q,b,BA,xA,em,a,y,ze,m,tm,Ke,H,It,bI,rm,G,qd,Pe,Wt,Co,re,jd,ne,OA,Eo,V,q,k,$i,T,Jt,bt,j,e,Wr,CI,nm,zd,EI,vI,TI,wI,Kd,RI,DI,PI,NI,kI,BI,xI,OI,_I,LI,$I,MI,_A,LA,$A,MA,FA,UA,QA,Xt,im,sm,Jr,Mi,FI,om,UI,QI,Xr,HI,GI,VI,qI,jI,zI,HA,GA,VA,qA,jA,Fi,KI,vo,zA,am,M,KA,We,To,Ct,WA,cm,JA,XA,YA,dm,F,WI,JI,XI,YI,ZA,ZI,z,eb,tb,rb,Wd,Jd,ey,lm,um,nb,ib,sb,ob,ab,ty,Xd,cb,db,lb,ub,gb,ry,ny,pb,mb,fb,hb,Ab,yb,Sb,iy,Ib,gm,Yd,bb,Cb,Eb,vb,pm,mm,fm,Tb,Zd,sy,oy,ay,cy,el,dy,wb,Rb,Db,Pb,Nb,kb,Bb,ly,uy,gy,py,hm,xb,Ob,_b,Lb,$b,Mb,Fb,Ub,Qb,my,fy,hy,Ay,Hb,Gb,Am,Vb,ym,Sm,Im,bm,qb,jb,zb,Kb,Ne,Ui,Wb,Jb,Xb,Yb,Zb,eC,tC,rC,yy,nC,iC,Cm,Em,sC,oC,Sy,aC,cC,dC,lC,uC,gC,pC,mC,fC,hC,AC,yC,SC,IC,bC,CC,EC,vC,TC,wC,RC,tl,Iy,rl,by,nl,Cy,il,Ey,sl,vy,Yt,Ty,ol,wy,Qi,Ry,al,Dy,cl,Py,vm,DC,Tm,PC,dl,Ny,Zt,ky,wm,NC,ll,By,Rm,kC,Dm,BC,Pm,xC,ul,xy,Nm,OC,km,_C,Bm,LC,xm,$C,gl,Oy,pl,_y,Om,MC,_m,FC,Lm,UC,$m,QC,Mm,HC,Fm,GC,ml,Ly,Um,VC,Qm,qC,Hm,jC,Gm,zC,Vm,KC,qm,WC,jm,zm,Km,Wm,Jm,JC,Xm,XC,Ym,YC,Zm,ZC,Je,ef,$y,wo,fl,Yr,My,Hi,er,hl,Al,Fy,Uy,yl,tf,Sl,rf,eE,tE,Ro,Do,Po,Il,Zr,bl,Cl,Gi,No,ko,nf,Qy,Hy,Gy,rE,sf,of,nE,Vy,af,qy,jy,zy,iE,cf,en,El,df,sE,Ky,Bo,xo,vl,lf,oE,Tl,Wy,uf,aE,gf,cE,pf,dE};