@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,429 @@
1
+ import { describe, expect, it, beforeEach } from 'bun:test'
2
+ import {
3
+ FIFOQueueManager,
4
+ fifoQueueManager,
5
+ DLQMonitoringManager,
6
+ dlqMonitoringManager,
7
+ BatchProcessingManager,
8
+ batchProcessingManager,
9
+ QueueManagementManager,
10
+ queueManagementManager,
11
+ } from '.'
12
+
13
+ describe('FIFO Queue Manager', () => {
14
+ let manager: FIFOQueueManager
15
+
16
+ beforeEach(() => {
17
+ manager = new FIFOQueueManager()
18
+ })
19
+
20
+ it('should create FIFO queue', () => {
21
+ const queue = manager.createFIFOQueue({
22
+ name: 'test-queue',
23
+ contentBasedDeduplication: true,
24
+ deduplicationScope: 'queue',
25
+ fifoThroughputLimit: 'perQueue',
26
+ messageRetentionPeriod: 345600,
27
+ visibilityTimeout: 30,
28
+ receiveMessageWaitTime: 0,
29
+ })
30
+
31
+ expect(queue.id).toContain('fifo-queue')
32
+ expect(queue.name).toBe('test-queue.fifo')
33
+ })
34
+
35
+ it('should create high-throughput FIFO', () => {
36
+ const queue = manager.createHighThroughputFIFO({
37
+ name: 'high-throughput',
38
+ contentBasedDeduplication: true,
39
+ })
40
+
41
+ expect(queue.deduplicationScope).toBe('messageGroup')
42
+ expect(queue.fifoThroughputLimit).toBe('perMessageGroupId')
43
+ })
44
+
45
+ it('should send message to FIFO queue', () => {
46
+ const queue = manager.createStandardFIFO({
47
+ name: 'test',
48
+ contentBasedDeduplication: false,
49
+ })
50
+
51
+ const message = manager.sendMessage({
52
+ queueId: queue.id,
53
+ messageGroupId: 'group1',
54
+ messageBody: 'Test message',
55
+ messageDeduplicationId: 'dedup-1',
56
+ })
57
+
58
+ expect(message).toBeDefined()
59
+ expect(message?.messageGroupId).toBe('group1')
60
+ })
61
+
62
+ it('should deduplicate messages', () => {
63
+ const queue = manager.createStandardFIFO({
64
+ name: 'test',
65
+ contentBasedDeduplication: false,
66
+ })
67
+
68
+ const msg1 = manager.sendMessage({
69
+ queueId: queue.id,
70
+ messageGroupId: 'group1',
71
+ messageBody: 'Test',
72
+ messageDeduplicationId: 'same-id',
73
+ })
74
+
75
+ const msg2 = manager.sendMessage({
76
+ queueId: queue.id,
77
+ messageGroupId: 'group1',
78
+ messageBody: 'Test',
79
+ messageDeduplicationId: 'same-id',
80
+ })
81
+
82
+ expect(msg1).toBeDefined()
83
+ expect(msg2).toBeNull() // Deduplicated
84
+ })
85
+
86
+ it('should track message groups', () => {
87
+ const queue = manager.createStandardFIFO({ name: 'test' })
88
+
89
+ manager.sendMessage({
90
+ queueId: queue.id,
91
+ messageGroupId: 'group1',
92
+ messageBody: 'Message 1',
93
+ messageDeduplicationId: 'msg1',
94
+ })
95
+
96
+ manager.sendMessage({
97
+ queueId: queue.id,
98
+ messageGroupId: 'group2',
99
+ messageBody: 'Message 2',
100
+ messageDeduplicationId: 'msg2',
101
+ })
102
+
103
+ const groups = manager.getMessageGroups(queue.id)
104
+ expect(groups).toHaveLength(2)
105
+ })
106
+
107
+ it('should use global instance', () => {
108
+ expect(fifoQueueManager).toBeInstanceOf(FIFOQueueManager)
109
+ })
110
+ })
111
+
112
+ describe('DLQ Monitoring Manager', () => {
113
+ let manager: DLQMonitoringManager
114
+
115
+ beforeEach(() => {
116
+ manager = new DLQMonitoringManager()
117
+ })
118
+
119
+ it('should create DLQ monitor', () => {
120
+ const monitor = manager.createDLQMonitor({
121
+ name: 'test-dlq',
122
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/test-dlq',
123
+ sourceQueues: ['source-queue'],
124
+ maxReceiveCount: 3,
125
+ alarmThreshold: 10,
126
+ autoReprocess: false,
127
+ reprocessStrategy: 'manual',
128
+ })
129
+
130
+ expect(monitor.id).toContain('dlq-monitor')
131
+ expect(monitor.maxReceiveCount).toBe(3)
132
+ })
133
+
134
+ it('should create automated monitor', () => {
135
+ const monitor = manager.createAutomatedMonitor({
136
+ name: 'automated',
137
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/dlq',
138
+ sourceQueues: ['main-queue'],
139
+ notificationTopicArn: 'arn:aws:sns:us-east-1:123456789012:alerts',
140
+ })
141
+
142
+ expect(monitor.autoReprocess).toBe(true)
143
+ expect(monitor.reprocessStrategy).toBe('scheduled')
144
+ })
145
+
146
+ it('should collect metrics', () => {
147
+ const metrics = manager.collectMetrics('https://sqs.us-east-1.amazonaws.com/123456789012/test')
148
+
149
+ expect(metrics.id).toContain('metrics')
150
+ expect(metrics.approximateNumberOfMessages).toBeGreaterThanOrEqual(0)
151
+ })
152
+
153
+ it('should create reprocess job', async () => {
154
+ const job = manager.createReprocessJob({
155
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/dlq',
156
+ messageId: 'msg-123',
157
+ })
158
+
159
+ expect(job.status).toBe('pending')
160
+
161
+ await manager.executeReprocessJob(job.id)
162
+
163
+ expect(['success', 'failed']).toContain(job.status)
164
+ })
165
+
166
+ it('should batch reprocess messages', async () => {
167
+ const jobs = await manager.batchReprocess({
168
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/dlq',
169
+ maxMessages: 5,
170
+ })
171
+
172
+ expect(jobs).toHaveLength(5)
173
+ })
174
+
175
+ it('should get DLQ statistics', () => {
176
+ manager.collectMetrics('https://sqs.us-east-1.amazonaws.com/123456789012/test')
177
+
178
+ const stats = manager.getDLQStatistics('https://sqs.us-east-1.amazonaws.com/123456789012/test')
179
+
180
+ expect(stats).toBeDefined()
181
+ expect(stats.totalMessages).toBeGreaterThanOrEqual(0)
182
+ })
183
+
184
+ it('should use global instance', () => {
185
+ expect(dlqMonitoringManager).toBeInstanceOf(DLQMonitoringManager)
186
+ })
187
+ })
188
+
189
+ describe('Batch Processing Manager', () => {
190
+ let manager: BatchProcessingManager
191
+
192
+ beforeEach(() => {
193
+ manager = new BatchProcessingManager()
194
+ })
195
+
196
+ it('should create batch config', () => {
197
+ const config = manager.createBatchConfig({
198
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
199
+ batchSize: 10,
200
+ maxWaitTime: 100,
201
+ parallelProcessors: 5,
202
+ retryAttempts: 3,
203
+ visibilityTimeout: 30,
204
+ })
205
+
206
+ expect(config.id).toContain('batch-config')
207
+ expect(config.batchSize).toBe(10)
208
+ })
209
+
210
+ it('should create high-throughput config', () => {
211
+ const config = manager.createHighThroughputConfig({
212
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
213
+ })
214
+
215
+ expect(config.batchSize).toBe(10)
216
+ expect(config.parallelProcessors).toBe(10)
217
+ })
218
+
219
+ it('should create low-latency config', () => {
220
+ const config = manager.createLowLatencyConfig({
221
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
222
+ })
223
+
224
+ expect(config.batchSize).toBe(1)
225
+ expect(config.maxWaitTime).toBe(0)
226
+ })
227
+
228
+ it('should create batch job', () => {
229
+ const config = manager.createBatchConfig({
230
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
231
+ batchSize: 5,
232
+ maxWaitTime: 100,
233
+ parallelProcessors: 2,
234
+ retryAttempts: 2,
235
+ visibilityTimeout: 30,
236
+ })
237
+
238
+ const job = manager.createBatchJob({
239
+ configId: config.id,
240
+ messageCount: 20,
241
+ })
242
+
243
+ expect(job.messages).toHaveLength(20)
244
+ expect(job.status).toBe('pending')
245
+ })
246
+
247
+ it('should process batch job', async () => {
248
+ const config = manager.createBatchConfig({
249
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
250
+ batchSize: 5,
251
+ maxWaitTime: 100,
252
+ parallelProcessors: 2,
253
+ retryAttempts: 2,
254
+ visibilityTimeout: 30,
255
+ })
256
+
257
+ const job = manager.createBatchJob({
258
+ configId: config.id,
259
+ messageCount: 10,
260
+ })
261
+
262
+ await manager.processBatchJob(job.id)
263
+
264
+ expect(['completed', 'failed']).toContain(job.status)
265
+ expect(job.processedCount).toBeGreaterThan(0)
266
+ })
267
+
268
+ it('should get batch statistics', async () => {
269
+ const config = manager.createBatchConfig({
270
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
271
+ batchSize: 5,
272
+ maxWaitTime: 100,
273
+ parallelProcessors: 2,
274
+ retryAttempts: 2,
275
+ visibilityTimeout: 30,
276
+ })
277
+
278
+ const job = manager.createBatchJob({
279
+ configId: config.id,
280
+ messageCount: 10,
281
+ })
282
+
283
+ await manager.processBatchJob(job.id)
284
+
285
+ const stats = manager.getBatchStatistics(config.id)
286
+
287
+ expect(stats.totalJobsProcessed).toBe(1)
288
+ expect(stats.totalMessagesProcessed).toBeGreaterThan(0)
289
+ })
290
+
291
+ it('should optimize batch config', async () => {
292
+ const config = manager.createBatchConfig({
293
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789012/queue',
294
+ batchSize: 5,
295
+ maxWaitTime: 100,
296
+ parallelProcessors: 2,
297
+ retryAttempts: 2,
298
+ visibilityTimeout: 30,
299
+ })
300
+
301
+ const job = manager.createBatchJob({
302
+ configId: config.id,
303
+ messageCount: 10,
304
+ })
305
+
306
+ await manager.processBatchJob(job.id)
307
+
308
+ const optimized = manager.optimizeBatchConfig(config.id)
309
+
310
+ expect(optimized).toBeDefined()
311
+ })
312
+
313
+ it('should use global instance', () => {
314
+ expect(batchProcessingManager).toBeInstanceOf(BatchProcessingManager)
315
+ })
316
+ })
317
+
318
+ describe('Queue Management Manager', () => {
319
+ let manager: QueueManagementManager
320
+
321
+ beforeEach(() => {
322
+ manager = new QueueManagementManager()
323
+ })
324
+
325
+ it('should create standard queue', () => {
326
+ const queue = manager.createStandardQueue({
327
+ queueName: 'test-queue',
328
+ messageRetentionDays: 4,
329
+ })
330
+
331
+ expect(queue.id).toContain('queue')
332
+ expect(queue.queueName).toBe('test-queue')
333
+ })
334
+
335
+ it('should create long polling queue', () => {
336
+ const queue = manager.createLongPollingQueue({
337
+ queueName: 'long-poll',
338
+ waitTimeSeconds: 20,
339
+ })
340
+
341
+ expect(queue.receiveMessageWaitTime).toBe(20)
342
+ })
343
+
344
+ it('should create retention policy', () => {
345
+ const queue = manager.createStandardQueue({
346
+ queueName: 'test',
347
+ })
348
+
349
+ const policy = manager.createRetentionPolicy({
350
+ queueId: queue.id,
351
+ retentionPeriod: 86400, // 1 day
352
+ autoCleanup: true,
353
+ archiveExpiredMessages: false,
354
+ })
355
+
356
+ expect(policy.id).toContain('retention')
357
+ expect(policy.retentionPeriod).toBe(86400)
358
+ })
359
+
360
+ it('should create archival retention policy', () => {
361
+ const queue = manager.createStandardQueue({
362
+ queueName: 'test',
363
+ })
364
+
365
+ const policy = manager.createArchivalRetentionPolicy({
366
+ queueId: queue.id,
367
+ retentionDays: 30,
368
+ s3Bucket: 'archive-bucket',
369
+ })
370
+
371
+ expect(policy.archiveExpiredMessages).toBe(true)
372
+ expect(policy.archiveS3Bucket).toBe('archive-bucket')
373
+ })
374
+
375
+ it('should create delay queue', () => {
376
+ const queue = manager.createStandardQueue({
377
+ queueName: 'test',
378
+ })
379
+
380
+ const delay = manager.createDelayQueue({
381
+ queueUrl: queue.queueUrl,
382
+ defaultDelay: 60,
383
+ perMessageDelay: false,
384
+ maxDelay: 900,
385
+ })
386
+
387
+ expect(delay.defaultDelay).toBe(60)
388
+ })
389
+
390
+ it('should purge queue', async () => {
391
+ const queue = manager.createStandardQueue({
392
+ queueName: 'test',
393
+ })
394
+
395
+ const purgeOp = await manager.purgeQueue(queue.id)
396
+
397
+ expect(purgeOp.status).toBe('in_progress')
398
+
399
+ await new Promise(resolve => setTimeout(resolve, 150))
400
+
401
+ expect(purgeOp.status).toBe('completed')
402
+ })
403
+
404
+ it('should collect queue metrics', () => {
405
+ const queue = manager.createStandardQueue({
406
+ queueName: 'test',
407
+ })
408
+
409
+ const metrics = manager.collectQueueMetrics(queue.queueUrl)
410
+
411
+ expect(metrics.approximateNumberOfMessages).toBeGreaterThanOrEqual(0)
412
+ })
413
+
414
+ it('should get queue health', () => {
415
+ const queue = manager.createStandardQueue({
416
+ queueName: 'test',
417
+ })
418
+
419
+ manager.collectQueueMetrics(queue.queueUrl)
420
+
421
+ const health = manager.getQueueHealth(queue.queueUrl)
422
+
423
+ expect(['healthy', 'warning', 'critical']).toContain(health.status)
424
+ })
425
+
426
+ it('should use global instance', () => {
427
+ expect(queueManagementManager).toBeInstanceOf(QueueManagementManager)
428
+ })
429
+ })
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Resource Management - Tagging strategies, cost allocation, resource groups
3
+ */
4
+
5
+ export interface TaggingStrategy { id: string; tags: Record<string, string>; resources: string[] }
6
+ export interface CostAllocation { id: string; tagKey: string; allocations: Array<{ tagValue: string; cost: number }> }
7
+ export interface ResourceGroup { id: string; name: string; query: { resourceTypeFilters: string[]; tagFilters: Array<{ key: string; values: string[] }> } }
8
+
9
+ export class ResourceManagementManager {
10
+ private strategies = new Map<string, TaggingStrategy>()
11
+ private allocations = new Map<string, CostAllocation>()
12
+ private groups = new Map<string, ResourceGroup>()
13
+ private counter = 0
14
+
15
+ createTaggingStrategy(tags: Record<string, string>, resources: string[]): TaggingStrategy {
16
+ const id = `tagging-${Date.now()}-${this.counter++}`
17
+ const strategy = { id, tags, resources }
18
+ this.strategies.set(id, strategy)
19
+ return strategy
20
+ }
21
+
22
+ createCostAllocation(tagKey: string, allocations: Array<{ tagValue: string; cost: number }>): CostAllocation {
23
+ const id = `cost-${Date.now()}-${this.counter++}`
24
+ const allocation = { id, tagKey, allocations }
25
+ this.allocations.set(id, allocation)
26
+ return allocation
27
+ }
28
+
29
+ createResourceGroup(name: string, resourceTypeFilters: string[], tagFilters: Array<{ key: string; values: string[] }>): ResourceGroup {
30
+ const id = `group-${Date.now()}-${this.counter++}`
31
+ const group = { id, name, query: { resourceTypeFilters, tagFilters } }
32
+ this.groups.set(id, group)
33
+ return group
34
+ }
35
+
36
+ clear(): void { this.strategies.clear(); this.allocations.clear(); this.groups.clear() }
37
+ }
38
+
39
+ export const resourceManagementManager: ResourceManagementManager = new ResourceManagementManager()
@@ -0,0 +1,62 @@
1
+ import type { EnvironmentType } from '@stacksjs/ts-cloud-types'
2
+
3
+ export interface NamingOptions {
4
+ slug: string
5
+ environment: EnvironmentType
6
+ timestamp?: string
7
+ resourceType: string
8
+ suffix?: string
9
+ }
10
+
11
+ /**
12
+ * Generate a consistent resource name following the naming convention:
13
+ * {slug}-{environment}-{resourceType}-{timestamp}
14
+ */
15
+ export function generateResourceName(options: NamingOptions): string {
16
+ const { slug, environment, resourceType, timestamp, suffix } = options
17
+
18
+ const parts = [
19
+ slug,
20
+ environment,
21
+ resourceType,
22
+ ]
23
+
24
+ if (timestamp) {
25
+ parts.push(timestamp)
26
+ }
27
+
28
+ if (suffix) {
29
+ parts.push(suffix)
30
+ }
31
+
32
+ return parts.join('-')
33
+ }
34
+
35
+ /**
36
+ * Generate a logical ID for CloudFormation resources
37
+ * Converts to PascalCase and removes hyphens
38
+ */
39
+ export function generateLogicalId(name: string): string {
40
+ return name
41
+ .split('-')
42
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
43
+ .join('')
44
+ }
45
+
46
+ /**
47
+ * Get current timestamp for resource naming
48
+ */
49
+ export function getTimestamp(): string {
50
+ return Date.now().toString()
51
+ }
52
+
53
+ /**
54
+ * Sanitize a name to be CloudFormation-compatible
55
+ */
56
+ export function sanitizeName(name: string): string {
57
+ return name
58
+ .toLowerCase()
59
+ .replace(/[^a-z0-9-]/g, '-')
60
+ .replace(/^-+|-+$/g, '')
61
+ .replace(/-+/g, '-')
62
+ }