@stacksjs/ts-cloud 0.16.46 → 0.16.48

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 (101) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-2gqhzn2r.js → chunk-1fj03993.js} +1 -1
  3. package/dist/bin/{chunk-t1mmfpn1.js → chunk-2pzh0wxc.js} +1 -1
  4. package/dist/bin/{chunk-yp3a0j9n.js → chunk-3pazrfsf.js} +5 -5
  5. package/dist/bin/{chunk-qq1f07te.js → chunk-4mecfcjk.js} +2 -2
  6. package/dist/bin/{chunk-dn1yybdy.js → chunk-akf9j8ps.js} +1 -1
  7. package/dist/bin/{chunk-nhqz2j90.js → chunk-cf3jn2ey.js} +1 -1
  8. package/dist/bin/{chunk-nmr484r7.js → chunk-g2kmr82n.js} +4 -4
  9. package/dist/bin/chunk-hhhrze6m.js +1 -0
  10. package/dist/bin/{chunk-rxy9fa64.js → chunk-nd8vnqk5.js} +79 -79
  11. package/dist/bin/{chunk-her9ny96.js → chunk-psmpw0ap.js} +1 -1
  12. package/dist/bin/{chunk-de69nra4.js → chunk-vhyp4xj0.js} +2 -2
  13. package/dist/bin/chunk-zjvg5pg8.js +1 -0
  14. package/dist/bin/cli.js +17 -17
  15. package/dist/bin/dashboard-server.js +1 -1
  16. package/dist/{chunk-6ea5d30w.js → chunk-22hfejjs.js} +1 -1
  17. package/dist/{chunk-bvzmbksp.js → chunk-25sw2s70.js} +1 -1
  18. package/dist/{chunk-1dbe68z7.js → chunk-2pns2rkf.js} +4 -4
  19. package/dist/{chunk-zwkm3pkb.js → chunk-6mp1fyxe.js} +1 -1
  20. package/dist/{chunk-j2jex596.js → chunk-8vtrjmmj.js} +51 -51
  21. package/dist/{chunk-jzpwfgg1.js → chunk-da62knsv.js} +15 -15
  22. package/dist/{chunk-wb7h8ag4.js → chunk-e8k29wen.js} +1 -1
  23. package/dist/{chunk-wmxw3pe4.js → chunk-fpkpwbv3.js} +5 -5
  24. package/dist/{chunk-v1bzy3tp.js → chunk-gh0ghb21.js} +2 -2
  25. package/dist/chunk-gqadvddh.js +1 -0
  26. package/dist/{chunk-tj852ns1.js → chunk-jhtp3m31.js} +2 -2
  27. package/dist/chunk-kpmxvpcv.js +1 -0
  28. package/dist/{chunk-j73ntebp.js → chunk-kr8aeva1.js} +13 -13
  29. package/dist/{chunk-46bazfbh.js → chunk-ndrpehf8.js} +84 -84
  30. package/dist/{chunk-79snvzcx.js → chunk-p7myt05d.js} +3 -3
  31. package/dist/{chunk-yxzdwe7j.js → chunk-vnarc5gc.js} +3 -3
  32. package/dist/{chunk-astzz50p.js → chunk-x0ep5ybv.js} +2 -2
  33. package/dist/{chunk-r86dh7h7.js → chunk-yme6q7k4.js} +2 -2
  34. package/dist/deploy/index.js +1 -1
  35. package/dist/deploy/server-dns.d.ts +7 -1
  36. package/dist/dns/index.js +1 -1
  37. package/dist/drivers/index.js +1 -1
  38. package/dist/drivers/shared/rpx-gateway.d.ts +39 -2
  39. package/dist/index.js +3 -3
  40. package/dist/operations/index.js +1 -1
  41. package/dist/protection/index.js +1 -1
  42. package/dist/spend/index.js +1 -1
  43. package/dist/ui/404.html +1 -1
  44. package/dist/ui/accept-invitation.html +1 -1
  45. package/dist/ui/access-denied.html +1 -1
  46. package/dist/ui/account/automation.html +6 -6
  47. package/dist/ui/account/security.html +1 -1
  48. package/dist/ui/applications/compose.html +6 -6
  49. package/dist/ui/applications/new.html +2 -2
  50. package/dist/ui/data/backups.html +6 -6
  51. package/dist/ui/data/services.html +6 -6
  52. package/dist/ui/data/volumes.html +6 -6
  53. package/dist/ui/index.html +6 -6
  54. package/dist/ui/infrastructure/topology.html +6 -6
  55. package/dist/ui/integrations.html +1 -1
  56. package/dist/ui/operations/alerts.html +6 -6
  57. package/dist/ui/operations/configuration.html +6 -6
  58. package/dist/ui/operations/jobs.html +6 -6
  59. package/dist/ui/operations/maintenance.html +5 -5
  60. package/dist/ui/operations/observability.html +5 -5
  61. package/dist/ui/operations/previews.html +6 -6
  62. package/dist/ui/operations/queue.html +6 -6
  63. package/dist/ui/operations/regions.html +5 -5
  64. package/dist/ui/operations/releases.html +6 -6
  65. package/dist/ui/operations/spend.html +6 -6
  66. package/dist/ui/operations/workloads.html +5 -5
  67. package/dist/ui/security.html +2 -2
  68. package/dist/ui/server/actions.html +6 -6
  69. package/dist/ui/server/activity.html +2 -2
  70. package/dist/ui/server/capacity.html +5 -5
  71. package/dist/ui/server/database.html +6 -6
  72. package/dist/ui/server/deployments.html +5 -5
  73. package/dist/ui/server/diagnostics.html +1 -1
  74. package/dist/ui/server/firewall.html +6 -6
  75. package/dist/ui/server/fleet.html +6 -6
  76. package/dist/ui/server/logs.html +5 -5
  77. package/dist/ui/server/metrics.html +5 -5
  78. package/dist/ui/server/security.html +1 -1
  79. package/dist/ui/server/services.html +2 -2
  80. package/dist/ui/server/sites.html +6 -6
  81. package/dist/ui/server/ssh-keys.html +6 -6
  82. package/dist/ui/server/team.html +6 -6
  83. package/dist/ui/server/terminal.html +2 -2
  84. package/dist/ui/serverless/alarms.html +6 -6
  85. package/dist/ui/serverless/assets.html +2 -2
  86. package/dist/ui/serverless/cost.html +2 -2
  87. package/dist/ui/serverless/data.html +6 -6
  88. package/dist/ui/serverless/deployments.html +2 -2
  89. package/dist/ui/serverless/firewall.html +1 -1
  90. package/dist/ui/serverless/functions.html +5 -5
  91. package/dist/ui/serverless/logs.html +5 -5
  92. package/dist/ui/serverless/metrics.html +1 -1
  93. package/dist/ui/serverless/queues.html +6 -6
  94. package/dist/ui/serverless/secrets.html +6 -6
  95. package/dist/ui/serverless/traces.html +6 -6
  96. package/dist/ui/serverless.html +6 -6
  97. package/package.json +3 -3
  98. package/dist/bin/chunk-r1kg6yxp.js +0 -1
  99. package/dist/bin/chunk-vt3hjh9q.js +0 -1
  100. package/dist/chunk-4t0vj9a4.js +0 -1
  101. package/dist/chunk-s7q23exe.js +0 -1
