@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,840 @@
1
+ import { describe, expect, it, beforeEach } from 'bun:test'
2
+ import {
3
+ LambdaLayersManager,
4
+ lambdaLayersManager,
5
+ LambdaVersionsManager,
6
+ lambdaVersionsManager,
7
+ LambdaConcurrencyManager,
8
+ lambdaConcurrencyManager,
9
+ LambdaDestinationsManager,
10
+ lambdaDestinationsManager,
11
+ LambdaVPCManager,
12
+ lambdaVPCManager,
13
+ LambdaDLQManager,
14
+ lambdaDLQManager,
15
+ } from '.'
16
+
17
+ describe('Lambda Layers Manager', () => {
18
+ let manager: LambdaLayersManager
19
+
20
+ beforeEach(() => {
21
+ manager = new LambdaLayersManager()
22
+ })
23
+
24
+ describe('Layer Creation', () => {
25
+ it('should create Lambda layer', () => {
26
+ const layer = manager.createLayer({
27
+ layerName: 'my-layer',
28
+ description: 'Test layer',
29
+ compatibleRuntimes: ['nodejs18.x'],
30
+ content: {
31
+ type: 's3',
32
+ s3Bucket: 'my-bucket',
33
+ s3Key: 'layer.zip',
34
+ },
35
+ size: 1024 * 1024,
36
+ })
37
+
38
+ expect(layer.id).toContain('layer')
39
+ expect(layer.layerName).toBe('my-layer')
40
+ expect(layer.version).toBe(1)
41
+ expect(layer.layerArn).toContain('my-layer:1')
42
+ })
43
+
44
+ it('should create Node.js dependencies layer', () => {
45
+ const layer = manager.createNodeDependenciesLayer({
46
+ layerName: 'node-deps',
47
+ nodeVersion: '18',
48
+ s3Bucket: 'my-bucket',
49
+ s3Key: 'deps.zip',
50
+ })
51
+
52
+ expect(layer.compatibleRuntimes).toContain('nodejs18')
53
+ expect(layer.description).toBe('Node.js dependencies layer')
54
+ })
55
+
56
+ it('should create utilities layer', () => {
57
+ const layer = manager.createUtilitiesLayer({
58
+ layerName: 'utils',
59
+ runtimes: ['nodejs18.x', 'python3.9'],
60
+ s3Bucket: 'my-bucket',
61
+ s3Key: 'utils.zip',
62
+ })
63
+
64
+ expect(layer.compatibleRuntimes).toHaveLength(2)
65
+ })
66
+ })
67
+
68
+ describe('Layer Versioning', () => {
69
+ it('should publish layer version', () => {
70
+ const layer = manager.createLayer({
71
+ layerName: 'test-layer',
72
+ compatibleRuntimes: ['nodejs18.x'],
73
+ content: { type: 's3', s3Bucket: 'bucket', s3Key: 'key' },
74
+ size: 1024,
75
+ })
76
+
77
+ const version = manager.publishVersion(layer.id)
78
+
79
+ expect(version.version).toBe(2)
80
+ expect(version.layerName).toBe('test-layer')
81
+ expect(layer.version).toBe(2)
82
+ expect(layer.layerArn).toContain(':2')
83
+ })
84
+ })
85
+
86
+ describe('Layer Permissions', () => {
87
+ it('should add layer permission', () => {
88
+ const permission = manager.addPermission({
89
+ layerName: 'my-layer',
90
+ version: 1,
91
+ principal: '123456789012',
92
+ })
93
+
94
+ expect(permission.id).toContain('permission')
95
+ expect(permission.action).toBe('lambda:GetLayerVersion')
96
+ })
97
+
98
+ it('should add organization permission', () => {
99
+ const permission = manager.addPermission({
100
+ layerName: 'my-layer',
101
+ version: 1,
102
+ principal: '*',
103
+ organizationId: 'o-123456',
104
+ })
105
+
106
+ expect(permission.organizationId).toBe('o-123456')
107
+ })
108
+ })
109
+
110
+ describe('CloudFormation Generation', () => {
111
+ it('should generate layer CloudFormation', () => {
112
+ const layer = manager.createLayer({
113
+ layerName: 'test-layer',
114
+ compatibleRuntimes: ['nodejs18.x'],
115
+ content: { type: 's3', s3Bucket: 'bucket', s3Key: 'key' },
116
+ size: 1024,
117
+ })
118
+
119
+ const cf = manager.generateLayerCF(layer)
120
+
121
+ expect(cf.Type).toBe('AWS::Lambda::LayerVersion')
122
+ expect(cf.Properties.LayerName).toBe('test-layer')
123
+ expect(cf.Properties.Content.S3Bucket).toBe('bucket')
124
+ })
125
+ })
126
+
127
+ it('should use global instance', () => {
128
+ expect(lambdaLayersManager).toBeInstanceOf(LambdaLayersManager)
129
+ })
130
+ })
131
+
132
+ describe('Lambda Versions Manager', () => {
133
+ let manager: LambdaVersionsManager
134
+
135
+ beforeEach(() => {
136
+ manager = new LambdaVersionsManager()
137
+ })
138
+
139
+ describe('Version Publishing', () => {
140
+ it('should publish function version', () => {
141
+ const version = manager.publishVersion({
142
+ functionName: 'my-function',
143
+ description: 'Version 1',
144
+ runtime: 'nodejs18.x',
145
+ memorySize: 256,
146
+ timeout: 30,
147
+ })
148
+
149
+ expect(version.id).toContain('version')
150
+ expect(version.version).toBe('1')
151
+ expect(version.functionArn).toContain('my-function:1')
152
+ })
153
+
154
+ it('should increment version numbers', () => {
155
+ const v1 = manager.publishVersion({
156
+ functionName: 'test-function',
157
+ runtime: 'nodejs18.x',
158
+ memorySize: 256,
159
+ timeout: 30,
160
+ })
161
+
162
+ const v2 = manager.publishVersion({
163
+ functionName: 'test-function',
164
+ runtime: 'nodejs18.x',
165
+ memorySize: 256,
166
+ timeout: 30,
167
+ })
168
+
169
+ expect(v1.version).toBe('1')
170
+ expect(v2.version).toBe('2')
171
+ })
172
+ })
173
+
174
+ describe('Alias Management', () => {
175
+ it('should create alias', () => {
176
+ const alias = manager.createAlias({
177
+ functionName: 'my-function',
178
+ aliasName: 'prod',
179
+ functionVersion: '1',
180
+ description: 'Production alias',
181
+ })
182
+
183
+ expect(alias.id).toContain('alias')
184
+ expect(alias.aliasName).toBe('prod')
185
+ expect(alias.aliasArn).toContain(':prod')
186
+ })
187
+
188
+ it('should create production alias', () => {
189
+ const alias = manager.createProductionAlias({
190
+ functionName: 'my-function',
191
+ version: '5',
192
+ })
193
+
194
+ expect(alias.aliasName).toBe('production')
195
+ expect(alias.functionVersion).toBe('5')
196
+ })
197
+
198
+ it('should create staging alias', () => {
199
+ const alias = manager.createStagingAlias({
200
+ functionName: 'my-function',
201
+ version: '3',
202
+ })
203
+
204
+ expect(alias.aliasName).toBe('staging')
205
+ })
206
+
207
+ it('should update alias', () => {
208
+ const alias = manager.createAlias({
209
+ functionName: 'my-function',
210
+ aliasName: 'test',
211
+ functionVersion: '1',
212
+ })
213
+
214
+ const updated = manager.updateAlias(alias.id, '2')
215
+
216
+ expect(updated.functionVersion).toBe('2')
217
+ })
218
+ })
219
+
220
+ describe('Weighted Routing', () => {
221
+ it('should configure weighted routing', () => {
222
+ const alias = manager.createAlias({
223
+ functionName: 'my-function',
224
+ aliasName: 'prod',
225
+ functionVersion: '1',
226
+ })
227
+
228
+ manager.configureWeightedRouting(alias.id, {
229
+ '2': 0.1,
230
+ })
231
+
232
+ expect(alias.routingConfig?.additionalVersionWeights).toEqual({ '2': 0.1 })
233
+ })
234
+ })
235
+
236
+ describe('Canary Deployments', () => {
237
+ it('should create canary deployment', () => {
238
+ const deployment = manager.createCanaryDeployment({
239
+ functionName: 'my-function',
240
+ fromVersion: '1',
241
+ toVersion: '2',
242
+ aliasName: 'prod',
243
+ canaryWeight: 0.1,
244
+ })
245
+
246
+ expect(deployment.id).toContain('deployment')
247
+ expect(deployment.strategy).toBe('canary')
248
+ expect(deployment.status).toBe('in_progress')
249
+ })
250
+
251
+ it('should complete deployment', () => {
252
+ const deployment = manager.createCanaryDeployment({
253
+ functionName: 'my-function',
254
+ fromVersion: '1',
255
+ toVersion: '2',
256
+ aliasName: 'prod',
257
+ canaryWeight: 0.1,
258
+ })
259
+
260
+ const completed = manager.completeDeployment(deployment.id)
261
+
262
+ expect(completed.status).toBe('completed')
263
+ expect(completed.completedAt).toBeDefined()
264
+ })
265
+
266
+ it('should rollback deployment', () => {
267
+ const deployment = manager.createCanaryDeployment({
268
+ functionName: 'my-function',
269
+ fromVersion: '1',
270
+ toVersion: '2',
271
+ aliasName: 'prod',
272
+ canaryWeight: 0.1,
273
+ })
274
+
275
+ const rolledBack = manager.rollbackDeployment(deployment.id)
276
+
277
+ expect(rolledBack.status).toBe('failed')
278
+ })
279
+ })
280
+
281
+ it('should use global instance', () => {
282
+ expect(lambdaVersionsManager).toBeInstanceOf(LambdaVersionsManager)
283
+ })
284
+ })
285
+
286
+ describe('Lambda Concurrency Manager', () => {
287
+ let manager: LambdaConcurrencyManager
288
+
289
+ beforeEach(() => {
290
+ manager = new LambdaConcurrencyManager()
291
+ })
292
+
293
+ describe('Reserved Concurrency', () => {
294
+ it('should set reserved concurrency', () => {
295
+ const config = manager.setReservedConcurrency({
296
+ functionName: 'my-function',
297
+ reservedConcurrency: 10,
298
+ })
299
+
300
+ expect(config.id).toContain('concurrency')
301
+ expect(config.reservedConcurrency).toBe(10)
302
+ })
303
+ })
304
+
305
+ describe('Provisioned Concurrency', () => {
306
+ it('should set provisioned concurrency', async () => {
307
+ const config = manager.setProvisionedConcurrency({
308
+ functionName: 'my-function',
309
+ qualifier: 'prod',
310
+ provisionedConcurrentExecutions: 5,
311
+ })
312
+
313
+ expect(config.id).toContain('provisioned')
314
+ expect(config.status).toBe('pending')
315
+
316
+ // Wait for provisioning
317
+ await new Promise(resolve => setTimeout(resolve, 150))
318
+
319
+ expect(config.status).toBe('ready')
320
+ expect(config.allocatedConcurrency).toBe(5)
321
+ })
322
+
323
+ it('should configure warm pool', () => {
324
+ const config = manager.configureWarmPool({
325
+ functionName: 'my-function',
326
+ alias: 'prod',
327
+ minInstances: 3,
328
+ })
329
+
330
+ expect(config.provisionedConcurrentExecutions).toBe(3)
331
+ })
332
+ })
333
+
334
+ describe('Concurrency Schedules', () => {
335
+ it('should create schedule', () => {
336
+ const schedule = manager.createSchedule({
337
+ name: 'business-hours',
338
+ functionName: 'my-function',
339
+ qualifier: 'prod',
340
+ schedule: [
341
+ {
342
+ name: 'morning',
343
+ cronExpression: '0 8 * * MON-FRI',
344
+ targetConcurrency: 10,
345
+ },
346
+ ],
347
+ })
348
+
349
+ expect(schedule.id).toContain('schedule')
350
+ expect(schedule.schedule).toHaveLength(1)
351
+ })
352
+
353
+ it('should create business hours schedule', () => {
354
+ const schedule = manager.createBusinessHoursSchedule({
355
+ functionName: 'my-function',
356
+ qualifier: 'prod',
357
+ businessHoursConcurrency: 10,
358
+ offHoursConcurrency: 2,
359
+ })
360
+
361
+ expect(schedule.schedule).toHaveLength(3)
362
+ expect(schedule.schedule[0].name).toBe('business-hours')
363
+ expect(schedule.schedule[1].name).toBe('off-hours')
364
+ expect(schedule.schedule[2].name).toBe('weekend')
365
+ })
366
+ })
367
+
368
+ describe('Auto-Scaling', () => {
369
+ it('should configure auto-scaling', () => {
370
+ const config = manager.configureAutoScaling({
371
+ functionName: 'my-function',
372
+ qualifier: 'prod',
373
+ minCapacity: 1,
374
+ maxCapacity: 10,
375
+ targetUtilization: 0.7,
376
+ })
377
+
378
+ expect(config.id).toContain('autoscaling')
379
+ expect(config.targetUtilization).toBe(0.7)
380
+ })
381
+
382
+ it('should configure predictive scaling', () => {
383
+ const config = manager.configurePredictiveScaling({
384
+ functionName: 'my-function',
385
+ qualifier: 'prod',
386
+ baselineCapacity: 2,
387
+ peakCapacity: 20,
388
+ })
389
+
390
+ expect(config.minCapacity).toBe(2)
391
+ expect(config.maxCapacity).toBe(20)
392
+ expect(config.targetUtilization).toBe(0.7)
393
+ })
394
+ })
395
+
396
+ it('should use global instance', () => {
397
+ expect(lambdaConcurrencyManager).toBeInstanceOf(LambdaConcurrencyManager)
398
+ })
399
+ })
400
+
401
+ describe('Lambda Destinations Manager', () => {
402
+ let manager: LambdaDestinationsManager
403
+
404
+ beforeEach(() => {
405
+ manager = new LambdaDestinationsManager()
406
+ })
407
+
408
+ describe('Destination Configuration', () => {
409
+ it('should configure SQS destination', () => {
410
+ const config = manager.configureSQSDestination({
411
+ functionName: 'my-function',
412
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:my-queue',
413
+ onFailure: true,
414
+ })
415
+
416
+ expect(config.id).toContain('destination')
417
+ expect(config.failureDestination?.type).toBe('sqs')
418
+ })
419
+
420
+ it('should configure SNS destination', () => {
421
+ const config = manager.configureSNSDestination({
422
+ functionName: 'my-function',
423
+ topicArn: 'arn:aws:sns:us-east-1:123456789012:my-topic',
424
+ onSuccess: true,
425
+ })
426
+
427
+ expect(config.successDestination?.type).toBe('sns')
428
+ })
429
+
430
+ it('should configure EventBridge destination', () => {
431
+ const config = manager.configureEventBridgeDestination({
432
+ functionName: 'my-function',
433
+ eventBusArn: 'arn:aws:events:us-east-1:123456789012:event-bus/default',
434
+ onSuccess: true,
435
+ onFailure: true,
436
+ })
437
+
438
+ expect(config.successDestination?.type).toBe('eventbridge')
439
+ expect(config.failureDestination?.type).toBe('eventbridge')
440
+ })
441
+
442
+ it('should configure Lambda destination', () => {
443
+ const config = manager.configureLambdaDestination({
444
+ functionName: 'my-function',
445
+ destinationFunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:handler',
446
+ onFailure: true,
447
+ })
448
+
449
+ expect(config.failureDestination?.type).toBe('lambda')
450
+ })
451
+ })
452
+
453
+ describe('EventBridge Integration', () => {
454
+ it('should create EventBridge integration', () => {
455
+ const integration = manager.createEventBridgeIntegration({
456
+ functionName: 'my-function',
457
+ eventBusArn: 'arn:aws:events:us-east-1:123456789012:event-bus/custom',
458
+ })
459
+
460
+ expect(integration.id).toContain('eventbridge')
461
+ expect(integration.source).toContain('my-function')
462
+ })
463
+ })
464
+
465
+ describe('Sending to Destinations', () => {
466
+ it('should send to success destination', () => {
467
+ manager.configureSQSDestination({
468
+ functionName: 'my-function',
469
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:queue',
470
+ onSuccess: true,
471
+ })
472
+
473
+ const record = manager.sendToDestination({
474
+ functionName: 'my-function',
475
+ requestId: 'req-123',
476
+ status: 'success',
477
+ payload: { result: 'ok' },
478
+ })
479
+
480
+ expect(record).toBeDefined()
481
+ expect(record?.status).toBe('success')
482
+ expect(record?.destinationType).toBe('sqs')
483
+ })
484
+
485
+ it('should send to failure destination', () => {
486
+ manager.configureSNSDestination({
487
+ functionName: 'my-function',
488
+ topicArn: 'arn:aws:sns:us-east-1:123456789012:topic',
489
+ onFailure: true,
490
+ })
491
+
492
+ const record = manager.sendToDestination({
493
+ functionName: 'my-function',
494
+ requestId: 'req-456',
495
+ status: 'failure',
496
+ error: 'Function failed',
497
+ })
498
+
499
+ expect(record?.status).toBe('failure')
500
+ expect(record?.error).toBe('Function failed')
501
+ })
502
+ })
503
+
504
+ it('should use global instance', () => {
505
+ expect(lambdaDestinationsManager).toBeInstanceOf(LambdaDestinationsManager)
506
+ })
507
+ })
508
+
509
+ describe('Lambda VPC Manager', () => {
510
+ let manager: LambdaVPCManager
511
+
512
+ beforeEach(() => {
513
+ manager = new LambdaVPCManager()
514
+ })
515
+
516
+ describe('VPC Configuration', () => {
517
+ it('should configure VPC', () => {
518
+ const config = manager.configureVPC({
519
+ functionName: 'my-function',
520
+ vpcId: 'vpc-123456',
521
+ subnetIds: ['subnet-1', 'subnet-2'],
522
+ securityGroupIds: ['sg-123456'],
523
+ })
524
+
525
+ expect(config.id).toContain('vpc-config')
526
+ expect(config.subnetIds).toHaveLength(2)
527
+ })
528
+
529
+ it('should configure private VPC', () => {
530
+ const config = manager.configurePrivateVPC({
531
+ functionName: 'my-function',
532
+ vpcId: 'vpc-123456',
533
+ privateSubnetIds: ['subnet-1', 'subnet-2'],
534
+ securityGroupId: 'sg-123456',
535
+ })
536
+
537
+ expect(config.ipv6Allowed).toBe(false)
538
+ })
539
+
540
+ it('should configure multi-AZ VPC', () => {
541
+ const config = manager.configureMultiAZVPC({
542
+ functionName: 'my-function',
543
+ vpcId: 'vpc-123456',
544
+ subnetIds: ['subnet-1', 'subnet-2', 'subnet-3'],
545
+ securityGroupIds: ['sg-123456'],
546
+ })
547
+
548
+ expect(config.subnetIds.length).toBeGreaterThanOrEqual(2)
549
+ })
550
+
551
+ it('should require at least 2 subnets for multi-AZ', () => {
552
+ expect(() => {
553
+ manager.configureMultiAZVPC({
554
+ functionName: 'my-function',
555
+ vpcId: 'vpc-123456',
556
+ subnetIds: ['subnet-1'],
557
+ securityGroupIds: ['sg-123456'],
558
+ })
559
+ }).toThrow('Multi-AZ configuration requires at least 2 subnets')
560
+ })
561
+ })
562
+
563
+ describe('VPC Endpoints', () => {
564
+ it('should create S3 endpoint', () => {
565
+ const endpoint = manager.createS3Endpoint({
566
+ vpcId: 'vpc-123456',
567
+ routeTableIds: ['rtb-1'],
568
+ })
569
+
570
+ expect(endpoint.endpointType).toBe('Gateway')
571
+ expect(endpoint.serviceName).toContain('s3')
572
+ })
573
+
574
+ it('should create DynamoDB endpoint', () => {
575
+ const endpoint = manager.createDynamoDBEndpoint({
576
+ vpcId: 'vpc-123456',
577
+ routeTableIds: ['rtb-1'],
578
+ })
579
+
580
+ expect(endpoint.serviceName).toContain('dynamodb')
581
+ })
582
+
583
+ it('should create Secrets Manager endpoint', () => {
584
+ const endpoint = manager.createSecretsManagerEndpoint({
585
+ vpcId: 'vpc-123456',
586
+ subnetIds: ['subnet-1'],
587
+ securityGroupIds: ['sg-123456'],
588
+ })
589
+
590
+ expect(endpoint.endpointType).toBe('Interface')
591
+ expect(endpoint.privateDnsEnabled).toBe(true)
592
+ })
593
+ })
594
+
595
+ describe('Network Interfaces', () => {
596
+ it('should create network interfaces', async () => {
597
+ const config = manager.configureVPC({
598
+ functionName: 'my-function',
599
+ vpcId: 'vpc-123456',
600
+ subnetIds: ['subnet-1', 'subnet-2'],
601
+ securityGroupIds: ['sg-123456'],
602
+ })
603
+
604
+ const enis = manager.getNetworkInterfaces('my-function')
605
+
606
+ expect(enis).toHaveLength(2)
607
+ expect(enis[0].subnetId).toBe('subnet-1')
608
+
609
+ // Wait for ENIs to become available
610
+ await new Promise(resolve => setTimeout(resolve, 150))
611
+
612
+ expect(enis[0].status).toBe('available')
613
+ })
614
+ })
615
+
616
+ describe('Connectivity Analysis', () => {
617
+ it('should analyze VPC connectivity', () => {
618
+ manager.configureVPC({
619
+ functionName: 'my-function',
620
+ vpcId: 'vpc-123456',
621
+ subnetIds: ['subnet-1'],
622
+ securityGroupIds: ['sg-123456'],
623
+ })
624
+
625
+ const connectivity = manager.analyzeConnectivity({
626
+ functionName: 'my-function',
627
+ hasNATGateway: true,
628
+ })
629
+
630
+ expect(connectivity.hasInternetAccess).toBe(true)
631
+ expect(connectivity.hasNATGateway).toBe(true)
632
+ })
633
+
634
+ it('should provide recommendations', () => {
635
+ manager.configureVPC({
636
+ functionName: 'my-function',
637
+ vpcId: 'vpc-123456',
638
+ subnetIds: ['subnet-1'],
639
+ securityGroupIds: ['sg-123456'],
640
+ })
641
+
642
+ const connectivity = manager.analyzeConnectivity({
643
+ functionName: 'my-function',
644
+ hasNATGateway: false,
645
+ })
646
+
647
+ expect(connectivity.recommendations.length).toBeGreaterThan(0)
648
+ })
649
+ })
650
+
651
+ it('should use global instance', () => {
652
+ expect(lambdaVPCManager).toBeInstanceOf(LambdaVPCManager)
653
+ })
654
+ })
655
+
656
+ describe('Lambda DLQ Manager', () => {
657
+ let manager: LambdaDLQManager
658
+
659
+ beforeEach(() => {
660
+ manager = new LambdaDLQManager()
661
+ })
662
+
663
+ describe('DLQ Configuration', () => {
664
+ it('should configure SQS DLQ', () => {
665
+ const config = manager.configureSQSDLQ({
666
+ functionName: 'my-function',
667
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:my-dlq',
668
+ })
669
+
670
+ expect(config.id).toContain('dlq')
671
+ expect(config.targetType).toBe('sqs')
672
+ expect(config.maxReceiveCount).toBe(3)
673
+ })
674
+
675
+ it('should configure SNS DLQ', () => {
676
+ const config = manager.configureSNSDLQ({
677
+ functionName: 'my-function',
678
+ topicArn: 'arn:aws:sns:us-east-1:123456789012:my-topic',
679
+ })
680
+
681
+ expect(config.targetType).toBe('sns')
682
+ })
683
+
684
+ it('should configure DLQ with alarm', () => {
685
+ const config = manager.configureDLQWithAlarm({
686
+ functionName: 'my-function',
687
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
688
+ alarmThreshold: 10,
689
+ notificationTopicArn: 'arn:aws:sns:us-east-1:123456789012:alerts',
690
+ })
691
+
692
+ expect(config.targetType).toBe('sqs')
693
+ })
694
+ })
695
+
696
+ describe('DLQ Messages', () => {
697
+ it('should send message to DLQ', () => {
698
+ const message = manager.sendToDLQ({
699
+ functionName: 'my-function',
700
+ requestId: 'req-123',
701
+ errorMessage: 'Function timeout',
702
+ errorType: 'TimeoutError',
703
+ payload: { test: 'data' },
704
+ attemptCount: 3,
705
+ })
706
+
707
+ expect(message.id).toContain('message')
708
+ expect(message.errorType).toBe('TimeoutError')
709
+ expect(message.attemptCount).toBe(3)
710
+ })
711
+ })
712
+
713
+ describe('DLQ Alarms', () => {
714
+ it('should create DLQ alarm', () => {
715
+ const config = manager.configureSQSDLQ({
716
+ functionName: 'my-function',
717
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
718
+ })
719
+
720
+ const alarm = manager.createDLQAlarm({
721
+ dlqConfigId: config.id,
722
+ alarmName: 'test-alarm',
723
+ threshold: 5,
724
+ evaluationPeriods: 2,
725
+ enabled: true,
726
+ })
727
+
728
+ expect(alarm.id).toContain('alarm')
729
+ expect(alarm.threshold).toBe(5)
730
+ })
731
+
732
+ it('should create age alarm', () => {
733
+ const config = manager.configureSQSDLQ({
734
+ functionName: 'my-function',
735
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
736
+ })
737
+
738
+ const alarm = manager.createAgeAlarm({
739
+ dlqConfigId: config.id,
740
+ maxAgeSeconds: 3600,
741
+ notificationTopicArn: 'arn:aws:sns:us-east-1:123456789012:alerts',
742
+ })
743
+
744
+ expect(alarm.threshold).toBe(3600)
745
+ })
746
+ })
747
+
748
+ describe('Message Reprocessing', () => {
749
+ it('should reprocess message', async () => {
750
+ const config = manager.configureSQSDLQ({
751
+ functionName: 'my-function',
752
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
753
+ })
754
+
755
+ const message = manager.sendToDLQ({
756
+ functionName: 'my-function',
757
+ requestId: 'req-123',
758
+ errorMessage: 'Error',
759
+ errorType: 'Error',
760
+ payload: {},
761
+ attemptCount: 1,
762
+ })
763
+
764
+ const reprocessing = await manager.reprocessMessage(message.id)
765
+
766
+ expect(reprocessing.status).toBe('pending')
767
+
768
+ // Wait for reprocessing to complete
769
+ await new Promise(resolve => setTimeout(resolve, 200))
770
+
771
+ expect(['success', 'failed']).toContain(reprocessing.status)
772
+ })
773
+
774
+ it('should batch reprocess messages', async () => {
775
+ const config = manager.configureSQSDLQ({
776
+ functionName: 'my-function',
777
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
778
+ })
779
+
780
+ // Send multiple messages
781
+ for (let i = 0; i < 5; i++) {
782
+ manager.sendToDLQ({
783
+ functionName: 'my-function',
784
+ requestId: `req-${i}`,
785
+ errorMessage: 'Error',
786
+ errorType: 'Error',
787
+ payload: {},
788
+ attemptCount: 1,
789
+ })
790
+ }
791
+
792
+ const results = await manager.batchReprocess({
793
+ dlqConfigId: config.id,
794
+ maxMessages: 3,
795
+ })
796
+
797
+ expect(results).toHaveLength(3)
798
+ })
799
+ })
800
+
801
+ describe('DLQ Statistics', () => {
802
+ it('should get DLQ stats', () => {
803
+ const config = manager.configureSQSDLQ({
804
+ functionName: 'my-function',
805
+ queueArn: 'arn:aws:sqs:us-east-1:123456789012:dlq',
806
+ })
807
+
808
+ manager.sendToDLQ({
809
+ functionName: 'my-function',
810
+ requestId: 'req-1',
811
+ errorMessage: 'Error 1',
812
+ errorType: 'TypeError',
813
+ payload: {},
814
+ attemptCount: 2,
815
+ })
816
+
817
+ manager.sendToDLQ({
818
+ functionName: 'my-function',
819
+ requestId: 'req-2',
820
+ errorMessage: 'Error 2',
821
+ errorType: 'ValidationError',
822
+ payload: {},
823
+ attemptCount: 3,
824
+ })
825
+
826
+ const stats = manager.getDLQStats(config.id)
827
+
828
+ expect(stats.totalMessages).toBe(2)
829
+ expect(stats.averageAttempts).toBe(2.5)
830
+ expect(stats.errorTypes).toEqual({
831
+ TypeError: 1,
832
+ ValidationError: 1,
833
+ })
834
+ })
835
+ })
836
+
837
+ it('should use global instance', () => {
838
+ expect(lambdaDLQManager).toBeInstanceOf(LambdaDLQManager)
839
+ })
840
+ })