@stacksjs/ts-cloud-core 0.1.1

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 (251) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +321 -0
  3. package/package.json +31 -0
  4. package/src/advanced-features.test.ts +465 -0
  5. package/src/aws/cloudformation.ts +421 -0
  6. package/src/aws/cloudfront.ts +158 -0
  7. package/src/aws/credentials.test.ts +132 -0
  8. package/src/aws/credentials.ts +545 -0
  9. package/src/aws/index.ts +87 -0
  10. package/src/aws/s3.test.ts +188 -0
  11. package/src/aws/s3.ts +1088 -0
  12. package/src/aws/signature.test.ts +670 -0
  13. package/src/aws/signature.ts +1155 -0
  14. package/src/backup/disaster-recovery.test.ts +726 -0
  15. package/src/backup/disaster-recovery.ts +500 -0
  16. package/src/backup/index.ts +34 -0
  17. package/src/backup/manager.test.ts +498 -0
  18. package/src/backup/manager.ts +432 -0
  19. package/src/cicd/circleci.ts +430 -0
  20. package/src/cicd/github-actions.ts +424 -0
  21. package/src/cicd/gitlab-ci.ts +255 -0
  22. package/src/cicd/index.ts +8 -0
  23. package/src/cli/history.ts +396 -0
  24. package/src/cli/index.ts +10 -0
  25. package/src/cli/progress.ts +458 -0
  26. package/src/cli/repl.ts +454 -0
  27. package/src/cli/suggestions.ts +327 -0
  28. package/src/cli/table.test.ts +319 -0
  29. package/src/cli/table.ts +332 -0
  30. package/src/cloudformation/builder.test.ts +327 -0
  31. package/src/cloudformation/builder.ts +378 -0
  32. package/src/cloudformation/builders/api-gateway.ts +449 -0
  33. package/src/cloudformation/builders/cache.ts +334 -0
  34. package/src/cloudformation/builders/cdn.ts +278 -0
  35. package/src/cloudformation/builders/compute.ts +485 -0
  36. package/src/cloudformation/builders/database.ts +392 -0
  37. package/src/cloudformation/builders/functions.ts +343 -0
  38. package/src/cloudformation/builders/messaging.ts +140 -0
  39. package/src/cloudformation/builders/monitoring.ts +300 -0
  40. package/src/cloudformation/builders/network.ts +264 -0
  41. package/src/cloudformation/builders/queue.ts +147 -0
  42. package/src/cloudformation/builders/security.ts +399 -0
  43. package/src/cloudformation/builders/storage.ts +285 -0
  44. package/src/cloudformation/index.ts +30 -0
  45. package/src/cloudformation/types.ts +173 -0
  46. package/src/compliance/aws-config.ts +543 -0
  47. package/src/compliance/cloudtrail.ts +376 -0
  48. package/src/compliance/compliance.test.ts +423 -0
  49. package/src/compliance/guardduty.ts +446 -0
  50. package/src/compliance/index.ts +66 -0
  51. package/src/compliance/security-hub.ts +456 -0
  52. package/src/containers/build-optimization.ts +416 -0
  53. package/src/containers/containers.test.ts +508 -0
  54. package/src/containers/image-scanning.ts +360 -0
  55. package/src/containers/index.ts +9 -0
  56. package/src/containers/registry.ts +293 -0
  57. package/src/containers/service-mesh.ts +520 -0
  58. package/src/database/database.test.ts +762 -0
  59. package/src/database/index.ts +9 -0
  60. package/src/database/migrations.ts +444 -0
  61. package/src/database/performance.ts +528 -0
  62. package/src/database/replicas.ts +534 -0
  63. package/src/database/users.ts +494 -0
  64. package/src/dependency-graph.ts +143 -0
  65. package/src/deployment/ab-testing.ts +582 -0
  66. package/src/deployment/blue-green.ts +452 -0
  67. package/src/deployment/canary.ts +500 -0
  68. package/src/deployment/deployment.test.ts +526 -0
  69. package/src/deployment/index.ts +61 -0
  70. package/src/deployment/progressive.ts +62 -0
  71. package/src/dns/dns.test.ts +641 -0
  72. package/src/dns/dnssec.ts +315 -0
  73. package/src/dns/index.ts +8 -0
  74. package/src/dns/resolver.ts +496 -0
  75. package/src/dns/routing.ts +593 -0
  76. package/src/email/advanced/analytics.ts +445 -0
  77. package/src/email/advanced/index.ts +11 -0
  78. package/src/email/advanced/rules.ts +465 -0
  79. package/src/email/advanced/scheduling.ts +352 -0
  80. package/src/email/advanced/search.ts +412 -0
  81. package/src/email/advanced/shared-mailboxes.ts +404 -0
  82. package/src/email/advanced/templates.ts +455 -0
  83. package/src/email/advanced/threading.ts +281 -0
  84. package/src/email/analytics.ts +467 -0
  85. package/src/email/bounce-handling.ts +425 -0
  86. package/src/email/email.test.ts +431 -0
  87. package/src/email/handlers/__tests__/inbound.test.ts +38 -0
  88. package/src/email/handlers/__tests__/outbound.test.ts +37 -0
  89. package/src/email/handlers/converter.ts +227 -0
  90. package/src/email/handlers/feedback.ts +228 -0
  91. package/src/email/handlers/inbound.ts +169 -0
  92. package/src/email/handlers/outbound.ts +178 -0
  93. package/src/email/index.ts +15 -0
  94. package/src/email/reputation.ts +303 -0
  95. package/src/email/templates.ts +352 -0
  96. package/src/errors/index.test.ts +434 -0
  97. package/src/errors/index.ts +416 -0
  98. package/src/health-checks/index.ts +40 -0
  99. package/src/index.ts +360 -0
  100. package/src/intrinsic-functions.ts +118 -0
  101. package/src/lambda/concurrency.ts +330 -0
  102. package/src/lambda/destinations.ts +345 -0
  103. package/src/lambda/dlq.ts +425 -0
  104. package/src/lambda/index.ts +11 -0
  105. package/src/lambda/lambda.test.ts +840 -0
  106. package/src/lambda/layers.ts +263 -0
  107. package/src/lambda/versions.ts +376 -0
  108. package/src/lambda/vpc.ts +399 -0
  109. package/src/local/config.ts +114 -0
  110. package/src/local/index.ts +6 -0
  111. package/src/local/mock-aws.ts +351 -0
  112. package/src/modules/ai.ts +340 -0
  113. package/src/modules/api.ts +478 -0
  114. package/src/modules/auth.ts +805 -0
  115. package/src/modules/cache.ts +417 -0
  116. package/src/modules/cdn.ts +1062 -0
  117. package/src/modules/communication.ts +1094 -0
  118. package/src/modules/compute.ts +3348 -0
  119. package/src/modules/database.ts +554 -0
  120. package/src/modules/deployment.ts +1079 -0
  121. package/src/modules/dns.ts +337 -0
  122. package/src/modules/email.ts +1538 -0
  123. package/src/modules/filesystem.ts +515 -0
  124. package/src/modules/index.ts +32 -0
  125. package/src/modules/messaging.ts +486 -0
  126. package/src/modules/monitoring.ts +2086 -0
  127. package/src/modules/network.ts +664 -0
  128. package/src/modules/parameter-store.ts +325 -0
  129. package/src/modules/permissions.ts +1081 -0
  130. package/src/modules/phone.ts +494 -0
  131. package/src/modules/queue.ts +1260 -0
  132. package/src/modules/redirects.ts +464 -0
  133. package/src/modules/registry.ts +699 -0
  134. package/src/modules/search.ts +401 -0
  135. package/src/modules/secrets.ts +416 -0
  136. package/src/modules/security.ts +731 -0
  137. package/src/modules/sms.ts +389 -0
  138. package/src/modules/storage.ts +1120 -0
  139. package/src/modules/workflow.ts +680 -0
  140. package/src/multi-account/config.ts +521 -0
  141. package/src/multi-account/index.ts +7 -0
  142. package/src/multi-account/manager.ts +427 -0
  143. package/src/multi-region/cross-region.ts +410 -0
  144. package/src/multi-region/index.ts +8 -0
  145. package/src/multi-region/manager.ts +483 -0
  146. package/src/multi-region/regions.ts +435 -0
  147. package/src/network-security/index.ts +48 -0
  148. package/src/observability/index.ts +9 -0
  149. package/src/observability/logs.ts +522 -0
  150. package/src/observability/metrics.ts +460 -0
  151. package/src/observability/observability.test.ts +782 -0
  152. package/src/observability/synthetics.ts +568 -0
  153. package/src/observability/xray.ts +358 -0
  154. package/src/phone/advanced/analytics.ts +349 -0
  155. package/src/phone/advanced/callbacks.ts +428 -0
  156. package/src/phone/advanced/index.ts +8 -0
  157. package/src/phone/advanced/ivr-builder.ts +504 -0
  158. package/src/phone/advanced/recording.ts +310 -0
  159. package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
  160. package/src/phone/handlers/incoming-call.ts +117 -0
  161. package/src/phone/handlers/missed-call.ts +116 -0
  162. package/src/phone/handlers/voicemail.ts +179 -0
  163. package/src/phone/index.ts +9 -0
  164. package/src/presets/api-backend.ts +134 -0
  165. package/src/presets/data-pipeline.ts +204 -0
  166. package/src/presets/extend.test.ts +295 -0
  167. package/src/presets/extend.ts +297 -0
  168. package/src/presets/fullstack-app.ts +144 -0
  169. package/src/presets/index.ts +27 -0
  170. package/src/presets/jamstack.ts +135 -0
  171. package/src/presets/microservices.ts +167 -0
  172. package/src/presets/ml-api.ts +208 -0
  173. package/src/presets/nodejs-server.ts +104 -0
  174. package/src/presets/nodejs-serverless.ts +114 -0
  175. package/src/presets/realtime-app.ts +184 -0
  176. package/src/presets/static-site.ts +64 -0
  177. package/src/presets/traditional-web-app.ts +339 -0
  178. package/src/presets/wordpress.ts +138 -0
  179. package/src/preview/github.test.ts +249 -0
  180. package/src/preview/github.ts +297 -0
  181. package/src/preview/index.ts +37 -0
  182. package/src/preview/manager.test.ts +440 -0
  183. package/src/preview/manager.ts +326 -0
  184. package/src/preview/notifications.test.ts +582 -0
  185. package/src/preview/notifications.ts +341 -0
  186. package/src/queue/batch-processing.ts +402 -0
  187. package/src/queue/dlq-monitoring.ts +402 -0
  188. package/src/queue/fifo.ts +342 -0
  189. package/src/queue/index.ts +9 -0
  190. package/src/queue/management.ts +428 -0
  191. package/src/queue/queue.test.ts +429 -0
  192. package/src/resource-mgmt/index.ts +39 -0
  193. package/src/resource-naming.ts +62 -0
  194. package/src/s3/index.ts +523 -0
  195. package/src/schema/cloud-config.schema.json +554 -0
  196. package/src/schema/index.ts +68 -0
  197. package/src/security/certificate-manager.ts +492 -0
  198. package/src/security/index.ts +9 -0
  199. package/src/security/scanning.ts +545 -0
  200. package/src/security/secrets-manager.ts +476 -0
  201. package/src/security/secrets-rotation.ts +456 -0
  202. package/src/security/security.test.ts +738 -0
  203. package/src/sms/advanced/ab-testing.ts +389 -0
  204. package/src/sms/advanced/analytics.ts +336 -0
  205. package/src/sms/advanced/campaigns.ts +523 -0
  206. package/src/sms/advanced/chatbot.ts +224 -0
  207. package/src/sms/advanced/index.ts +10 -0
  208. package/src/sms/advanced/link-tracking.ts +248 -0
  209. package/src/sms/advanced/mms.ts +308 -0
  210. package/src/sms/handlers/__tests__/send.test.ts +40 -0
  211. package/src/sms/handlers/delivery-status.ts +133 -0
  212. package/src/sms/handlers/receive.ts +162 -0
  213. package/src/sms/handlers/send.ts +174 -0
  214. package/src/sms/index.ts +9 -0
  215. package/src/stack-diff.ts +389 -0
  216. package/src/static-site/index.ts +85 -0
  217. package/src/template-builder.ts +110 -0
  218. package/src/template-validator.ts +574 -0
  219. package/src/utils/cache.ts +291 -0
  220. package/src/utils/diff.ts +269 -0
  221. package/src/utils/hash.ts +227 -0
  222. package/src/utils/index.ts +8 -0
  223. package/src/utils/parallel.ts +294 -0
  224. package/src/validators/credentials.test.ts +274 -0
  225. package/src/validators/credentials.ts +233 -0
  226. package/src/validators/quotas.test.ts +434 -0
  227. package/src/validators/quotas.ts +217 -0
  228. package/test/ai.test.ts +327 -0
  229. package/test/api.test.ts +511 -0
  230. package/test/auth.test.ts +632 -0
  231. package/test/cache.test.ts +406 -0
  232. package/test/cdn.test.ts +247 -0
  233. package/test/compute.test.ts +861 -0
  234. package/test/database.test.ts +523 -0
  235. package/test/deployment.test.ts +499 -0
  236. package/test/dns.test.ts +270 -0
  237. package/test/email.test.ts +439 -0
  238. package/test/filesystem.test.ts +382 -0
  239. package/test/integration.test.ts +350 -0
  240. package/test/messaging.test.ts +514 -0
  241. package/test/monitoring.test.ts +634 -0
  242. package/test/network.test.ts +425 -0
  243. package/test/permissions.test.ts +488 -0
  244. package/test/queue.test.ts +484 -0
  245. package/test/registry.test.ts +306 -0
  246. package/test/security.test.ts +462 -0
  247. package/test/storage.test.ts +463 -0
  248. package/test/template-validator.test.ts +559 -0
  249. package/test/workflow.test.ts +592 -0
  250. package/tsconfig.json +16 -0
  251. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,452 @@
