@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,281 @@
1
+ /**
2
+ * Email Threading and Conversation View
3
+ *
4
+ * Groups emails into conversations based on subject and references
5
+ */
6
+
7
+ export interface EmailThread {
8
+ threadId: string
9
+ subject: string
10
+ participants: string[]
11
+ messageCount: number
12
+ unreadCount: number
13
+ lastMessageDate: string
14
+ firstMessageDate: string
15
+ messages: ThreadMessage[]
16
+ labels?: string[]
17
+ isStarred?: boolean
18
+ }
19
+
20
+ export interface ThreadMessage {
21
+ messageId: string
22
+ from: string
23
+ fromName?: string
24
+ to: string[]
25
+ cc?: string[]
26
+ date: string
27
+ bodyPreview: string
28
+ isRead: boolean
29
+ hasAttachments: boolean
30
+ }
31
+
32
+ /**
33
+ * Email Threading Module
34
+ */
35
+ export class EmailThreading {
36
+ /**
37
+ * Lambda code for threading emails
38
+ */
39
+ static ThreadingLambdaCode = `
40
+ const { S3Client, GetObjectCommand, PutObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
41
+ const crypto = require('crypto');
42
+
43
+ const s3 = new S3Client({});
44
+ const EMAIL_BUCKET = process.env.EMAIL_BUCKET;
45
+
46
+ exports.handler = async (event) => {
47
+ console.log('Email threading event:', JSON.stringify(event, null, 2));
48
+
49
+ for (const record of event.Records) {
50
+ try {
51
+ const bucket = record.s3?.bucket?.name || EMAIL_BUCKET;
52
+ const key = decodeURIComponent(record.s3?.object?.key?.replace(/\\+/g, ' ') || '');
53
+
54
+ if (!key.endsWith('/metadata.json')) continue;
55
+
56
+ // Get email metadata
57
+ const result = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
58
+ const metadata = JSON.parse(await result.Body.transformToString());
59
+
60
+ // Extract mailbox path
61
+ const pathParts = key.split('/');
62
+ const domain = pathParts[1];
63
+ const localPart = pathParts[2];
64
+ const mailboxPath = \`mailboxes/\${domain}/\${localPart}\`;
65
+
66
+ // Generate thread ID from subject
67
+ const threadId = generateThreadId(metadata.subject, metadata.from, metadata.to);
68
+
69
+ // Update email metadata with thread ID
70
+ metadata.threadId = threadId;
71
+ await s3.send(new PutObjectCommand({
72
+ Bucket: bucket,
73
+ Key: key,
74
+ Body: JSON.stringify(metadata, null, 2),
75
+ ContentType: 'application/json',
76
+ }));
77
+
78
+ // Update thread index
79
+ await updateThreadIndex(bucket, mailboxPath, threadId, metadata);
80
+
81
+ console.log(\`Threaded email \${metadata.messageId} into thread \${threadId}\`);
82
+ } catch (error) {
83
+ console.error('Error threading email:', error);
84
+ }
85
+ }
86
+
87
+ return { statusCode: 200 };
88
+ };
89
+
90
+ function generateThreadId(subject, from, to) {
91
+ // Normalize subject (remove Re:, Fwd:, etc.)
92
+ const normalizedSubject = subject
93
+ .replace(/^(Re|Fwd|Fw|RE|FWD|FW):\\s*/gi, '')
94
+ .trim()
95
+ .toLowerCase();
96
+
97
+ // Create hash from normalized subject
98
+ const hash = crypto.createHash('md5')
99
+ .update(normalizedSubject)
100
+ .digest('hex')
101
+ .substring(0, 12);
102
+
103
+ return \`thread-\${hash}\`;
104
+ }
105
+
106
+ async function updateThreadIndex(bucket, mailboxPath, threadId, metadata) {
107
+ const threadsKey = \`\${mailboxPath}/threads.json\`;
108
+ let threads = {};
109
+
110
+ // Load existing threads
111
+ try {
112
+ const result = await s3.send(new GetObjectCommand({
113
+ Bucket: bucket,
114
+ Key: threadsKey,
115
+ }));
116
+ threads = JSON.parse(await result.Body.transformToString());
117
+ } catch {
118
+ // No threads file yet
119
+ }
120
+
121
+ // Get or create thread
122
+ if (!threads[threadId]) {
123
+ threads[threadId] = {
124
+ threadId,
125
+ subject: metadata.subject.replace(/^(Re|Fwd|Fw|RE|FWD|FW):\\s*/gi, '').trim(),
126
+ participants: [],
127
+ messageCount: 0,
128
+ unreadCount: 0,
129
+ messages: [],
130
+ firstMessageDate: metadata.date,
131
+ lastMessageDate: metadata.date,
132
+ };
133
+ }
134
+
135
+ const thread = threads[threadId];
136
+
137
+ // Add participant if not already in list
138
+ if (!thread.participants.includes(metadata.from)) {
139
+ thread.participants.push(metadata.from);
140
+ }
141
+
142
+ // Add message to thread
143
+ thread.messages.push({
144
+ messageId: metadata.messageId,
145
+ from: metadata.from,
146
+ fromName: metadata.fromName,
147
+ to: [metadata.to],
148
+ date: metadata.date,
149
+ bodyPreview: metadata.preview || '',
150
+ isRead: false,
151
+ hasAttachments: metadata.hasAttachments || false,
152
+ });
153
+
154
+ // Update counts
155
+ thread.messageCount = thread.messages.length;
156
+ thread.unreadCount = thread.messages.filter(m => !m.isRead).length;
157
+
158
+ // Update dates
159
+ if (new Date(metadata.date) > new Date(thread.lastMessageDate)) {
160
+ thread.lastMessageDate = metadata.date;
161
+ }
162
+ if (new Date(metadata.date) < new Date(thread.firstMessageDate)) {
163
+ thread.firstMessageDate = metadata.date;
164
+ }
165
+
166
+ // Sort messages by date
167
+ thread.messages.sort((a, b) => new Date(a.date) - new Date(b.date));
168
+
169
+ // Save threads
170
+ await s3.send(new PutObjectCommand({
171
+ Bucket: bucket,
172
+ Key: threadsKey,
173
+ Body: JSON.stringify(threads, null, 2),
174
+ ContentType: 'application/json',
175
+ }));
176
+ }
177
+ `
178
+
179
+ /**
180
+ * Create threading Lambda function
181
+ */
182
+ static createThreadingLambda(config: {
183
+ slug: string
184
+ roleArn: string
185
+ emailBucket: string
186
+ }): Record<string, any> {
187
+ return {
188
+ [`${config.slug}EmailThreadingLambda`]: {
189
+ Type: 'AWS::Lambda::Function',
190
+ Properties: {
191
+ FunctionName: `${config.slug}-email-threading`,
192
+ Runtime: 'nodejs20.x',
193
+ Handler: 'index.handler',
194
+ Role: config.roleArn,
195
+ Timeout: 60,
196
+ MemorySize: 256,
197
+ Code: {
198
+ ZipFile: EmailThreading.ThreadingLambdaCode,
199
+ },
200
+ Environment: {
201
+ Variables: {
202
+ EMAIL_BUCKET: config.emailBucket,
203
+ },
204
+ },
205
+ },
206
+ },
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Get threads for a mailbox (SDK helper)
212
+ */
213
+ static async getThreads(params: {
214
+ s3Client: any
215
+ bucket: string
216
+ mailbox: string
217
+ limit?: number
218
+ offset?: number
219
+ }): Promise<EmailThread[]> {
220
+ const { s3Client, bucket, mailbox, limit = 50, offset = 0 } = params
221
+
222
+ const [localPart, domain] = mailbox.includes('@')
223
+ ? mailbox.split('@')
224
+ : [mailbox, 'default']
225
+
226
+ const threadsKey = `mailboxes/${domain}/${localPart}/threads.json`
227
+
228
+ try {
229
+ const result = await s3Client.send({
230
+ Bucket: bucket,
231
+ Key: threadsKey,
232
+ })
233
+
234
+ const threads = JSON.parse(result.Body)
235
+ const threadList = Object.values(threads) as EmailThread[]
236
+
237
+ // Sort by last message date
238
+ threadList.sort((a, b) =>
239
+ new Date(b.lastMessageDate).getTime() - new Date(a.lastMessageDate).getTime()
240
+ )
241
+
242
+ return threadList.slice(offset, offset + limit)
243
+ }
244
+ catch {
245
+ return []
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Get a specific thread
251
+ */
252
+ static async getThread(params: {
253
+ s3Client: any
254
+ bucket: string
255
+ mailbox: string
256
+ threadId: string
257
+ }): Promise<EmailThread | null> {
258
+ const { s3Client, bucket, mailbox, threadId } = params
259
+
260
+ const [localPart, domain] = mailbox.includes('@')
261
+ ? mailbox.split('@')
262
+ : [mailbox, 'default']
263
+
264
+ const threadsKey = `mailboxes/${domain}/${localPart}/threads.json`
265
+
266
+ try {
267
+ const result = await s3Client.send({
268
+ Bucket: bucket,
269
+ Key: threadsKey,
270
+ })
271
+
272
+ const threads = JSON.parse(result.Body)
273
+ return threads[threadId] || null
274
+ }
275
+ catch {
276
+ return null
277
+ }
278
+ }
279
+ }
280
+
281
+ export default EmailThreading