@@ -1,4 +1,4 @@
1
- import{R,Mo}from"./chunk-astzz50p.js";import{sn,Xe}from"./chunk-ynprwawa.js";var lI={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}},uI={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 ft,join as Ze,relative as ar}from"node:path";var Od=".ts-cloud",jp="TS_CLOUD_STATE_DIR",ht=null;function _d(n){ht=n?.trim()||null}function Ld(){return Boolean(process.env[jp]?.trim()||ht)}function Jr(){return process.env[jp]?.trim()||ht||Od}function L(...n){return Ze(Jr(),...n)}function d(n,...i){let s=Jr();return ft(s)?Ze(s,...i):Ze(n,s,...i)}function $d(n,i=process.cwd()){let s=(c,l)=>{let u=ar(c,l);return u===""||!u.startsWith("..")&&!ft(u)},o=ft(n)?n:Ze(i,n);return s(d(i),o)}function zp(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function Q(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=zp(n);return i?"serverless":"server"}function Md(n){let{server:i,serverless:s}=zp(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 or(n){return typeof n==="object"&&n!==null?n:{}}function kA(n){return n===!0||typeof n==="object"&&n!==null}function cr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function lr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Mi(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=or(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",f=cr(n,i.environment),h=o.hostname??(u?`mail.${f}`:"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:{},M=o.webmail===!1?!1:x.enabled??!0,w=o.spam??{},O=o.delivery??(u?"direct":"none"),B=o.expose??u,_=lr(h),Z=[...new Set([h,..._?[_]:[],...o.domains??[]])];return{enabled:kA(s),mode:l,version:o.version,hostname:h,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:M,port:x.port??A.webmail,domain:x.domain},delivery:O,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:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Fd(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 Ud(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 fe(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 Qd{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,Fo}from"./chunk-x0ep5ybv.js";import{sn,Xe}from"./chunk-ynprwawa.js";var lI={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}},uI={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 ft,join as Ze,relative as ar}from"node:path";var Od=".ts-cloud",jp="TS_CLOUD_STATE_DIR",ht=null;function _d(n){ht=n?.trim()||null}function Ld(){return Boolean(process.env[jp]?.trim()||ht)}function Jr(){return process.env[jp]?.trim()||ht||Od}function L(...n){return Ze(Jr(),...n)}function d(n,...i){let s=Jr();return ft(s)?Ze(s,...i):Ze(n,s,...i)}function $d(n,i=process.cwd()){let s=(c,l)=>{let u=ar(c,l);return u===""||!u.startsWith("..")&&!ft(u)},o=ft(n)?n:Ze(i,n);return s(d(i),o)}function zp(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function Q(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=zp(n);return i?"serverless":"server"}function Md(n){let{server:i,serverless:s}=zp(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 or(n){return typeof n==="object"&&n!==null?n:{}}function kA(n){return n===!0||typeof n==="object"&&n!==null}function cr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function lr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Mi(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=or(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",f=cr(n,i.environment),h=o.hostname??(u?`mail.${f}`:"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:{},M=o.webmail===!1?!1:x.enabled??!0,w=o.spam??{},O=o.delivery??(u?"direct":"none"),B=o.expose??u,_=lr(h),Z=[...new Set([h,..._?[_]:[],...o.domains??[]])];return{enabled:kA(s),mode:l,version:o.version,hostname:h,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:M,port:x.port??A.webmail,domain:x.domain},delivery:O,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:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Fd(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 Ud(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 fe(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 Qd{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}
@@ -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)=>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 Gd=[400,403,404,416,429,500,502,503,504],Kp=[500,502,503,504],Wp=["GET","HEAD","OPTIONS"],CI="-failover-group",Jp=["default","media-quality-based"],Xp={min:1,max:3},Yp={min:1,max:10};function Eo(n){if(n===void 0)return[...Kp];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${Gd.join(", ")}). Omit it to use the default ${Kp.join(", ")}.`);let i=n.filter((s)=>!Gd.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: ${Gd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Vd(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=Eo(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(!Jp.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Jp.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 re(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)et(n.connectionAttempts,Xp,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)et(n.connectionTimeout,Yp,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Xr(n){return{Quantity:1,Items:[Vd(n)]}}function yt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!Wp.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 ${Wp.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function vo(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 ye(n){return typeof n==="string"?n:void 0}var pr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function St(n,i="the distribution"){let s=_e(n.Origins),o=new Set(s.map((A)=>ye(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[ye(A.Id)??"",A.DomainName])),l=s.some((A)=>ye(A.Id)===void 0);for(let A of s){let v=ye(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)et(A.ConnectionAttempts,Xp,`${i} origin "${v}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)et(A.ConnectionTimeout,Yp,`${i} origin "${v}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,f=_e(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==f.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${f.length} group(s).`);let h=new Set;for(let A of f){let v=ye(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(h.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.`);h.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((M)=>ye(M.OriginId));for(let M of I)if(M&&!o.has(M)&&!l)throw Error(`CloudFront origin failover: ${C} lists member "${M}", 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(Eo(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 M of I){let w=M?ye(c.get(M)):void 0;if(w&&!pr.test(w))throw Error(`CloudFront origin failover: ${C} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${M}" 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=ye(A.TargetOriginId);if(!C)continue;if(h.has(C))yt(A.AllowedMethods??["GET","HEAD"],`${v} of ${i} (origin group "${C}")`);else if(!o.has(C)&&!l&&f.every((P)=>ye(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 he{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:f,edgeFunctions:h,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||"",...re(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(h&&h.length>0)D.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=h.map((x)=>({EventType:x.event,LambdaFunctionARN:x.functionArn}));if(v)he.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=Vd({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),f=i.type??(vo(i.domainName)?"s3":"custom"),h={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...re(i,"the failover origin")},S=re(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(f==="s3"){let A=s.Origins.find((v)=>v.Id===c);if(h.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)h.OriginAccessControlId=A.OriginAccessControlId}else h.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(h),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 he.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`),f={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"]}},h=`
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 Gd=[400,403,404,416,429,500,502,503,504],Kp=[500,502,503,504],Wp=["GET","HEAD","OPTIONS"],CI="-failover-group",Jp=["default","media-quality-based"],Xp={min:1,max:3},Yp={min:1,max:10};function vo(n){if(n===void 0)return[...Kp];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${Gd.join(", ")}). Omit it to use the default ${Kp.join(", ")}.`);let i=n.filter((s)=>!Gd.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: ${Gd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Vd(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=vo(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(!Jp.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Jp.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 re(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)et(n.connectionAttempts,Xp,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)et(n.connectionTimeout,Yp,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Xr(n){return{Quantity:1,Items:[Vd(n)]}}function yt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!Wp.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 ${Wp.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function To(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 ye(n){return typeof n==="string"?n:void 0}var pr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function St(n,i="the distribution"){let s=_e(n.Origins),o=new Set(s.map((A)=>ye(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[ye(A.Id)??"",A.DomainName])),l=s.some((A)=>ye(A.Id)===void 0);for(let A of s){let v=ye(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)et(A.ConnectionAttempts,Xp,`${i} origin "${v}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)et(A.ConnectionTimeout,Yp,`${i} origin "${v}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,f=_e(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==f.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${f.length} group(s).`);let h=new Set;for(let A of f){let v=ye(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(h.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.`);h.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((M)=>ye(M.OriginId));for(let M of I)if(M&&!o.has(M)&&!l)throw Error(`CloudFront origin failover: ${C} lists member "${M}", 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(vo(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 M of I){let w=M?ye(c.get(M)):void 0;if(w&&!pr.test(w))throw Error(`CloudFront origin failover: ${C} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${M}" 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=ye(A.TargetOriginId);if(!C)continue;if(h.has(C))yt(A.AllowedMethods??["GET","HEAD"],`${v} of ${i} (origin group "${C}")`);else if(!o.has(C)&&!l&&f.every((P)=>ye(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 he{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:f,edgeFunctions:h,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||"",...re(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(h&&h.length>0)D.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=h.map((x)=>({EventType:x.event,LambdaFunctionARN:x.functionArn}));if(v)he.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=Vd({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),f=i.type??(To(i.domainName)?"s3":"custom"),h={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...re(i,"the failover origin")},S=re(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(f==="s3"){let A=s.Origins.find((v)=>v.Id===c);if(h.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)h.OriginAccessControlId=A.OriginAccessControlId}else h.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(h),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 he.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`),f={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"]}},h=`
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:f=!0,forwardHeaders:h=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:he.Config.allowedMethods(c),CachedMethods:he.Config.cachedMethods(l),ForwardedValues:{QueryString:f,Headers:h,Cookies:he.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=he.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=he.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=he.Config.cookies(i.cookies,i.allowedCookies)}return n}}var OA=[403,404,500,502,503,504],qd="TsCloud::StorageFailover",To="AllowCloudFrontFailoverRead",gr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,yr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function Zp(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||!gr.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(!yr.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:Eo(i.statusCodes??OA),primaryConnection:re(i,`${c}.failover`)}}function em(n,i){return`${n}.s3.${i}.amazonaws.com`}function tm(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 rm(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 jd(n){return{Sid:To,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function EI(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[qd];return Array.isArray(s)?s:[]}class H{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:f}=n,h=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(f)S.Properties.AliasTarget={DNSName:f.dnsName,HostedZoneId:f.hostedZoneId,EvaluateTargetHealth:f.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:h}}static createCloudFrontAlias(n,i,s){return H.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return H.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return H.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return H.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return H.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 H.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return H.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return H.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return H.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 H.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return H.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return H.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,f=r({slug:o,environment:c,resourceType:"acm"}),h=t(`${f}-${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:h}}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"}),f=t(u),h={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:h,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(f)}};return{key:S,alias:v,logicalId:f,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:f,logicalId:h}=b.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(f=b.addManagedRules(f,{name:"AWSIPReputationList",priority:S++,...b.ManagedRuleGroups.AmazonIpReputation}),f=b.addManagedRules(f,{name:"AWSAnonymousIPList",priority:S++,...b.ManagedRuleGroups.AnonymousIpList}),f=b.addManagedRules(f,{name:"AWSCoreRuleSet",priority:S++,...b.ManagedRuleGroups.CoreRuleSet}),f=b.addManagedRules(f,{name:"AWSKnownBadInputs",priority:S++,...b.ManagedRuleGroups.KnownBadInputs}),f=b.addManagedRules(f,{name:"AWSSQLi",priority:S++,...b.ManagedRuleGroups.SqlDatabase}),c)f=b.addManagedRules(f,{name:"AWSBotControl",priority:S++,...b.ManagedRuleGroups.BotControl});if(l)f=b.setRateLimit(f,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:f,logicalId:h}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function _A(n){let i=n.split(".")[0]??"";return i==="a1"||/^[a-z]+\d+g[a-z]*$/.test(i)}function LA(n="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${_A(n)?"arm64":"x86_64"}`}function nm(n="t3.micro"){return`{{resolve:ssm:${LA(n)}}}`}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c=nm(o),keyName:l,securityGroupIds:u,subnetId:f,userData:h,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(f)E.Properties.SubnetId=f;if(h)E.Properties.UserData=N.Base64(h);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,f=r({slug:i,environment:s,resourceType:"sg"}),h=t(f),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:f},{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:h}}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,f=r({slug:i,environment:s,resourceType:"alb"}),h=t(f),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:f,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:h}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:f="/",healthCheckInterval:h=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:f,HealthCheckIntervalSeconds:h,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}`),f={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)f.Properties.Certificates=[{CertificateArn:c}],f.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:f,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:f=8080,environmentVariables:h={},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"}),M=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"]}},O=t(`${x}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},_=t(`${x}-task`),Z={Type:"AWS::ECS::TaskDefinition",Properties:{Family:x,TaskRoleArn:N.GetAtt(O,"Arn"),ExecutionRoleArn:N.GetAtt(M,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:f,Protocol:"tcp"}],Environment:Object.entries(h).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(_),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:f}];return{cluster:I,taskDefinition:Z,service:Y,taskRole:B,executionRole:w,clusterLogicalId:D,taskDefinitionLogicalId:_,serviceLogicalId:J,taskRoleLogicalId:O,executionRoleLogicalId:M}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:f=128,environmentVariables:h={},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:f,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(h).length>0)E.Properties.Environment={Variables:h};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:f=!0,forwardHeaders:h=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:he.Config.allowedMethods(c),CachedMethods:he.Config.cachedMethods(l),ForwardedValues:{QueryString:f,Headers:h,Cookies:he.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=he.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=he.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=he.Config.cookies(i.cookies,i.allowedCookies)}return n}}var OA=[403,404,500,502,503,504],qd="TsCloud::StorageFailover",wo="AllowCloudFrontFailoverRead",gr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,yr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function Zp(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||!gr.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(!yr.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:vo(i.statusCodes??OA),primaryConnection:re(i,`${c}.failover`)}}function em(n,i){return`${n}.s3.${i}.amazonaws.com`}function tm(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 rm(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 jd(n){return{Sid:wo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function EI(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[qd];return Array.isArray(s)?s:[]}class H{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:f}=n,h=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(f)S.Properties.AliasTarget={DNSName:f.dnsName,HostedZoneId:f.hostedZoneId,EvaluateTargetHealth:f.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:h}}static createCloudFrontAlias(n,i,s){return H.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return H.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return H.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return H.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return H.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 H.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return H.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return H.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return H.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 H.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return H.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return H.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,f=r({slug:o,environment:c,resourceType:"acm"}),h=t(`${f}-${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:h}}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"}),f=t(u),h={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:h,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(f)}};return{key:S,alias:v,logicalId:f,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:f,logicalId:h}=b.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(f=b.addManagedRules(f,{name:"AWSIPReputationList",priority:S++,...b.ManagedRuleGroups.AmazonIpReputation}),f=b.addManagedRules(f,{name:"AWSAnonymousIPList",priority:S++,...b.ManagedRuleGroups.AnonymousIpList}),f=b.addManagedRules(f,{name:"AWSCoreRuleSet",priority:S++,...b.ManagedRuleGroups.CoreRuleSet}),f=b.addManagedRules(f,{name:"AWSKnownBadInputs",priority:S++,...b.ManagedRuleGroups.KnownBadInputs}),f=b.addManagedRules(f,{name:"AWSSQLi",priority:S++,...b.ManagedRuleGroups.SqlDatabase}),c)f=b.addManagedRules(f,{name:"AWSBotControl",priority:S++,...b.ManagedRuleGroups.BotControl});if(l)f=b.setRateLimit(f,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:f,logicalId:h}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function _A(n){let i=n.split(".")[0]??"";return i==="a1"||/^[a-z]+\d+g[a-z]*$/.test(i)}function LA(n="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${_A(n)?"arm64":"x86_64"}`}function nm(n="t3.micro"){return`{{resolve:ssm:${LA(n)}}}`}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c=nm(o),keyName:l,securityGroupIds:u,subnetId:f,userData:h,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(f)E.Properties.SubnetId=f;if(h)E.Properties.UserData=N.Base64(h);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,f=r({slug:i,environment:s,resourceType:"sg"}),h=t(f),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:f},{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:h}}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,f=r({slug:i,environment:s,resourceType:"alb"}),h=t(f),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:f,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:h}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:f="/",healthCheckInterval:h=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:f,HealthCheckIntervalSeconds:h,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}`),f={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)f.Properties.Certificates=[{CertificateArn:c}],f.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:f,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:f=8080,environmentVariables:h={},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"}),M=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"]}},O=t(`${x}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},_=t(`${x}-task`),Z={Type:"AWS::ECS::TaskDefinition",Properties:{Family:x,TaskRoleArn:N.GetAtt(O,"Arn"),ExecutionRoleArn:N.GetAtt(M,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:f,Protocol:"tcp"}],Environment:Object.entries(h).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(_),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:f}];return{cluster:I,taskDefinition:Z,service:Y,taskRole:B,executionRole:w,clusterLogicalId:D,taskDefinitionLogicalId:_,serviceLogicalId:J,taskRoleLogicalId:O,executionRoleLogicalId:M}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:f=128,environmentVariables:h={},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:f,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(h).length>0)E.Properties.Environment={Variables:h};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
@@ -2271,14 +2271,14 @@ catch (error) {
2271
2271
 
2272
2272
  return { statusCode: 200, body: 'OK' };
2273
2273
  };
2274
- `;class V{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:V.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:V.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:V.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,V.createPinpointApp({slug:n.slug})),Object.assign(i,V.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,V.createSmsLambdaRole({slug:n.slug})),Object.assign(i,V.createMessageLogTable({slug:n.slug})),Object.assign(i,V.createOptOutTable({slug:n.slug})),Object.assign(i,V.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`},f={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,V.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,V.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:f,webhookUrl:n.webhookUrl}));return Object.assign(i,V.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:f,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 br(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Sr(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 Ar(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 Cr(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function vr(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 zd{static create(n){let i=Sr(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={},f;if(n.logging!==!1){let h=`${c}LoggingRole`;u[h]={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/*"}]}}]}},f={"Fn::GetAtt":[h,"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}:{},...f?{LoggingRole:f}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[h,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(h))throw Error(`sftp: invalid username ${h}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${h} requires at least one SSH public key`);let A=Tt(h),v=br(S.homeDirectory,h),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:vr(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:h,Role:P,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Cr(i.fileSystemId,v):`/${i.bucket}/${v}`,...i.type==="efs"?{PosixProfile:Ar(h,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,f=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),h=t(f),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:f,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${f}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:A}]}}],Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:o}]}},logicalId:h}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:f=!1}=n,h=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(h),A=[];if(l)A.push("bedrock:InvokeModel");if(u)A.push("bedrock:InvokeModelWithResponseStream");if(f)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:h,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 Yt{static createPostgres(n){return Yt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return Yt.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:f="gp3",masterUsername:h="admin",masterPassword:S,databaseName:A,subnetIds:v,securityGroupIds:C,encrypted:P=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:D=7,publiclyAccessible:x=!1,enableCloudwatchLogs:M=!0,deletionProtection:w=!0}=s,O=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(O),_,Z;if(v&&v.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});Z=t(Y),_={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${O}`,SubnetIds:v,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let J={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:O,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:h,MasterUserPassword:S,AllocatedStorage:u,StorageType:f,StorageEncrypted:P,MultiAZ:I,BackupRetentionPeriod:D,PubliclyAccessible:x,DeletionProtection:w,Tags:[{Key:"Name",Value:O},{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(M)J.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:J,subnetGroup:_,logicalId:B,subnetGroupId:Z}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,f=r({slug:s,environment:o,resourceType:"db-replica"}),h=t(f),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:f,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:h}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),f=t(u),h=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:h,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:f}}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:f=5,writeCapacity:h=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 M=[{AttributeName:c.name,KeyType:"HASH"}];if(l)M.push({AttributeName:l.name,KeyType:"RANGE"});let w={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:x,KeySchema:M,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")w.Properties.ProvisionedThroughput={ReadCapacityUnits:f,WriteCapacityUnits:h};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:f=5,writeCapacity:h=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:f,WriteCapacityUnits:h};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 wo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:f,numCacheClusters:h=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:M=7,snapshotWindow:w,maintenanceWindow:O}=n,B=r({slug:i,environment:s,resourceType:"redis"}),_=t(B),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 ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:A,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:M,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(v)Y.Properties.NumNodeGroups=C,Y.Properties.ReplicasPerNodeGroup=P;else Y.Properties.NumCacheClusters=h;if(D)Y.Properties.AuthToken=D;if(x)Y.Properties.KmsKeyId=x;if(J)Y.Properties.CacheSubnetGroupName=N.Ref(J);if(f&&f.length>0)Y.Properties.SecurityGroupIds=f;if(w)Y.Properties.SnapshotWindow=w;if(O)Y.Properties.PreferredMaintenanceWindow=O;return{replicationGroup:Y,subnetGroup:Z,logicalId:_,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:f,securityGroupIds:h,azMode:S="cross-az",preferredAzs:A,maintenanceWindow:v}=n,C=r({slug:i,environment:s,resourceType:"memcached"}),P=t(C),E,I;if(f&&f.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:f,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(h&&h.length>0)D.Properties.VpcSecurityGroupIds=h;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 ne{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),f=t(u),h={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)h.Properties.Groups=c;if(l&&l.length>0)h.Properties.ManagedPolicyArns=l;return{user:h,logicalId:f}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,f=o||r({slug:i,environment:s,resourceType:"role"}),h=t(f),S={};if(c)S.Service=c;if(l)S.AWS=l;let A={Type:"AWS::IAM::Role",Properties:{RoleName:f,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.ManagedPolicyArns=u;return{role:A,logicalId:h}}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),f={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)f.Properties.ManagedPolicyArns=c;return{group:f,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"}),f=t(u),h=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:h}}},logicalId:f}}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:f,logicalId:h}=ne.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[h]=f;let{user:S,logicalId:A}=ne.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(h)]});l[A]=S;let v,C;if(c){let P=ne.createAccessKey(A,{slug:i,environment:s});v=P.accessKey,C=P.logicalId,l[C]=v}return{user:S,accessKey:v,policy:f,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:h,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,f={},{policy:h,logicalId:S}=ne.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});f[S]=h;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 f[v]=P,{role:P,policy:h,roleLogicalId:v,policyLogicalId:S,resources:f}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[ne.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=[ne.ManagedPolicies.AdministratorAccess];break}let f,h;if(l.length>0){let P=ne.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});f=P.policy,h=P.logicalId,c[h]=f,u=[N.Ref(h)]}let{user:S,logicalId:A}=ne.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[A]=S;let{accessKey:v,logicalId:C}=ne.createAccessKey(A,{slug:i,environment:s});return c[C]=v,{user:S,accessKey:v,policy:f,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:h,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 Kd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:f}=n,h=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(h),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:h,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.BinaryMediaTypes=u;if(f!==void 0)A.Properties.MinimumCompressionSize=f;return{restApi:A,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:f=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:h=["*"],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:f,AllowHeaders:h,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:f=!1,cacheSize:h="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:f,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:c}]}};if(f)P.Properties.CacheClusterSize=h;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:f,userPoolArns:h,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=f||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!h||h.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=h,C.Properties.IdentitySource=f||"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 ie{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,f=o||r({slug:i,environment:s,resourceType:"topic"}),h=t(f),S={Type:"AWS::SNS::Topic",Properties:{TopicName:f,DisplayName:c||f,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:h}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:f=!1}=i,h=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(`${h}-${c}-${A}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:f}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:v}}static subscribeEmail(n,i,s){return ie.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ie.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ie.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ie.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ie.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,f=r({slug:s,environment:o,resourceType:"topic-policy"}),h=t(f),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:h}}static allowCloudWatchAlarms(n,i){return ie.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ie.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ie.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)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class $A{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:f,tracingConfiguration:h}=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(f)E.Properties.LoggingConfiguration={Level:f.level,IncludeExecutionData:f.includeExecutionData,Destinations:f.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(h)E.Properties.TracingConfiguration={Enabled:h.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 Ro{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:f=300,evaluationPeriods:h=1,threshold:S,comparisonOperator:A,treatMissingData:v="notBreaching",actionsEnabled:C=!0,alarmActions:P,okActions:E,insufficientDataActions:I,dimensions:D,unit:x,datapointsToAlarm:M}=n,w=o||r({slug:i,environment:s,resourceType:"alarm"}),O=t(w),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:w,MetricName:c,Namespace:l,Statistic:u,Period:f,EvaluationPeriods:h,Threshold:S,ComparisonOperator:A,TreatMissingData:v,ActionsEnabled:C}};if(P&&P.length>0)B.Properties.AlarmActions=P;if(E&&E.length>0)B.Properties.OKActions=E;if(I&&I.length>0)B.Properties.InsufficientDataActions=I;if(D)B.Properties.Dimensions=Object.entries(D).map(([_,Z])=>({Name:_,Value:Z}));if(x)B.Properties.Unit=x;if(M!==void 0)B.Properties.DatapointsToAlarm=M;return{alarm:B,logicalId:O}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:f,insufficientDataActions:h}=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(f&&f.length>0)v.Properties.OKActions=f;if(h&&h.length>0)v.Properties.InsufficientDataActions=h;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),f={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(f)}},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"}),f=t(u),h={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)h.Properties.RetentionInDays=c;if(l)h.Properties.KmsKeyId=l;return{logGroup:h,logicalId:f}}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,f=c||r({slug:s,environment:o,resourceType:"metric-filter"}),h=t(f);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:h}}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 V{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:V.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:V.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:V.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,V.createPinpointApp({slug:n.slug})),Object.assign(i,V.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,V.createSmsLambdaRole({slug:n.slug})),Object.assign(i,V.createMessageLogTable({slug:n.slug})),Object.assign(i,V.createOptOutTable({slug:n.slug})),Object.assign(i,V.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`},f={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,V.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,V.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:f,webhookUrl:n.webhookUrl}));return Object.assign(i,V.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:f,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 br(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Sr(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 Ar(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 Cr(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function vr(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 zd{static create(n){let i=Sr(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={},f;if(n.logging!==!1){let h=`${c}LoggingRole`;u[h]={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/*"}]}}]}},f={"Fn::GetAtt":[h,"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}:{},...f?{LoggingRole:f}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[h,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(h))throw Error(`sftp: invalid username ${h}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${h} requires at least one SSH public key`);let A=Tt(h),v=br(S.homeDirectory,h),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:vr(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:h,Role:P,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Cr(i.fileSystemId,v):`/${i.bucket}/${v}`,...i.type==="efs"?{PosixProfile:Ar(h,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,f=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),h=t(f),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:f,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${f}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:A}]}}],Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:o}]}},logicalId:h}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:f=!1}=n,h=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(h),A=[];if(l)A.push("bedrock:InvokeModel");if(u)A.push("bedrock:InvokeModelWithResponseStream");if(f)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:h,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 Yt{static createPostgres(n){return Yt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return Yt.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:f="gp3",masterUsername:h="admin",masterPassword:S,databaseName:A,subnetIds:v,securityGroupIds:C,encrypted:P=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:D=7,publiclyAccessible:x=!1,enableCloudwatchLogs:M=!0,deletionProtection:w=!0}=s,O=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(O),_,Z;if(v&&v.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});Z=t(Y),_={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${O}`,SubnetIds:v,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let J={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:O,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:h,MasterUserPassword:S,AllocatedStorage:u,StorageType:f,StorageEncrypted:P,MultiAZ:I,BackupRetentionPeriod:D,PubliclyAccessible:x,DeletionProtection:w,Tags:[{Key:"Name",Value:O},{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(M)J.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:J,subnetGroup:_,logicalId:B,subnetGroupId:Z}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,f=r({slug:s,environment:o,resourceType:"db-replica"}),h=t(f),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:f,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:h}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),f=t(u),h=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:h,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:f}}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:f=5,writeCapacity:h=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 M=[{AttributeName:c.name,KeyType:"HASH"}];if(l)M.push({AttributeName:l.name,KeyType:"RANGE"});let w={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:x,KeySchema:M,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")w.Properties.ProvisionedThroughput={ReadCapacityUnits:f,WriteCapacityUnits:h};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:f=5,writeCapacity:h=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:f,WriteCapacityUnits:h};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 Ro{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:f,numCacheClusters:h=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:M=7,snapshotWindow:w,maintenanceWindow:O}=n,B=r({slug:i,environment:s,resourceType:"redis"}),_=t(B),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 ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:A,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:M,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(v)Y.Properties.NumNodeGroups=C,Y.Properties.ReplicasPerNodeGroup=P;else Y.Properties.NumCacheClusters=h;if(D)Y.Properties.AuthToken=D;if(x)Y.Properties.KmsKeyId=x;if(J)Y.Properties.CacheSubnetGroupName=N.Ref(J);if(f&&f.length>0)Y.Properties.SecurityGroupIds=f;if(w)Y.Properties.SnapshotWindow=w;if(O)Y.Properties.PreferredMaintenanceWindow=O;return{replicationGroup:Y,subnetGroup:Z,logicalId:_,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:f,securityGroupIds:h,azMode:S="cross-az",preferredAzs:A,maintenanceWindow:v}=n,C=r({slug:i,environment:s,resourceType:"memcached"}),P=t(C),E,I;if(f&&f.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:f,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(h&&h.length>0)D.Properties.VpcSecurityGroupIds=h;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 ne{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),f=t(u),h={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)h.Properties.Groups=c;if(l&&l.length>0)h.Properties.ManagedPolicyArns=l;return{user:h,logicalId:f}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,f=o||r({slug:i,environment:s,resourceType:"role"}),h=t(f),S={};if(c)S.Service=c;if(l)S.AWS=l;let A={Type:"AWS::IAM::Role",Properties:{RoleName:f,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.ManagedPolicyArns=u;return{role:A,logicalId:h}}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),f={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)f.Properties.ManagedPolicyArns=c;return{group:f,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"}),f=t(u),h=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:h}}},logicalId:f}}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:f,logicalId:h}=ne.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[h]=f;let{user:S,logicalId:A}=ne.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(h)]});l[A]=S;let v,C;if(c){let P=ne.createAccessKey(A,{slug:i,environment:s});v=P.accessKey,C=P.logicalId,l[C]=v}return{user:S,accessKey:v,policy:f,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:h,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,f={},{policy:h,logicalId:S}=ne.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});f[S]=h;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 f[v]=P,{role:P,policy:h,roleLogicalId:v,policyLogicalId:S,resources:f}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[ne.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=[ne.ManagedPolicies.AdministratorAccess];break}let f,h;if(l.length>0){let P=ne.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});f=P.policy,h=P.logicalId,c[h]=f,u=[N.Ref(h)]}let{user:S,logicalId:A}=ne.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[A]=S;let{accessKey:v,logicalId:C}=ne.createAccessKey(A,{slug:i,environment:s});return c[C]=v,{user:S,accessKey:v,policy:f,userLogicalId:A,accessKeyLogicalId:C,policyLogicalId:h,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 Kd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:f}=n,h=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(h),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:h,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)A.Properties.BinaryMediaTypes=u;if(f!==void 0)A.Properties.MinimumCompressionSize=f;return{restApi:A,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:f=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:h=["*"],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:f,AllowHeaders:h,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:f=!1,cacheSize:h="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:f,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:c}]}};if(f)P.Properties.CacheClusterSize=h;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:f,userPoolArns:h,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=f||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!h||h.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=h,C.Properties.IdentitySource=f||"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 ie{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,f=o||r({slug:i,environment:s,resourceType:"topic"}),h=t(f),S={Type:"AWS::SNS::Topic",Properties:{TopicName:f,DisplayName:c||f,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:h}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:f=!1}=i,h=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(`${h}-${c}-${A}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:f}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:v}}static subscribeEmail(n,i,s){return ie.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ie.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ie.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ie.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ie.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,f=r({slug:s,environment:o,resourceType:"topic-policy"}),h=t(f),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:h}}static allowCloudWatchAlarms(n,i){return ie.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ie.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ie.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)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ie.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class $A{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:f,tracingConfiguration:h}=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(f)E.Properties.LoggingConfiguration={Level:f.level,IncludeExecutionData:f.includeExecutionData,Destinations:f.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(h)E.Properties.TracingConfiguration={Enabled:h.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 Do{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:f=300,evaluationPeriods:h=1,threshold:S,comparisonOperator:A,treatMissingData:v="notBreaching",actionsEnabled:C=!0,alarmActions:P,okActions:E,insufficientDataActions:I,dimensions:D,unit:x,datapointsToAlarm:M}=n,w=o||r({slug:i,environment:s,resourceType:"alarm"}),O=t(w),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:w,MetricName:c,Namespace:l,Statistic:u,Period:f,EvaluationPeriods:h,Threshold:S,ComparisonOperator:A,TreatMissingData:v,ActionsEnabled:C}};if(P&&P.length>0)B.Properties.AlarmActions=P;if(E&&E.length>0)B.Properties.OKActions=E;if(I&&I.length>0)B.Properties.InsufficientDataActions=I;if(D)B.Properties.Dimensions=Object.entries(D).map(([_,Z])=>({Name:_,Value:Z}));if(x)B.Properties.Unit=x;if(M!==void 0)B.Properties.DatapointsToAlarm=M;return{alarm:B,logicalId:O}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:f,insufficientDataActions:h}=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(f&&f.length>0)v.Properties.OKActions=f;if(h&&h.length>0)v.Properties.InsufficientDataActions=h;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),f={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(f)}},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"}),f=t(u),h={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)h.Properties.RetentionInDays=c;if(l)h.Properties.KmsKeyId=l;return{logGroup:h,logicalId:f}}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,f=c||r({slug:s,environment:o,resourceType:"metric-filter"}),h=t(f);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:h}}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 '")}'
2275
2275
  | fields @timestamp, @message
2276
2276
  | sort @timestamp desc
2277
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((f)=>["AWS/EC2","CPUUtilization","InstanceId",f]),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((f)=>[["AWS/EC2","NetworkIn","InstanceId",f,{label:`${f} In`}],["AWS/EC2","NetworkOut","InstanceId",f,{label:`${f} 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((f)=>["AWS/EC2","StatusCheckFailed","InstanceId",f]),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((f)=>["AWS/Lambda","Invocations","FunctionName",f]),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((f)=>["AWS/Lambda","Duration","FunctionName",f]),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((f)=>["AWS/Lambda","Errors","FunctionName",f]),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((f)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",f]),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((f)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",f]),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 '")}'
2278
2278
  | fields @timestamp, @message
2279
2279
  | filter @message like /ERROR|WARN|Exception/
2280
2280
  | sort @timestamp desc
2281
- | limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return Ro.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:f="Average",treatMissingData:h="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:f,TreatMissingData:h}},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 q{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:f,emailConfiguration:h,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:f,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(h)I.Properties.EmailConfiguration={EmailSendingAccount:h.emailSendingAccount,From:h.from,ReplyToEmailAddress:h.replyToEmailAddress,SourceArn:h.sourceArn,ConfigurationSet:h.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:f,idTokenValidity:h,tokenValidityUnits:S,readAttributes:A,writeAttributes:v,explicitAuthFlows:C,preventUserExistenceErrors:P,enableTokenRevocation:E,callbackURLs:I,logoutURLs:D,allowedOAuthFlows:x,allowedOAuthScopes:M,allowedOAuthFlowsUserPoolClient:w,supportedIdentityProviders:O}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),_=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:f,IdTokenValidity:h,TokenValidityUnits:S,ReadAttributes:A,WriteAttributes:v,ExplicitAuthFlows:C,PreventUserExistenceErrors:P,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:D,AllowedOAuthFlows:x,AllowedOAuthScopes:M,AllowedOAuthFlowsUserPoolClient:w,SupportedIdentityProviders:O}},logicalId:_}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),f=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(n),CustomDomainConfig:l}},logicalId:f}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:f,openIdConnectProviderARNs:h}=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:f,OpenIdConnectProviderARNs:h}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,f=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),h=t(f),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(n),Roles:S,RoleMappings:u}},logicalId:h}}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}=q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=q.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...q.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...q.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=q.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...q.AuthFlows.standard]}),{identityPool:u,logicalId:f}=q.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(o,"ProviderName")}]}),{role:h,logicalId:S}=q.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:f}),{attachment:A,logicalId:v}=q.createIdentityPoolRoleAttachment(f,{slug:n,environment:i,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:f,authRole:h,authRoleId:S,attachment:A,attachmentId:v}}}}import{createHash as Tr}from"node:crypto";import{copyFileSync as Rr,existsSync as Rt,readdirSync as Pr,readFileSync as tt,statSync as Er,writeFileSync as nt}from"node:fs";import{basename as Ir,dirname as pn,extname as gn,join as Ve}from"node:path";class j{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:f,deploymentConfigName:h,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:f?.map((D)=>({Key:D.key,Value:D.value,Type:D.type})),DeploymentConfigName:h,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"}),f=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:f}}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}=j.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:f}=j.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:j.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:f}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=j.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:f,logicalId:h}=j.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:j.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:A}=j.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:N.Ref(h),autoRollbackConfiguration:j.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:f,configId:h,deploymentGroup:S,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=j.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:f}=j.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:j.BlueGreenConfigs.standard(),autoRollbackConfiguration:j.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:f}}};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 Tr(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=Ir(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=Pr(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),f=[],h={};for(let A of u){let v=A.replace(i,"").replace(/^[/\\]/,""),C=k.shouldHashFile(v,o),P=Er(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(f.push(D),h[v]=I,s){let x=Ve(s,I),M=pn(x);if(!Rt(M)){let{mkdirSync:w}=Xe("node:fs");w(M,{recursive:!0})}if(C||l)Rr(A,x)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:f,hashMap:h};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 f=o[l];if(!f||f!==u){if(s.push(`/${l}`),f&&f!==u)s.push(`/${f}`)}}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[f,h]of Object.entries(s.hashMap)){if(f===h)continue;let S=[new RegExp(`(src|href)=["']${o}/?${k.escapeRegExp(f)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(f)}["']?\\)`,"g")];for(let A of S)u=u.replace(A,(v)=>v.replace(f,h))}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[f,h]of Object.entries(s.hashMap)){if(f===h)continue;let S=new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(f)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${h})`)}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 f=u.hash!=="",h=u.contentType==="text/html",S=c.unhashed||"public, max-age=3600";if(h)S=c.html||"public, max-age=0, must-revalidate";else if(f)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 Ui{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:f}=n,h=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(h),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:h,Description:c,SecretString:l,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},...f?Object.entries(f).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:f,excludePunctuation:h,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:f,ExcludePunctuation:h,ExcludeUppercase:S,PasswordLength:A||32,RequireEachIncludedType:v!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...P?Object.entries(P).map(([x,M])=>({Key:x,Value:M})):[]]}};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:f,port:h,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(f)C.host=f;if(h)C.port=h;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"}),f=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:f}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:f,vpcSecurityGroupIds:h,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:f,VpcSecurityGroupIds:h,VpcSubnetIds:S};return{rotation:C,logicalId:v}}static SecretTypes={apiKey:(n,i,s)=>Ui.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)=>Ui.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)=>Ui.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Ui.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:f="Standard",tags:h}=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:f,Tags:{Name:S,Environment:s,...h}}},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"),f=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),h=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:f,host:h,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 Zt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:f=10,volumeType:h="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:M,autoSnapshotHour:w=0,autoTune:O=!0,tags:B={}}=n,_=o||r({slug:i,environment:s,resourceType:"search"}),Z=t(_);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:_,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:h,VolumeSize:f},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}},...M&&{AdvancedSecurityOptions:{Enabled:M.enabled,InternalUserDatabaseEnabled:M.internalUserDatabase??!0,...M.masterUserName&&M.masterUserPassword&&{MasterUserOptions:{MasterUserName:M.masterUserName,MasterUserPassword:M.masterUserPassword}},...M.masterUserArn&&{MasterUserOptions:{MasterUserARN:M.masterUserArn}}}},...O&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s},...Object.entries(B).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)=>Zt.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)=>Zt.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)=>Zt.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)=>Zt.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"}),f=t(u),h=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(f),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(f,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:A,logicalId:f,policyLogicalId:h}}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 Do.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:f="Average",treatMissingData:h="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:f,TreatMissingData:h}},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 q{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:f,emailConfiguration:h,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:f,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(h)I.Properties.EmailConfiguration={EmailSendingAccount:h.emailSendingAccount,From:h.from,ReplyToEmailAddress:h.replyToEmailAddress,SourceArn:h.sourceArn,ConfigurationSet:h.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:f,idTokenValidity:h,tokenValidityUnits:S,readAttributes:A,writeAttributes:v,explicitAuthFlows:C,preventUserExistenceErrors:P,enableTokenRevocation:E,callbackURLs:I,logoutURLs:D,allowedOAuthFlows:x,allowedOAuthScopes:M,allowedOAuthFlowsUserPoolClient:w,supportedIdentityProviders:O}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),_=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:f,IdTokenValidity:h,TokenValidityUnits:S,ReadAttributes:A,WriteAttributes:v,ExplicitAuthFlows:C,PreventUserExistenceErrors:P,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:D,AllowedOAuthFlows:x,AllowedOAuthScopes:M,AllowedOAuthFlowsUserPoolClient:w,SupportedIdentityProviders:O}},logicalId:_}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),f=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(n),CustomDomainConfig:l}},logicalId:f}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:f,openIdConnectProviderARNs:h}=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:f,OpenIdConnectProviderARNs:h}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,f=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),h=t(f),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(n),Roles:S,RoleMappings:u}},logicalId:h}}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}=q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=q.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...q.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...q.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=q.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...q.AuthFlows.standard]}),{identityPool:u,logicalId:f}=q.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(o,"ProviderName")}]}),{role:h,logicalId:S}=q.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:f}),{attachment:A,logicalId:v}=q.createIdentityPoolRoleAttachment(f,{slug:n,environment:i,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:f,authRole:h,authRoleId:S,attachment:A,attachmentId:v}}}}import{createHash as Tr}from"node:crypto";import{copyFileSync as Rr,existsSync as Rt,readdirSync as Pr,readFileSync as tt,statSync as Er,writeFileSync as nt}from"node:fs";import{basename as Ir,dirname as pn,extname as gn,join as Ve}from"node:path";class j{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:f,deploymentConfigName:h,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:f?.map((D)=>({Key:D.key,Value:D.value,Type:D.type})),DeploymentConfigName:h,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"}),f=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:f}}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}=j.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:f}=j.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:j.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:f}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=j.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:f,logicalId:h}=j.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:j.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:A}=j.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:N.Ref(h),autoRollbackConfiguration:j.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:f,configId:h,deploymentGroup:S,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=j.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:f}=j.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:j.BlueGreenConfigs.standard(),autoRollbackConfiguration:j.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:f}}};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 Tr(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=Ir(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=Pr(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),f=[],h={};for(let A of u){let v=A.replace(i,"").replace(/^[/\\]/,""),C=k.shouldHashFile(v,o),P=Er(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(f.push(D),h[v]=I,s){let x=Ve(s,I),M=pn(x);if(!Rt(M)){let{mkdirSync:w}=Xe("node:fs");w(M,{recursive:!0})}if(C||l)Rr(A,x)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:f,hashMap:h};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 f=o[l];if(!f||f!==u){if(s.push(`/${l}`),f&&f!==u)s.push(`/${f}`)}}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[f,h]of Object.entries(s.hashMap)){if(f===h)continue;let S=[new RegExp(`(src|href)=["']${o}/?${k.escapeRegExp(f)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(f)}["']?\\)`,"g")];for(let A of S)u=u.replace(A,(v)=>v.replace(f,h))}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[f,h]of Object.entries(s.hashMap)){if(f===h)continue;let S=new RegExp(`url\\(["']?${o}/?${k.escapeRegExp(f)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${h})`)}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 f=u.hash!=="",h=u.contentType==="text/html",S=c.unhashed||"public, max-age=3600";if(h)S=c.html||"public, max-age=0, must-revalidate";else if(f)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 Ui{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:f}=n,h=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(h),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:h,Description:c,SecretString:l,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},...f?Object.entries(f).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:f,excludePunctuation:h,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:f,ExcludePunctuation:h,ExcludeUppercase:S,PasswordLength:A||32,RequireEachIncludedType:v!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...P?Object.entries(P).map(([x,M])=>({Key:x,Value:M})):[]]}};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:f,port:h,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(f)C.host=f;if(h)C.port=h;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"}),f=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:f}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:f,vpcSecurityGroupIds:h,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:f,VpcSecurityGroupIds:h,VpcSubnetIds:S};return{rotation:C,logicalId:v}}static SecretTypes={apiKey:(n,i,s)=>Ui.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)=>Ui.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)=>Ui.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Ui.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:f="Standard",tags:h}=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:f,Tags:{Name:S,Environment:s,...h}}},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"),f=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),h=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:f,host:h,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 Zt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:f=10,volumeType:h="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:M,autoSnapshotHour:w=0,autoTune:O=!0,tags:B={}}=n,_=o||r({slug:i,environment:s,resourceType:"search"}),Z=t(_);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:_,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:h,VolumeSize:f},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}},...M&&{AdvancedSecurityOptions:{Enabled:M.enabled,InternalUserDatabaseEnabled:M.internalUserDatabase??!0,...M.masterUserName&&M.masterUserPassword&&{MasterUserOptions:{MasterUserName:M.masterUserName,MasterUserPassword:M.masterUserPassword}},...M.masterUserArn&&{MasterUserOptions:{MasterUserARN:M.masterUserArn}}}},...O&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s},...Object.entries(B).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)=>Zt.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)=>Zt.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)=>Zt.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)=>Zt.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"}),f=t(u),h=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(f),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(f,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:A,logicalId:f,policyLogicalId:h}}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) {
2282
2282
  const request = event.request;
2283
2283
  const uri = request.uri;
2284
2284
  const querystring = request.querystring;
@@ -2456,18 +2456,18 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2456
2456
  # Configure application server (PM2, Nginx, Apache)
2457
2457
  # Mount EFS for shared file storage
2458
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:f==="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:h==="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:f==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...h==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function FI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:f=s.replace(/-/g,"_"),databasePassword:h,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:f,username:f,password:h}},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 UI(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:f=1024,build:h,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:f,build:h,deploy:S,assets:"public",queues:!0,scheduler:v,cache:{driver:A},domain:o}}}}}function QI(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 MA=Od,FA="./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 UA=20000,QA=12000;function HA(n){return UA+si(n)%QA}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((f)=>typeof f==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function GA(n,i,s){if(s)return s;let o=Nn(n,i),c=o[0];if(!c)return null;return Dn(c,o)}function VA(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 er(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return Zr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var am="dashboard-";function cm(n){return am+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function Zr(n){return n==="dashboard"||n.startsWith(am)}function Qi(n,i,s){if(er(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=GA(n,i,s.domain);if(!u)return[];let f=s.port??HA(u),h=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,S={root:s.uiRoot,deploy:"server",domain:u,preStart:["bun install --production --no-save"],start:`bun ${FA} --box --host 127.0.0.1 --port ${f}`,port:f,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...h?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:h.password}:{}},zeroDowntime:!1,sharedPaths:[MA],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:cm(u),site:S}]}return VA(n,i,s.domain).map((u)=>({name:cm(u),site:{root:s.uiRoot,deploy:"server",type:"static",domain:u,ssl:{provider:"letsencrypt"},...c,...o}}))}function HI(n,i,s){return Qi(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 dm(n,i){return wt(n,i)}function GI(...n){return n.reduce((i,s)=>wt(i,s),{})}function VI(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return dm(o,i(o,s));return dm(o,i)}}function en(n){return{infrastructure:n}}function qI(n){return en({monitoring:n})}function jI(n){return en({security:n})}function zI(n){return en({databases:n})}function KI(n){return en({cache:n})}function WI(n){return en({cdn:n})}function JI(n){return en({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 qA(){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 jA(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 f of s){let h=f.trim();if(!h||h.startsWith("#")||h.startsWith(";"))continue;let S=h.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]=h.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 zA(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(),f=await He(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!f.ok)return null;let h=await f.json();return{accessKeyId:h.AccessKeyId,secretAccessKey:h.SecretAccessKey,sessionToken:h.Token,expiration:new Date(h.Expiration)}}catch{return null}}async function KA(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 f=await He(c,{headers:l},i);if(!f.ok)return null;let h=await f.json();return{accessKeyId:h.AccessKeyId,secretAccessKey:h.SecretAccessKey,sessionToken:h.Token,expiration:new Date(h.Expiration)}}catch{return null}}async function WA(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",f=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,h=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),S=await He(`${f}/?${h.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 Hi(n){let i=qA();if(i)return i;let s=jA(n);if(s)return s;let o=await WA(n);if(o)return o;let c=await KA(n);if(c)return c;let l=await zA(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 XI(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=Hi(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 Do(n){return Hi({profile:n})}function JA(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
- `),f=!1;for(let h of u){let S=h.trim();if(S.startsWith("[")){f=S===l;continue}if(f&&S.startsWith("region")){let[,A]=S.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function lm(n){let i=n||await Hi(),s=JA(),{signRequest:o}=await import("./chunk-bvzmbksp.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}),f=await fetch(u.url,{method:u.method,headers:u.headers,body:u.body});if(!f.ok)throw Error(`Failed to get account ID: ${await f.text()}`);let h=await f.text(),S=Ue(h,"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 Hi(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 f=R({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),h=await fetch(f.url,{method:f.method,headers:f.headers});if(!h.ok&&h.status!==304){let S=await h.text();throw new F(`Failed to get object: ${S}`,h.status,n,i)}return h}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),f={"Content-Length":String(o),"Content-Type":c.contentType||Ln(i)};if(c.contentEncoding)f["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)f["Cache-Control"]=c.cacheControl;if(c.contentDisposition)f["Content-Disposition"]=c.contentDisposition;if(c.storageClass)f["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)f["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)f["x-amz-acl"]=c.acl;if(c.tagging)f["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,P]of Object.entries(c.metadata))f[`x-amz-meta-${C.toLowerCase()}`]=P;let h;if(typeof s==="string")h=s;else if(s instanceof Blob)h=await s.text();else h=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=R({method:"PUT",url:u,headers:f,body:h,...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 F(`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 F(`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}),f=await fetch(u.url,{method:u.method,headers:u.headers,body:l});if(!f.ok){let E=await f.text();throw new F(`Failed to delete objects: ${E}`,f.status,n)}let h=await f.text(),S=[],A=[],v=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=v.exec(h))!==null)S.push(C[1]);let P=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=P.exec(h))!==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 f=await l.text();throw new F(`Failed to list objects: ${f}`,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 f=await l.text();throw new F(`Failed to head object: ${f}`,l.status,n,i)}let u={};return l.headers.forEach((f,h)=>{if(h.toLowerCase().startsWith("x-amz-meta-"))u[h.slice(11)]=f}),{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),f={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)f["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)f["Content-Type"]=c.contentType;if(c.storageClass)f["x-amz-storage-class"]=c.storageClass;if(c.acl)f["x-amz-acl"]=c.acl;if(c.metadata)for(let[P,E]of Object.entries(c.metadata))f[`x-amz-meta-${P.toLowerCase()}`]=E;let h=R({method:"PUT",url:u,headers:f,...l,service:"s3",region:this.region}),S=await fetch(h.url,{method:h.method,headers:h.headers});if(!S.ok){let P=await S.text();throw new F(`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 Mo({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,f;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),f=s.size;else{let A=new Blob([s]);u=A.stream(),f=A.size}let{uploadId:h,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,S,h,u,l,c,f,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,h,A)}catch(A){throw await this.abortMultipartUpload(n,i,h,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 f=R({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),h=await fetch(f.url,{method:f.method,headers:f.headers});if(!h.ok){let C=await h.text();throw new F(`Failed to initiate multipart upload: ${C}`,h.status,n,i)}let A=(await h.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new F("Failed to parse upload ID from response",0,n,i);let v=c;if(h.url)try{let C=new URL(h.url);C.search="",v=C.toString()}catch{}return{uploadId:A[1],baseUrl:v}}async uploadParts(n,i,s,o,c,l,u,f,h,S){let A=[],v=c.getReader(),C=1,P=new Uint8Array(0),E=0,I=f?Math.ceil(f/l):void 0,D=new Map,x=async(w,O)=>{let B=`${s}?partNumber=${O}&uploadId=${encodeURIComponent(o)}`,_={"Content-Length":String(w.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=R({method:"PUT",url:B,headers:_,...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 F(`Failed to upload part ${O}: ${X}`,J.status,n,i)}let Y=(J.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new F(`Missing ETag for part ${O}`,J.status,n,i);return{partNumber:O,etag:Y}},M=async()=>{let w=await Promise.race(D.values());D.delete(w.partNumber),A.push(w)};while(!0){let{done:w,value:O}=await v.read();if(O){let B=new Uint8Array(P.length+O.length);B.set(P),B.set(O,P.length),P=B}while(P.length>=l||w&&P.length>0){let B=P.slice(0,l);P=P.slice(l);let _=C++;if(D.size>=h)await M();if(D.set(_,x(B,_)),E+=B.byteLength,S)S({loaded:E,total:f||E,part:_,totalParts:I||_})}if(w)break}while(D.size>0)await M();return A.sort((w,O)=>w.partNumber-O.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?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:h,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:h});if(!A.ok){let E=await A.text();throw new F(`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 F 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 XA(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+=`
2459
+ `),o=null,c,l,u;for(let f of s){let h=f.trim();if(!h||h.startsWith("#")||h.startsWith(";"))continue;let S=h.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]=h.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 zA(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(),f=await He(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!f.ok)return null;let h=await f.json();return{accessKeyId:h.AccessKeyId,secretAccessKey:h.SecretAccessKey,sessionToken:h.Token,expiration:new Date(h.Expiration)}}catch{return null}}async function KA(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 f=await He(c,{headers:l},i);if(!f.ok)return null;let h=await f.json();return{accessKeyId:h.AccessKeyId,secretAccessKey:h.SecretAccessKey,sessionToken:h.Token,expiration:new Date(h.Expiration)}}catch{return null}}async function WA(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",f=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,h=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),S=await He(`${f}/?${h.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 Hi(n){let i=qA();if(i)return i;let s=jA(n);if(s)return s;let o=await WA(n);if(o)return o;let c=await KA(n);if(c)return c;let l=await zA(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 XI(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=Hi(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 Po(n){return Hi({profile:n})}function JA(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
+ `),f=!1;for(let h of u){let S=h.trim();if(S.startsWith("[")){f=S===l;continue}if(f&&S.startsWith("region")){let[,A]=S.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function lm(n){let i=n||await Hi(),s=JA(),{signRequest:o}=await import("./chunk-25sw2s70.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}),f=await fetch(u.url,{method:u.method,headers:u.headers,body:u.body});if(!f.ok)throw Error(`Failed to get account ID: ${await f.text()}`);let h=await f.text(),S=Ue(h,"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 Hi(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 f=R({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),h=await fetch(f.url,{method:f.method,headers:f.headers});if(!h.ok&&h.status!==304){let S=await h.text();throw new F(`Failed to get object: ${S}`,h.status,n,i)}return h}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),f={"Content-Length":String(o),"Content-Type":c.contentType||Ln(i)};if(c.contentEncoding)f["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)f["Cache-Control"]=c.cacheControl;if(c.contentDisposition)f["Content-Disposition"]=c.contentDisposition;if(c.storageClass)f["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)f["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)f["x-amz-acl"]=c.acl;if(c.tagging)f["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,P]of Object.entries(c.metadata))f[`x-amz-meta-${C.toLowerCase()}`]=P;let h;if(typeof s==="string")h=s;else if(s instanceof Blob)h=await s.text();else h=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=R({method:"PUT",url:u,headers:f,body:h,...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 F(`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 F(`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}),f=await fetch(u.url,{method:u.method,headers:u.headers,body:l});if(!f.ok){let E=await f.text();throw new F(`Failed to delete objects: ${E}`,f.status,n)}let h=await f.text(),S=[],A=[],v=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=v.exec(h))!==null)S.push(C[1]);let P=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=P.exec(h))!==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 f=await l.text();throw new F(`Failed to list objects: ${f}`,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 f=await l.text();throw new F(`Failed to head object: ${f}`,l.status,n,i)}let u={};return l.headers.forEach((f,h)=>{if(h.toLowerCase().startsWith("x-amz-meta-"))u[h.slice(11)]=f}),{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),f={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)f["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)f["Content-Type"]=c.contentType;if(c.storageClass)f["x-amz-storage-class"]=c.storageClass;if(c.acl)f["x-amz-acl"]=c.acl;if(c.metadata)for(let[P,E]of Object.entries(c.metadata))f[`x-amz-meta-${P.toLowerCase()}`]=E;let h=R({method:"PUT",url:u,headers:f,...l,service:"s3",region:this.region}),S=await fetch(h.url,{method:h.method,headers:h.headers});if(!S.ok){let P=await S.text();throw new F(`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 Fo({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,f;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),f=s.size;else{let A=new Blob([s]);u=A.stream(),f=A.size}let{uploadId:h,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,S,h,u,l,c,f,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,h,A)}catch(A){throw await this.abortMultipartUpload(n,i,h,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 f=R({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),h=await fetch(f.url,{method:f.method,headers:f.headers});if(!h.ok){let C=await h.text();throw new F(`Failed to initiate multipart upload: ${C}`,h.status,n,i)}let A=(await h.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new F("Failed to parse upload ID from response",0,n,i);let v=c;if(h.url)try{let C=new URL(h.url);C.search="",v=C.toString()}catch{}return{uploadId:A[1],baseUrl:v}}async uploadParts(n,i,s,o,c,l,u,f,h,S){let A=[],v=c.getReader(),C=1,P=new Uint8Array(0),E=0,I=f?Math.ceil(f/l):void 0,D=new Map,x=async(w,O)=>{let B=`${s}?partNumber=${O}&uploadId=${encodeURIComponent(o)}`,_={"Content-Length":String(w.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=R({method:"PUT",url:B,headers:_,...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 F(`Failed to upload part ${O}: ${X}`,J.status,n,i)}let Y=(J.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new F(`Missing ETag for part ${O}`,J.status,n,i);return{partNumber:O,etag:Y}},M=async()=>{let w=await Promise.race(D.values());D.delete(w.partNumber),A.push(w)};while(!0){let{done:w,value:O}=await v.read();if(O){let B=new Uint8Array(P.length+O.length);B.set(P),B.set(O,P.length),P=B}while(P.length>=l||w&&P.length>0){let B=P.slice(0,l);P=P.slice(l);let _=C++;if(D.size>=h)await M();if(D.set(_,x(B,_)),E+=B.byteLength,S)S({loaded:E,total:f||E,part:_,totalParts:I||_})}if(w)break}while(D.size>0)await M();return A.sort((w,O)=>w.partNumber-O.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?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:h,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:h});if(!A.ok){let E=await A.text();throw new F(`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 F 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 XA(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+=`
2461
2461
 
2462
2462
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){n+=`
2463
2463
 
2464
2464
  Details:`;for(let[i,s]of Object.entries(this.details))n+=`
2465
- ${i}: ${JSON.stringify(s)}`}return n}}class Po 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 YA extends We{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class um extends We{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class ZA extends We{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var ey={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2465
+ ${i}: ${JSON.stringify(s)}`}return n}}class No 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 YA extends We{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class um extends We{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class ZA extends We{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var ey={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2466
2466
  1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
2467
2467
  2. Create ~/.aws/credentials file with your credentials
2468
2468
  3. Use an IAM role (for EC2 instances)
2469
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 ty(n){return ey[n]}function gm(n,i){let s=ty(n);return new We(s.message,n,s.solution,i)}class U{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 YI(n){if(!n)throw gm("MISSING_CONFIG");if(!n.project)throw new Po("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new Po("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new Po("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 um("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 gm("INVALID_REGION",{region:n.project.region})}U.success("Configuration validation passed")}function ZI(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 eb(n="default"){try{U.verbose("Resolving AWS credentials...");let i=await Do(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");U.verbose("Credentials resolved successfully"),U.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),U.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await lm(i),U.verbose("Credentials are valid"),U.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 tb(n,i){return{allowed:i,denied:[]}}function ry(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function rb(n){let i=ry(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var K={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 nb(n){let i=[];if(U.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:K.ec2["Running On-Demand Instances"],percentage:o/K.ec2["Running On-Demand Instances"]*100,warning:o>K.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:K.ec2.VPCs,percentage:1/K.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:K.rds["DB Instances"],percentage:1/K.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:K.s3.Buckets,percentage:o/K.s3.Buckets*100,warning:o>K.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:K.dynamodb.Tables,percentage:o/K.dynamodb.Tables*100,warning:o>K.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){U.warn("Service quota warnings detected:");for(let o of s)U.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else U.verbose("All service quotas are within limits");return i}function ib(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2470
+ Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function YI(n){if(!n)throw gm("MISSING_CONFIG");if(!n.project)throw new No("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new No("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new No("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 um("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 gm("INVALID_REGION",{region:n.project.region})}U.success("Configuration validation passed")}function ZI(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 eb(n="default"){try{U.verbose("Resolving AWS credentials...");let i=await Po(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");U.verbose("Credentials resolved successfully"),U.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),U.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await lm(i),U.verbose("Credentials are valid"),U.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 tb(n,i){return{allowed:i,denied:[]}}function ry(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function rb(n){let i=ry(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var K={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 nb(n){let i=[];if(U.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:K.ec2["Running On-Demand Instances"],percentage:o/K.ec2["Running On-Demand Instances"]*100,warning:o>K.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:K.ec2.VPCs,percentage:1/K.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:K.rds["DB Instances"],percentage:1/K.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:K.s3.Buckets,percentage:o/K.s3.Buckets*100,warning:o>K.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:K.dynamodb.Tables,percentage:o/K.dynamodb.Tables*100,warning:o>K.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){U.warn("Service quota warnings detected:");for(let o of s)U.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else U.verbose("All service quotas are within limits");return i}function ib(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2471
2471
 
2472
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}:
2473
2473
  `;for(let l of c){let u=l.warning?"⚠":"✓";i+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
@@ -7236,9 +7236,9 @@ const __handlers = createHandlers(__app)
7236
7236
  export const http = __handlers.http
7237
7237
  export const queue = __handlers.queue
7238
7238
  export const cli = __handlers.cli
7239
- `}import{execSync as Li}from"node:child_process";import{createHash as Oi}from"node:crypto";import{cpSync as $i,mkdtempSync as Bi,rmSync as _i,writeFileSync as Wi}from"node:fs";import{tmpdir as Ki}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 Uy(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Li(o,{stdio:"inherit",cwd:i})}function No(n){return Oi("sha256").update(n).digest("hex")}function Al(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function tn(n){let i=Yi(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)Uy(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=Bi(Me(Ki(),"tscloud-pkg-"));try{for(let C of Xi)$i(Me(es(),C),Me(l,C));let u=Me(l,"bootstrap.ts");Wi(u,nf({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let f=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!f.success){let C=f.logs.map((P)=>String(P)).join(`
7239
+ `}import{execSync as Li}from"node:child_process";import{createHash as Oi}from"node:crypto";import{cpSync as $i,mkdtempSync as Bi,rmSync as _i,writeFileSync as Wi}from"node:fs";import{tmpdir as Ki}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 Uy(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Li(o,{stdio:"inherit",cwd:i})}function ko(n){return Oi("sha256").update(n).digest("hex")}function Al(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function tn(n){let i=Yi(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)Uy(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=Bi(Me(Ki(),"tscloud-pkg-"));try{for(let C of Xi)$i(Me(es(),C),Me(l,C));let u=Me(l,"bootstrap.ts");Wi(u,nf({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let f=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!f.success){let C=f.logs.map((P)=>String(P)).join(`
7240
7240
  `);throw Error(`serverless app bundle failed:
7241
- ${C}`)}let h=f.outputs[0],S=Buffer.from(await h.arrayBuffer()),A="index",v=Je([{name:`${A}.mjs`,data:S}]);return{zip:v,bundle:S,sha256:No(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{_i(l,{recursive:!0,force:!0})}}var Qy=["18","20","22"];function ts(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function qi(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"&&Qy.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 nr(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 yl(n,i,s){return nr(n,i,s).map((o)=>o.name)}function Sl(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=qi(i).lambdaRuntime,u=i.architecture??"x86_64",f=n.config.project.region,h={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=nr(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=Fi(c,s),M=i.tmpStorage??512,w={},O={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${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)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let _=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)_.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)_.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");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:_,Policies:B}};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,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((W,ee)=>`EfsMountTarget${ee}`):[],pt=J?{FileSystemConfigs:[{Arn:Oe,LocalMountPath:X}]}:{};if(J)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function me(W,ee,se,te,de,gt,Be,Ee=M){w[`${W}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[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(te)},EphemeralStorage:{Size:Ee},...an,...Be!==void 0?{ReservedConcurrentExecutions:Be}:{},...dt,...pt}}}if(me("HttpFunction",h.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,M),me("CliFunction",h.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??M),v)me("QueueFunction",h.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??M);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,pe=["HttpFunction","CliFunction",...v?["QueueFunction"]:[]];if(ue)for(let W of pe)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 Re=(W)=>ue?e.ref(`${W}Alias`):e.getAtt(W,"Arn"),ge=(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: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:ge("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},O.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},O.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let 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 W=i.certificateArn;if(!W)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}))}},W=e.ref("HttpCertificate");Se.forEach((ee,se)=>{let te=`HttpDomain${se}`;if(w[te]={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(te),Stage:"$default"}},i.hostedZoneId)w[`HttpDomainRecord${se}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ee,Type:"A",AliasTarget:{DNSName:e.getAtt(te,"RegionalDomainName"),HostedZoneId:e.getAtt(te,"RegionalHostedZoneId")}}};O[`CustomDomain${se}`]={Description:`Custom domain ${ee}`,Value:ee},O[`CustomDomainTarget${se}`]={Description:`Point ${ee} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(te,"RegionalDomainName")}})}if(v)w.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((W,ee)=>{let se=`AppQueue${ee}`,te=i.queueTimeout??120;w[se]={Type:"AWS::SQS::Queue",Properties:{QueueName:W.name,VisibilityTimeout:Math.min(43200,te*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:ge("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...de?{ScalingConfig:{MaximumConcurrency:Math.max(2,de)}}:{}}},O[`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:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},w.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ge("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((te)=>te!=="queue"||v);for(let te of se){let de=te.charAt(0).toUpperCase()+te.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-${te}-${Ee}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Fe},(an,sr)=>({Id:`warm-${te}-${Ee}-${sr}`,Arn:e.getAtt(ee[te],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Be+=Fe}w[`Warmer${de}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ee[te]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${te}-*`)}}}}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}}},O.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(f!=="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 ${f}. 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"}}};O.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}")}}}]}}},O.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},O.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let 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 te of i.firewall.rules??[]){let de=se[te];if(!de)continue;W.push({Name:`managed-${te}`,Priority:ee++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:de}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${te}`}})}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`}}},O.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(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((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"}}}},O.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}},O.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")}},O.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")]}},O.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(O.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},O.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},v)O.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:O},$e={};for(let W of Object.values(w))$e[W.Type]=($e[W.Type]??0)+1;return{template:xe,functionNames:h,queueNames:A,resourceSummary:$e}}var Hy=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function Gy(n){let i=`php${n.replace(".","")}`;return Hy.map((s)=>`${i}-php-${s}`)}function Il(n,i){let s=`php${n.replace(".","")}`,o=Gy(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 h=f.outputs[0],S=Buffer.from(await h.arrayBuffer()),A="index",v=Je([{name:`${A}.mjs`,data:S}]);return{zip:v,bundle:S,sha256:ko(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{_i(l,{recursive:!0,force:!0})}}var Qy=["18","20","22"];function ts(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function qi(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"&&Qy.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 nr(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 yl(n,i,s){return nr(n,i,s).map((o)=>o.name)}function Sl(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=qi(i).lambdaRuntime,u=i.architecture??"x86_64",f=n.config.project.region,h={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=nr(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=Fi(c,s),M=i.tmpStorage??512,w={},O={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${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)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let _=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)_.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)_.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");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:_,Policies:B}};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,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((W,ee)=>`EfsMountTarget${ee}`):[],pt=J?{FileSystemConfigs:[{Arn:Oe,LocalMountPath:X}]}:{};if(J)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function me(W,ee,se,te,de,gt,Be,Ee=M){w[`${W}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[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(te)},EphemeralStorage:{Size:Ee},...an,...Be!==void 0?{ReservedConcurrentExecutions:Be}:{},...dt,...pt}}}if(me("HttpFunction",h.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,M),me("CliFunction",h.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??M),v)me("QueueFunction",h.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??M);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,pe=["HttpFunction","CliFunction",...v?["QueueFunction"]:[]];if(ue)for(let W of pe)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 Re=(W)=>ue?e.ref(`${W}Alias`):e.getAtt(W,"Arn"),ge=(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: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:ge("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},O.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},O.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let 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 W=i.certificateArn;if(!W)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}))}},W=e.ref("HttpCertificate");Se.forEach((ee,se)=>{let te=`HttpDomain${se}`;if(w[te]={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(te),Stage:"$default"}},i.hostedZoneId)w[`HttpDomainRecord${se}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ee,Type:"A",AliasTarget:{DNSName:e.getAtt(te,"RegionalDomainName"),HostedZoneId:e.getAtt(te,"RegionalHostedZoneId")}}};O[`CustomDomain${se}`]={Description:`Custom domain ${ee}`,Value:ee},O[`CustomDomainTarget${se}`]={Description:`Point ${ee} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(te,"RegionalDomainName")}})}if(v)w.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((W,ee)=>{let se=`AppQueue${ee}`,te=i.queueTimeout??120;w[se]={Type:"AWS::SQS::Queue",Properties:{QueueName:W.name,VisibilityTimeout:Math.min(43200,te*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:ge("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...de?{ScalingConfig:{MaximumConcurrency:Math.max(2,de)}}:{}}},O[`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:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},w.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ge("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((te)=>te!=="queue"||v);for(let te of se){let de=te.charAt(0).toUpperCase()+te.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-${te}-${Ee}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Fe},(an,sr)=>({Id:`warm-${te}-${Ee}-${sr}`,Arn:e.getAtt(ee[te],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Be+=Fe}w[`Warmer${de}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ee[te]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${te}-*`)}}}}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}}},O.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(f!=="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 ${f}. 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"}}};O.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}")}}}]}}},O.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},O.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let 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 te of i.firewall.rules??[]){let de=se[te];if(!de)continue;W.push({Name:`managed-${te}`,Priority:ee++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:de}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${te}`}})}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`}}},O.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(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((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"}}}},O.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}},O.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")}},O.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")]}},O.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(O.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},O.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},v)O.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:O},$e={};for(let W of Object.values(w))$e[W.Type]=($e[W.Type]??0)+1;return{template:xe,functionNames:h,queueNames:A,resourceSummary:$e}}var Hy=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function Gy(n){let i=`php${n.replace(".","")}`;return Hy.map((s)=>`${i}-php-${s}`)}function Il(n,i){let s=`php${n.replace(".","")}`,o=Gy(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7242
7242
 
7243
7243
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7244
7244
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7299,7 +7299,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7299
7299
 
7300
7300
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7301
7301
  CMD [ "index.http" ]
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 of(){return ct(ve(Hn(),"runtime.mjs"),"utf-8")}function jn(n){return ct(ve(Hn(),`${n}-bootstrap`),"utf-8")}function nE(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),f=`node-v${u}-linux-${s}`,h=`https://nodejs.org/dist/v${u}/${f}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=ve(l,"node.tar.xz");Kn(h,S),c("extracting node binary"),ot("tar",["-xf",S,"-C",l,`${f}/bin/node`],{stdio:"inherit"});let A=ct(ve(l,f,"bin","node"));c("packaging layer");let v=[{name:"bootstrap",data:jn("node"),mode:493},{name:"runtime.mjs",data:of(),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 iE(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 f=ve(l,"bun.zip");Kn(u,f),c("extracting bun binary"),ot("unzip",["-o","-q",f,"-d",l],{stdio:"inherit"});let h=ct(ve(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:jn("bun"),mode:493},{name:"runtime.mjs",data:of(),mode:420},{name:"bin/bun",data:h,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 ko="x-ts-cloud-invoke-depth",Bo="x-ts-cloud-invoke-chain",xo="x-ts-cloud-trace-id";function Cl(n){return ss("sha256").update(n).digest("hex").slice(0,8)}var rn={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function zt(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 El(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function vl(n,i=rn){let s=Cl(n.functionId),o=El(zt(n.headers,Bo)),c=n.traceId??zt(n.headers,xo)??crypto.randomUUID(),l=[...o,s],u=o.filter((v)=>v===s).length,f=o[o.length-1]===s,h=Number.parseInt(zt(n.headers,ko)??"",10),S=Math.max(l.length,Number.isFinite(h)?h+1:0),A="ok";if(S>i.maxDepth)A="depth_exceeded";else if(u>=i.maxRepeats)A="cycle_detected";else if(f&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:S,chain:l,traceId:c,selfInvocation:f,repeats:u,propagate:{[ko]:String(S),[Bo]:l.join("."),[xo]: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 ji{limits;clock;traces=new Map;breakers=new Map;constructor(n=rn,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=vl(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let 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 Oo(n){return{...n.propagate}}function _o(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 af=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 Vy(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:{...rn,...i.limits},functionId:i.functionId??os()}}var we,be;function qy(){let n=globalThis.fetch;if(!n||we===n)return()=>{};be=n;let i=async(s,o)=>{let c=af.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,f]of Object.entries(Oo(c)))l.set(u,f);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,Qt;function jy(n){if(!lt||JSON.stringify(Qt)!==JSON.stringify(n))lt=new ji(n),Qt=n;return lt}function sE(){if(lt=void 0,Qt=void 0,we&&be&&globalThis.fetch===we)globalThis.fetch=be;we=void 0,be=void 0}function cf(n,i){let s=Vy(i);if(!s.enabled)return;let o=jy(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 df(n,i){return qy(),af.run(n,i)}function oE(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 zy(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[f,h]of Object.entries(n.headers??{}))if(h!==void 0)c.set(f,h);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 lf(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,f)=>{if(f.toLowerCase()==="set-cookie")return;i[f]=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 Ky(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((f)=>f.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=cf(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=_o(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=zy(s);if(!c){let u=await n(l);return lf(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 df(c.verdict,async()=>lf(await n(l)))}}function ds(n){try{return JSON.parse(n)}catch{return n}}function Wy(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 Jy(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 aE(n,i){return{http:Ky(n.fetch,i),queue:Wy(n.queue),cli:Jy(n.cli)}}function uf(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 of(){return ct(ve(Hn(),"runtime.mjs"),"utf-8")}function jn(n){return ct(ve(Hn(),`${n}-bootstrap`),"utf-8")}function nE(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),f=`node-v${u}-linux-${s}`,h=`https://nodejs.org/dist/v${u}/${f}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=ve(l,"node.tar.xz");Kn(h,S),c("extracting node binary"),ot("tar",["-xf",S,"-C",l,`${f}/bin/node`],{stdio:"inherit"});let A=ct(ve(l,f,"bin","node"));c("packaging layer");let v=[{name:"bootstrap",data:jn("node"),mode:493},{name:"runtime.mjs",data:of(),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 iE(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 f=ve(l,"bun.zip");Kn(u,f),c("extracting bun binary"),ot("unzip",["-o","-q",f,"-d",l],{stdio:"inherit"});let h=ct(ve(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:jn("bun"),mode:493},{name:"runtime.mjs",data:of(),mode:420},{name:"bin/bun",data:h,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 Bo="x-ts-cloud-invoke-depth",xo="x-ts-cloud-invoke-chain",Oo="x-ts-cloud-trace-id";function Cl(n){return ss("sha256").update(n).digest("hex").slice(0,8)}var rn={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function zt(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 El(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function vl(n,i=rn){let s=Cl(n.functionId),o=El(zt(n.headers,xo)),c=n.traceId??zt(n.headers,Oo)??crypto.randomUUID(),l=[...o,s],u=o.filter((v)=>v===s).length,f=o[o.length-1]===s,h=Number.parseInt(zt(n.headers,Bo)??"",10),S=Math.max(l.length,Number.isFinite(h)?h+1:0),A="ok";if(S>i.maxDepth)A="depth_exceeded";else if(u>=i.maxRepeats)A="cycle_detected";else if(f&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:S,chain:l,traceId:c,selfInvocation:f,repeats:u,propagate:{[Bo]:String(S),[xo]:l.join("."),[Oo]: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 ji{limits;clock;traces=new Map;breakers=new Map;constructor(n=rn,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=vl(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let 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 _o(n){return{...n.propagate}}function Lo(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 af=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 Vy(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:{...rn,...i.limits},functionId:i.functionId??os()}}var we,be;function qy(){let n=globalThis.fetch;if(!n||we===n)return()=>{};be=n;let i=async(s,o)=>{let c=af.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,f]of Object.entries(_o(c)))l.set(u,f);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,Qt;function jy(n){if(!lt||JSON.stringify(Qt)!==JSON.stringify(n))lt=new ji(n),Qt=n;return lt}function sE(){if(lt=void 0,Qt=void 0,we&&be&&globalThis.fetch===we)globalThis.fetch=be;we=void 0,be=void 0}function cf(n,i){let s=Vy(i);if(!s.enabled)return;let o=jy(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 df(n,i){return qy(),af.run(n,i)}function oE(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 zy(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[f,h]of Object.entries(n.headers??{}))if(h!==void 0)c.set(f,h);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 lf(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,f)=>{if(f.toLowerCase()==="set-cookie")return;i[f]=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 Ky(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((f)=>f.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=cf(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=Lo(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=zy(s);if(!c){let u=await n(l);return lf(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 df(c.verdict,async()=>lf(await n(l)))}}function ds(n){try{return JSON.parse(n)}catch{return n}}function Wy(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 Jy(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 aE(n,i){return{http:Ky(n.fetch,i),queue:Wy(n.queue),cli:Jy(n.cli)}}function uf(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7303
7303
  [global]
7304
7304
  daemonize = no
7305
7305
  error_log = ${n.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7316,4 +7316,4 @@ decorate_workers_output = no
7316
7316
  php_admin_value[error_log] = /dev/stderr
7317
7317
  php_admin_flag[log_errors] = on
7318
7318
  clear_env = no
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 nn(){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:uf(),mode:420}]}function Tl(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 gf=["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 fs,mkdirSync as hs,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 cE(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"),sf(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(),f=Le(c,"opt");hs(f,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,Le(f,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!fs(Le(f,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let h=[];for(let C of Yn(f)){let P=Rs(f,C).replace(/\\/g,"/"),E=Jn(C).mode&73?493:420;h.push({name:P,data:As(C),mode:E})}o("Injecting runtime assets");let S=new Set(nn().map((C)=>C.path)),A=h.filter((C)=>!S.has(C.name));for(let C of nn())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 Jt}from"node:path";var Xy=[".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*ir(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*ir(c,i,s);else yield c}}function Lo(n){if(n.skipBuild)return;let i=Jt(n.projectRoot??process.cwd()),s=n.app.build??gf;for(let o of s)n.onStep?.(`build: ${o}`),Ps(o,{stdio:"inherit",cwd:i})}function $o(n,i=[]){let s=Jt(n),o=[...Xy,Jr(),...i],c=[];for(let l of ir(s,s,o)){let u=Xn(s,l).replace(/\\/g,"/"),f=(Zn(l).mode&73)!==0;c.push({name:u,data:ws(l),mode:f?493:420})}return c}function wl(n){let i=Jt(n.projectRoot??process.cwd());Lo(n),n.onStep?.("packaging application tree");let s=$o(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 pf{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 dE=new pf;class Rl{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 Yy=new Rl;class mf{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 lE=new mf;class ff{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 uE=new ff;class hf{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 gE=new hf;export{lI,uI,Od,jp,_d,Ld,Jr,L,d,$d,zp,Q,Md,g,kA,Mi,Fd,Ud,fe,Qd,BA,r,t,gI,pI,p,mI,fI,hI,yI,SI,Xt,Hd,Fi,xA,II,bI,De,je,Gd,Kp,Wp,CI,Jp,Xp,Yp,Eo,Vd,re,Xr,yt,vo,St,he,OA,qd,To,Zp,em,tm,rm,jd,EI,H,b,_A,LA,nm,a,y,ze,m,im,Ke,G,It,vI,sm,V,zd,Pe,Yt,wo,ne,Kd,ie,$A,Ro,q,j,k,Ui,T,Zt,bt,z,e,Yr,TI,om,Wd,wI,RI,DI,PI,Jd,NI,kI,BI,xI,OI,_I,LI,$I,MI,FI,UI,QI,MA,FA,UA,QA,HA,GA,VA,er,am,cm,Zr,Qi,HI,dm,GI,VI,en,qI,jI,zI,KI,WI,JI,qA,jA,zA,KA,WA,Hi,XI,Do,JA,lm,F,XA,We,Po,Ct,YA,um,ZA,ey,ty,gm,U,YI,ZI,eb,tb,ry,rb,K,nb,ib,sb,Xd,Yd,ny,pm,mm,ob,ab,cb,db,lb,iy,Zd,ub,gb,pb,mb,fb,sy,oy,hb,Ab,yb,Sb,Ib,bb,Cb,ay,Eb,fm,el,vb,Tb,wb,Rb,hm,Am,ym,Db,tl,cy,dy,ly,uy,rl,gy,Pb,Nb,kb,Bb,xb,Ob,_b,py,my,fy,hy,Sm,Lb,$b,Mb,Fb,Ub,Qb,Hb,Gb,Vb,Ay,yy,Sy,Iy,qb,jb,Im,zb,bm,Cm,Em,vm,Kb,Wb,Jb,Xb,Ne,Gi,Yb,Zb,eC,tC,rC,nC,iC,sC,by,oC,aC,Tm,wm,cC,dC,Cy,lC,uC,gC,pC,mC,fC,hC,AC,yC,SC,IC,bC,CC,EC,vC,TC,wC,RC,DC,PC,NC,nl,Ey,il,vy,sl,Ty,ol,wy,al,Ry,tr,Dy,cl,Py,Vi,Ny,dl,ky,ll,By,Rm,kC,Dm,BC,ul,xy,rr,Oy,Pm,xC,gl,_y,Nm,OC,km,_C,Bm,LC,pl,Ly,xm,$C,Om,MC,_m,FC,Lm,UC,ml,$y,fl,My,$m,QC,Mm,HC,Fm,GC,Um,VC,Qm,qC,Hm,jC,hl,Fy,Gm,zC,Vm,KC,qm,WC,jm,JC,zm,XC,Km,YC,Wm,Jm,Xm,Ym,Zm,ZC,ef,eE,tf,tE,rf,rE,Je,nf,Uy,No,Al,tn,Qy,qi,nr,yl,Sl,Hy,Gy,Il,sf,bl,of,nE,iE,ko,Bo,xo,Cl,rn,El,vl,ji,Oo,_o,af,Vy,qy,jy,sE,cf,df,oE,zy,lf,Ky,Wy,Jy,aE,uf,nn,Tl,gf,cE,Xy,Lo,$o,wl,pf,dE,Rl,Yy,mf,lE,ff,uE,hf,gE};
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 nn(){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:uf(),mode:420}]}function Tl(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 gf=["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 fs,mkdirSync as hs,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 cE(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"),sf(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(),f=Le(c,"opt");hs(f,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,Le(f,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!fs(Le(f,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let h=[];for(let C of Yn(f)){let P=Rs(f,C).replace(/\\/g,"/"),E=Jn(C).mode&73?493:420;h.push({name:P,data:As(C),mode:E})}o("Injecting runtime assets");let S=new Set(nn().map((C)=>C.path)),A=h.filter((C)=>!S.has(C.name));for(let C of nn())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 Jt}from"node:path";var Xy=[".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*ir(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*ir(c,i,s);else yield c}}function $o(n){if(n.skipBuild)return;let i=Jt(n.projectRoot??process.cwd()),s=n.app.build??gf;for(let o of s)n.onStep?.(`build: ${o}`),Ps(o,{stdio:"inherit",cwd:i})}function Mo(n,i=[]){let s=Jt(n),o=[...Xy,Jr(),...i],c=[];for(let l of ir(s,s,o)){let u=Xn(s,l).replace(/\\/g,"/"),f=(Zn(l).mode&73)!==0;c.push({name:u,data:ws(l),mode:f?493:420})}return c}function wl(n){let i=Jt(n.projectRoot??process.cwd());$o(n),n.onStep?.("packaging application tree");let s=Mo(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 pf{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 dE=new pf;class Rl{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 Yy=new Rl;class mf{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 lE=new mf;class ff{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 uE=new ff;class hf{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 gE=new hf;export{lI,uI,Od,jp,_d,Ld,Jr,L,d,$d,zp,Q,Md,g,kA,Mi,Fd,Ud,fe,Qd,BA,r,t,gI,pI,p,mI,fI,hI,yI,SI,Xt,Hd,Fi,xA,II,bI,De,je,Gd,Kp,Wp,CI,Jp,Xp,Yp,vo,Vd,re,Xr,yt,To,St,he,OA,qd,wo,Zp,em,tm,rm,jd,EI,H,b,_A,LA,nm,a,y,ze,m,im,Ke,G,It,vI,sm,V,zd,Pe,Yt,Ro,ne,Kd,ie,$A,Do,q,j,k,Ui,T,Zt,bt,z,e,Yr,TI,om,Wd,wI,RI,DI,PI,Jd,NI,kI,BI,xI,OI,_I,LI,$I,MI,FI,UI,QI,MA,FA,UA,QA,HA,GA,VA,er,am,cm,Zr,Qi,HI,dm,GI,VI,en,qI,jI,zI,KI,WI,JI,qA,jA,zA,KA,WA,Hi,XI,Po,JA,lm,F,XA,We,No,Ct,YA,um,ZA,ey,ty,gm,U,YI,ZI,eb,tb,ry,rb,K,nb,ib,sb,Xd,Yd,ny,pm,mm,ob,ab,cb,db,lb,iy,Zd,ub,gb,pb,mb,fb,sy,oy,hb,Ab,yb,Sb,Ib,bb,Cb,ay,Eb,fm,el,vb,Tb,wb,Rb,hm,Am,ym,Db,tl,cy,dy,ly,uy,rl,gy,Pb,Nb,kb,Bb,xb,Ob,_b,py,my,fy,hy,Sm,Lb,$b,Mb,Fb,Ub,Qb,Hb,Gb,Vb,Ay,yy,Sy,Iy,qb,jb,Im,zb,bm,Cm,Em,vm,Kb,Wb,Jb,Xb,Ne,Gi,Yb,Zb,eC,tC,rC,nC,iC,sC,by,oC,aC,Tm,wm,cC,dC,Cy,lC,uC,gC,pC,mC,fC,hC,AC,yC,SC,IC,bC,CC,EC,vC,TC,wC,RC,DC,PC,NC,nl,Ey,il,vy,sl,Ty,ol,wy,al,Ry,tr,Dy,cl,Py,Vi,Ny,dl,ky,ll,By,Rm,kC,Dm,BC,ul,xy,rr,Oy,Pm,xC,gl,_y,Nm,OC,km,_C,Bm,LC,pl,Ly,xm,$C,Om,MC,_m,FC,Lm,UC,ml,$y,fl,My,$m,QC,Mm,HC,Fm,GC,Um,VC,Qm,qC,Hm,jC,hl,Fy,Gm,zC,Vm,KC,qm,WC,jm,JC,zm,XC,Km,YC,Wm,Jm,Xm,Ym,Zm,ZC,ef,eE,tf,tE,rf,rE,Je,nf,Uy,ko,Al,tn,Qy,qi,nr,yl,Sl,Hy,Gy,Il,sf,bl,of,nE,iE,Bo,xo,Oo,Cl,rn,El,vl,ji,_o,Lo,af,Vy,qy,jy,sE,cf,df,oE,zy,lf,Ky,Wy,Jy,aE,uf,nn,Tl,gf,cE,Xy,$o,Mo,wl,pf,dE,Rl,Yy,mf,lE,ff,uE,hf,gE};