1
+ /**
2
+ * Blue/Green Deployment Strategy
3
+ * Zero-downtime deployments with instant rollback capability
4
+ */
5
+
6
+ export interface BlueGreenDeployment {
7
+ id: string
8
+ name: string
9
+ blueEnvironment: Environment
10
+ greenEnvironment: Environment
11
+ activeEnvironment: 'blue' | 'green'
12
+ routingConfig: RoutingConfig
13
+ autoPromote?: boolean
14
+ autoRollback?: boolean
15
+ healthCheckConfig?: HealthCheckConfig
16
+ }
17
+
18
+ export interface Environment {
19
+ name: string
20
+ targetGroupArn: string
21
+ autoScalingGroupName?: string
22
+ taskDefinitionArn?: string // For ECS
23
+ functionVersionArn?: string // For Lambda
24
+ instanceIds?: string[] // For EC2
25
+ weight?: number
26
+ }
27
+
28
+ export interface RoutingConfig {
29
+ type: 'alb' | 'route53' | 'cloudfront' | 'api-gateway'
30
+ listenerArn?: string // For ALB
31
+ hostedZoneId?: string // For Route53
32
+ distributionId?: string // For CloudFront
33
+ apiId?: string // For API Gateway
34
+ switchoverTimeSeconds?: number
35
+ }
36
+
37
+ export interface HealthCheckConfig {
38
+ healthyThreshold: number
39
+ unhealthyThreshold: number
40
+ interval: number
41
+ timeout: number
42
+ path?: string
43
+ port?: number
44
+ }
45
+
46
+ export interface DeploymentResult {
47
+ success: boolean
48
+ deploymentId: string
49
+ startTime: Date
50
+ endTime?: Date
51
+ switchedAt?: Date
52
+ rolledBackAt?: Date
53
+ healthChecksPassed: boolean
54
+ errors?: string[]
55
+ }
56
+
57
+ /**
58
+ * Blue/Green deployment manager
59
+ */
60
+ export class BlueGreenManager {
61
+ private deployments: Map<string, BlueGreenDeployment> = new Map()
62
+ private deploymentHistory: Map<string, DeploymentResult[]> = new Map()
63
+ private deploymentCounter = 0
64
+ private resultCounter = 0
65
+
66
+ /**
67
+ * Create blue/green deployment configuration
68
+ */
69
+ createDeployment(deployment: Omit<BlueGreenDeployment, 'id'>): BlueGreenDeployment {
70
+ const id = `bg-deployment-${Date.now()}-${this.deploymentCounter++}`
71
+
72
+ const blueGreenDeployment: BlueGreenDeployment = {
73
+ id,
74
+ ...deployment,
75
+ }
76
+
77
+ this.deployments.set(id, blueGreenDeployment)
78
+
79
+ return blueGreenDeployment
80
+ }
81
+
82
+ /**
83
+ * Create ALB-based blue/green deployment
84
+ */
85
+ createALBDeployment(options: {
86
+ name: string
87
+ listenerArn: string
88
+ blueTargetGroupArn: string
89
+ greenTargetGroupArn: string
90
+ autoPromote?: boolean
91
+ healthCheckConfig?: HealthCheckConfig
92
+ }): BlueGreenDeployment {
93
+ return this.createDeployment({
94
+ name: options.name,
95
+ blueEnvironment: {
96
+ name: 'blue',
97
+ targetGroupArn: options.blueTargetGroupArn,
98
+ weight: 100,
99
+ },
100
+ greenEnvironment: {
101
+ name: 'green',
102
+ targetGroupArn: options.greenTargetGroupArn,
103
+ weight: 0,
104
+ },
105
+ activeEnvironment: 'blue',
106
+ routingConfig: {
107
+ type: 'alb',
108
+ listenerArn: options.listenerArn,
109
+ switchoverTimeSeconds: 0,
110
+ },
111
+ autoPromote: options.autoPromote,
112
+ healthCheckConfig: options.healthCheckConfig,
113
+ })
114
+ }
115
+
116
+ /**
117
+ * Create Route53-based blue/green deployment
118
+ */
119
+ createRoute53Deployment(options: {
120
+ name: string
121
+ hostedZoneId: string
122
+ blueTargetGroupArn: string
123
+ greenTargetGroupArn: string
124
+ switchoverTimeSeconds?: number
125
+ }): BlueGreenDeployment {
126
+ return this.createDeployment({
127
+ name: options.name,
128
+ blueEnvironment: {
129
+ name: 'blue',
130
+ targetGroupArn: options.blueTargetGroupArn,
131
+ weight: 100,
132
+ },
133
+ greenEnvironment: {
134
+ name: 'green',
135
+ targetGroupArn: options.greenTargetGroupArn,
136
+ weight: 0,
137
+ },
138
+ activeEnvironment: 'blue',
139
+ routingConfig: {
140
+ type: 'route53',
141
+ hostedZoneId: options.hostedZoneId,
142
+ switchoverTimeSeconds: options.switchoverTimeSeconds || 60,
143
+ },
144
+ })
145
+ }
146
+
147
+ /**
148
+ * Create ECS blue/green deployment
149
+ */
150
+ createECSDeployment(options: {
151
+ name: string
152
+ listenerArn: string
153
+ blueTargetGroupArn: string
154
+ greenTargetGroupArn: string
155
+ blueTaskDefinitionArn: string
156
+ greenTaskDefinitionArn: string
157
+ autoRollback?: boolean
158
+ }): BlueGreenDeployment {
159
+ return this.createDeployment({
160
+ name: options.name,
161
+ blueEnvironment: {
162
+ name: 'blue',
163
+ targetGroupArn: options.blueTargetGroupArn,
164
+ taskDefinitionArn: options.blueTaskDefinitionArn,
165
+ weight: 100,
166
+ },
167
+ greenEnvironment: {
168
+ name: 'green',
169
+ targetGroupArn: options.greenTargetGroupArn,
170
+ taskDefinitionArn: options.greenTaskDefinitionArn,
171
+ weight: 0,
172
+ },
173
+ activeEnvironment: 'blue',
174
+ routingConfig: {
175
+ type: 'alb',
176
+ listenerArn: options.listenerArn,
177
+ },
178
+ autoRollback: options.autoRollback ?? true,
179
+ })
180
+ }
181
+
182
+ /**
183
+ * Execute blue/green deployment
184
+ */
185
+ async executeDeployment(deploymentId: string, dryRun: boolean = false): Promise<DeploymentResult> {
186
+ const deployment = this.deployments.get(deploymentId)
187
+
188
+ if (!deployment) {
189
+ throw new Error(`Deployment not found: ${deploymentId}`)
190
+ }
191
+
192
+ const result: DeploymentResult = {
193
+ success: false,
194
+ deploymentId: `result-${Date.now()}-${this.resultCounter++}`,
195
+ startTime: new Date(),
196
+ healthChecksPassed: false,
197
+ errors: [],
198
+ }
199
+
200
+ console.log(`${dryRun ? '[DRY RUN] ' : ''}Starting blue/green deployment: ${deployment.name}`)
201
+ console.log(` Active environment: ${deployment.activeEnvironment}`)
202
+ console.log(` Routing type: ${deployment.routingConfig.type}`)
203
+
204
+ // Determine target environment
205
+ const targetEnv = deployment.activeEnvironment === 'blue' ? 'green' : 'blue'
206
+ console.log(` Switching to: ${targetEnv}`)
207
+
208
+ // Step 1: Deploy to inactive environment
209
+ console.log(`\\n1. Deploying to ${targetEnv} environment`)
210
+ if (!dryRun) {
211
+ // Simulate deployment
212
+ await new Promise(resolve => setTimeout(resolve, 100))
213
+ }
214
+
215
+ // Step 2: Run health checks
216
+ console.log(`\\n2. Running health checks on ${targetEnv} environment`)
217
+ if (deployment.healthCheckConfig) {
218
+ const passed = await this.runHealthChecks(deployment, targetEnv, dryRun)
219
+ result.healthChecksPassed = passed
220
+
221
+ if (!passed) {
222
+ result.errors?.push('Health checks failed')
223
+ result.endTime = new Date()
224
+
225
+ if (deployment.autoRollback) {
226
+ console.log(' Auto-rollback enabled - keeping current environment active')
227
+ result.rolledBackAt = new Date()
228
+ }
229
+
230
+ this.recordDeployment(deploymentId, result)
231
+ return result
232
+ }
233
+ }
234
+ else {
235
+ result.healthChecksPassed = true
236
+ }
237
+
238
+ // Step 3: Switch traffic
239
+ console.log(`\\n3. Switching traffic to ${targetEnv} environment`)
240
+ if (!dryRun) {
241
+ deployment.activeEnvironment = targetEnv
242
+ result.switchedAt = new Date()
243
+ }
244
+
245
+ // Step 4: Monitor
246
+ console.log(`\\n4. Monitoring ${targetEnv} environment`)
247
+ if (!dryRun) {
248
+ await new Promise(resolve => setTimeout(resolve, 100))
249
+ }
250
+
251
+ result.success = true
252
+ result.endTime = new Date()
253
+
254
+ console.log(`\\n✓ Deployment completed successfully`)
255
+
256
+ this.recordDeployment(deploymentId, result)
257
+
258
+ return result
259
+ }
260
+
261
+ /**
262
+ * Rollback deployment
263
+ */
264
+ async rollback(deploymentId: string): Promise<DeploymentResult> {
265
+ const deployment = this.deployments.get(deploymentId)
266
+
267
+ if (!deployment) {
268
+ throw new Error(`Deployment not found: ${deploymentId}`)
269
+ }
270
+
271
+ const result: DeploymentResult = {
272
+ success: false,
273
+ deploymentId: `result-${Date.now()}-${this.resultCounter++}`,
274
+ startTime: new Date(),
275
+ healthChecksPassed: true,
276
+ errors: [],
277
+ }
278
+
279
+ console.log(`Rolling back deployment: ${deployment.name}`)
280
+
281
+ const previousEnv = deployment.activeEnvironment === 'blue' ? 'green' : 'blue'
282
+ deployment.activeEnvironment = previousEnv
283
+
284
+ result.success = true
285
+ result.rolledBackAt = new Date()
286
+ result.endTime = new Date()
287
+
288
+ console.log(` Switched back to: ${previousEnv}`)
289
+
290
+ this.recordDeployment(deploymentId, result)
291
+
292
+ return result
293
+ }
294
+
295
+ /**
296
+ * Run health checks
297
+ */
298
+ private async runHealthChecks(
299
+ deployment: BlueGreenDeployment,
300
+ environment: 'blue' | 'green',
301
+ dryRun: boolean,
302
+ ): Promise<boolean> {
303
+ const config = deployment.healthCheckConfig!
304
+
305
+ console.log(` Health check path: ${config.path || '/'}`)
306
+ console.log(` Healthy threshold: ${config.healthyThreshold}`)
307
+ console.log(` Interval: ${config.interval}s`)
308
+
309
+ if (dryRun) {
310
+ console.log(' [SKIPPED - DRY RUN]')
311
+ return true
312
+ }
313
+
314
+ // Simulate health checks
315
+ let consecutiveSuccesses = 0
316
+ const maxAttempts = config.healthyThreshold + 2
317
+
318
+ for (let i = 0; i < maxAttempts; i++) {
319
+ await new Promise(resolve => setTimeout(resolve, 50))
320
+
321
+ const healthy = Math.random() > 0.1 // 90% success rate
322
+
323
+ if (healthy) {
324
+ consecutiveSuccesses++
325
+ console.log(` Check ${i + 1}: ✓ Healthy (${consecutiveSuccesses}/${config.healthyThreshold})`)
326
+
327
+ if (consecutiveSuccesses >= config.healthyThreshold) {
328
+ return true
329
+ }
330
+ }
331
+ else {
332
+ consecutiveSuccesses = 0
333
+ console.log(` Check ${i + 1}: ✗ Unhealthy`)
334
+ }
335
+ }
336
+
337
+ return false
338
+ }
339
+
340
+ /**
341
+ * Record deployment result
342
+ */
343
+ private recordDeployment(deploymentId: string, result: DeploymentResult): void {
344
+ if (!this.deploymentHistory.has(deploymentId)) {
345
+ this.deploymentHistory.set(deploymentId, [])
346
+ }
347
+
348
+ this.deploymentHistory.get(deploymentId)!.push(result)
349
+ }
350
+
351
+ /**
352
+ * Get deployment
353
+ */
354
+ getDeployment(id: string): BlueGreenDeployment | undefined {
355
+ return this.deployments.get(id)
356
+ }
357
+
358
+ /**
359
+ * List deployments
360
+ */
361
+ listDeployments(): BlueGreenDeployment[] {
362
+ return Array.from(this.deployments.values())
363
+ }
364
+
365
+ /**
366
+ * Get deployment history
367
+ */
368
+ getDeploymentHistory(deploymentId: string): DeploymentResult[] {
369
+ return this.deploymentHistory.get(deploymentId) || []
370
+ }
371
+
372
+ /**
373
+ * Generate CloudFormation for ALB target group switching
374
+ */
375
+ generateALBListenerCF(deployment: BlueGreenDeployment): any {
376
+ const activeEnv
377
+ = deployment.activeEnvironment === 'blue' ? deployment.blueEnvironment : deployment.greenEnvironment
378
+
379
+ return {
380
+ Type: 'AWS::ElasticLoadBalancingV2::ListenerRule',
381
+ Properties: {
382
+ ListenerArn: deployment.routingConfig.listenerArn,
383
+ Priority: 1,
384
+ Conditions: [
385
+ {
386
+ Field: 'path-pattern',
387
+ Values: ['/*'],
388
+ },
389
+ ],
390
+ Actions: [
391
+ {
392
+ Type: 'forward',
393
+ TargetGroupArn: activeEnv.targetGroupArn,
394
+ },
395
+ ],
396
+ },
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Generate CloudFormation for Route53 weighted routing
402
+ */
403
+ generateRoute53RecordSetCF(deployment: BlueGreenDeployment, recordName: string): any[] {
404
+ return [
405
+ {
406
+ Type: 'AWS::Route53::RecordSet',
407
+ Properties: {
408
+ HostedZoneId: deployment.routingConfig.hostedZoneId,
409
+ Name: recordName,
410
+ Type: 'A',
411
+ SetIdentifier: 'blue',
412
+ Weight: deployment.activeEnvironment === 'blue' ? 100 : 0,
413
+ AliasTarget: {
414
+ HostedZoneId: deployment.routingConfig.hostedZoneId,
415
+ DNSName: deployment.blueEnvironment.targetGroupArn,
416
+ EvaluateTargetHealth: true,
417
+ },
418
+ },
419
+ },
420
+ {
421
+ Type: 'AWS::Route53::RecordSet',
422
+ Properties: {
423
+ HostedZoneId: deployment.routingConfig.hostedZoneId,
424
+ Name: recordName,
425
+ Type: 'A',
426
+ SetIdentifier: 'green',
427
+ Weight: deployment.activeEnvironment === 'green' ? 100 : 0,
428
+ AliasTarget: {
429
+ HostedZoneId: deployment.routingConfig.hostedZoneId,
430
+ DNSName: deployment.greenEnvironment.targetGroupArn,
431
+ EvaluateTargetHealth: true,
432
+ },
433
+ },
434
+ },
435
+ ]
436
+ }
437
+
438
+ /**
439
+ * Clear all data
440
+ */
441
+ clear(): void {
442
+ this.deployments.clear()
443
+ this.deploymentHistory.clear()
444
+ this.deploymentCounter = 0
445
+ this.resultCounter = 0
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Global blue/green manager instance
451
+ */
452
+ export const blueGreenManager: BlueGreenManager = new BlueGreenManager()