@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,404 @@
1
+ /**
2
+ * Shared Mailboxes for Teams
3
+ *
4
+ * Provides shared mailbox functionality with team access
5
+ */
6
+
7
+ export interface SharedMailbox {
8
+ id: string
9
+ address: string
10
+ displayName: string
11
+ description?: string
12
+ members: MailboxMember[]
13
+ settings: MailboxSettings
14
+ createdAt: string
15
+ updatedAt: string
16
+ }
17
+
18
+ export interface MailboxMember {
19
+ userId: string
20
+ email: string
21
+ name?: string
22
+ role: 'owner' | 'admin' | 'member' | 'viewer'
23
+ permissions: MailboxPermissions
24
+ addedAt: string
25
+ addedBy: string
26
+ }
27
+
28
+ export interface MailboxPermissions {
29
+ read: boolean
30
+ send: boolean
31
+ delete: boolean
32
+ manage: boolean
33
+ assignTo: boolean
34
+ }
35
+
36
+ export interface MailboxSettings {
37
+ autoAssign: boolean
38
+ assignmentStrategy: 'round-robin' | 'least-busy' | 'manual'
39
+ notifyOnNew: boolean
40
+ notifyMembers: string[]
41
+ signature?: string
42
+ autoResponder?: {
43
+ enabled: boolean
44
+ subject: string
45
+ body: string
46
+ }
47
+ }
48
+
49
+ export interface MailboxAssignment {
50
+ messageId: string
51
+ assignedTo: string
52
+ assignedBy: string
53
+ assignedAt: string
54
+ status: 'open' | 'in-progress' | 'resolved' | 'closed'
55
+ notes?: string
56
+ }
57
+
58
+ /**
59
+ * Shared Mailboxes Module
60
+ */
61
+ export class SharedMailboxes {
62
+ /**
63
+ * Lambda code for shared mailbox management
64
+ */
65
+ static SharedMailboxLambdaCode = `
66
+ const { S3Client, GetObjectCommand, PutObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
67
+ const { DynamoDBClient, GetItemCommand, PutItemCommand, QueryCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
68
+
69
+ const s3 = new S3Client({});
70
+ const dynamodb = new DynamoDBClient({});
71
+ const EMAIL_BUCKET = process.env.EMAIL_BUCKET;
72
+ const MAILBOX_TABLE = process.env.MAILBOX_TABLE;
73
+
74
+ exports.handler = async (event) => {
75
+ console.log('Shared mailbox event:', JSON.stringify(event, null, 2));
76
+
77
+ const { httpMethod, path, body, pathParameters } = event;
78
+ const mailboxId = pathParameters?.mailboxId;
79
+
80
+ try {
81
+ switch (\`\${httpMethod} \${path.split('/')[1]}\`) {
82
+ case 'GET mailboxes':
83
+ return await listMailboxes();
84
+ case 'GET mailbox':
85
+ return await getMailbox(mailboxId);
86
+ case 'POST mailboxes':
87
+ return await createMailbox(JSON.parse(body));
88
+ case 'PUT mailbox':
89
+ return await updateMailbox(mailboxId, JSON.parse(body));
90
+ case 'DELETE mailbox':
91
+ return await deleteMailbox(mailboxId);
92
+ case 'POST assign':
93
+ return await assignMessage(mailboxId, JSON.parse(body));
94
+ case 'GET messages':
95
+ return await getMailboxMessages(mailboxId, event.queryStringParameters);
96
+ default:
97
+ return { statusCode: 404, body: JSON.stringify({ error: 'Not found' }) };
98
+ }
99
+ } catch (error) {
100
+ console.error('Error:', error);
101
+ return { statusCode: 500, body: JSON.stringify({ error: error.message }) };
102
+ }
103
+ };
104
+
105
+ async function listMailboxes() {
106
+ const result = await dynamodb.send(new QueryCommand({
107
+ TableName: MAILBOX_TABLE,
108
+ IndexName: 'type-index',
109
+ KeyConditionExpression: '#type = :type',
110
+ ExpressionAttributeNames: { '#type': 'type' },
111
+ ExpressionAttributeValues: { ':type': { S: 'mailbox' } },
112
+ }));
113
+
114
+ const mailboxes = result.Items?.map(item => ({
115
+ id: item.id.S,
116
+ address: item.address.S,
117
+ displayName: item.displayName.S,
118
+ memberCount: item.memberCount?.N || 0,
119
+ })) || [];
120
+
121
+ return {
122
+ statusCode: 200,
123
+ body: JSON.stringify(mailboxes),
124
+ };
125
+ }
126
+
127
+ async function getMailbox(mailboxId) {
128
+ const result = await dynamodb.send(new GetItemCommand({
129
+ TableName: MAILBOX_TABLE,
130
+ Key: { id: { S: mailboxId } },
131
+ }));
132
+
133
+ if (!result.Item) {
134
+ return { statusCode: 404, body: JSON.stringify({ error: 'Mailbox not found' }) };
135
+ }
136
+
137
+ return {
138
+ statusCode: 200,
139
+ body: JSON.stringify(unmarshallMailbox(result.Item)),
140
+ };
141
+ }
142
+
143
+ async function createMailbox(data) {
144
+ const id = \`mb-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`;
145
+ const now = new Date().toISOString();
146
+
147
+ const mailbox = {
148
+ id: { S: id },
149
+ type: { S: 'mailbox' },
150
+ address: { S: data.address },
151
+ displayName: { S: data.displayName },
152
+ description: { S: data.description || '' },
153
+ members: { S: JSON.stringify(data.members || []) },
154
+ settings: { S: JSON.stringify(data.settings || {}) },
155
+ memberCount: { N: String((data.members || []).length) },
156
+ createdAt: { S: now },
157
+ updatedAt: { S: now },
158
+ };
159
+
160
+ await dynamodb.send(new PutItemCommand({
161
+ TableName: MAILBOX_TABLE,
162
+ Item: mailbox,
163
+ }));
164
+
165
+ return {
166
+ statusCode: 201,
167
+ body: JSON.stringify({ id, ...data, createdAt: now }),
168
+ };
169
+ }
170
+
171
+ async function updateMailbox(mailboxId, data) {
172
+ const now = new Date().toISOString();
173
+
174
+ await dynamodb.send(new UpdateItemCommand({
175
+ TableName: MAILBOX_TABLE,
176
+ Key: { id: { S: mailboxId } },
177
+ UpdateExpression: 'SET displayName = :name, description = :desc, members = :members, settings = :settings, memberCount = :count, updatedAt = :now',
178
+ ExpressionAttributeValues: {
179
+ ':name': { S: data.displayName },
180
+ ':desc': { S: data.description || '' },
181
+ ':members': { S: JSON.stringify(data.members || []) },
182
+ ':settings': { S: JSON.stringify(data.settings || {}) },
183
+ ':count': { N: String((data.members || []).length) },
184
+ ':now': { S: now },
185
+ },
186
+ }));
187
+
188
+ return {
189
+ statusCode: 200,
190
+ body: JSON.stringify({ id: mailboxId, ...data, updatedAt: now }),
191
+ };
192
+ }
193
+
194
+ async function deleteMailbox(mailboxId) {
195
+ await dynamodb.send(new DeleteItemCommand({
196
+ TableName: MAILBOX_TABLE,
197
+ Key: { id: { S: mailboxId } },
198
+ }));
199
+
200
+ return { statusCode: 204, body: '' };
201
+ }
202
+
203
+ async function assignMessage(mailboxId, data) {
204
+ const { messageId, assignedTo, assignedBy, notes } = data;
205
+ const now = new Date().toISOString();
206
+
207
+ await dynamodb.send(new PutItemCommand({
208
+ TableName: MAILBOX_TABLE,
209
+ Item: {
210
+ id: { S: \`assign-\${messageId}\` },
211
+ type: { S: 'assignment' },
212
+ mailboxId: { S: mailboxId },
213
+ messageId: { S: messageId },
214
+ assignedTo: { S: assignedTo },
215
+ assignedBy: { S: assignedBy },
216
+ assignedAt: { S: now },
217
+ status: { S: 'open' },
218
+ notes: { S: notes || '' },
219
+ },
220
+ }));
221
+
222
+ return {
223
+ statusCode: 200,
224
+ body: JSON.stringify({ messageId, assignedTo, status: 'open' }),
225
+ };
226
+ }
227
+
228
+ async function getMailboxMessages(mailboxId, queryParams) {
229
+ const mailbox = await getMailbox(mailboxId);
230
+ if (mailbox.statusCode !== 200) return mailbox;
231
+
232
+ const mailboxData = JSON.parse(mailbox.body);
233
+ const [localPart, domain] = mailboxData.address.split('@');
234
+
235
+ // Get inbox from S3
236
+ const inboxKey = \`mailboxes/\${domain}/\${localPart}/inbox.json\`;
237
+ try {
238
+ const result = await s3.send(new GetObjectCommand({
239
+ Bucket: EMAIL_BUCKET,
240
+ Key: inboxKey,
241
+ }));
242
+
243
+ const inbox = JSON.parse(await result.Body.transformToString());
244
+
245
+ // Get assignments
246
+ const assignmentResult = await dynamodb.send(new QueryCommand({
247
+ TableName: MAILBOX_TABLE,
248
+ IndexName: 'mailbox-index',
249
+ KeyConditionExpression: 'mailboxId = :mailboxId AND begins_with(id, :prefix)',
250
+ ExpressionAttributeValues: {
251
+ ':mailboxId': { S: mailboxId },
252
+ ':prefix': { S: 'assign-' },
253
+ },
254
+ }));
255
+
256
+ const assignments = {};
257
+ for (const item of assignmentResult.Items || []) {
258
+ assignments[item.messageId.S] = {
259
+ assignedTo: item.assignedTo.S,
260
+ status: item.status.S,
261
+ };
262
+ }
263
+
264
+ // Merge assignments with inbox
265
+ const messages = inbox.map(msg => ({
266
+ ...msg,
267
+ assignment: assignments[msg.messageId] || null,
268
+ }));
269
+
270
+ return {
271
+ statusCode: 200,
272
+ body: JSON.stringify(messages),
273
+ };
274
+ } catch (error) {
275
+ if (error.name === 'NoSuchKey') {
276
+ return { statusCode: 200, body: JSON.stringify([]) };
277
+ }
278
+ throw error;
279
+ }
280
+ }
281
+
282
+ function unmarshallMailbox(item) {
283
+ return {
284
+ id: item.id.S,
285
+ address: item.address.S,
286
+ displayName: item.displayName.S,
287
+ description: item.description?.S,
288
+ members: JSON.parse(item.members?.S || '[]'),
289
+ settings: JSON.parse(item.settings?.S || '{}'),
290
+ createdAt: item.createdAt.S,
291
+ updatedAt: item.updatedAt.S,
292
+ };
293
+ }
294
+ `
295
+
296
+ /**
297
+ * Create shared mailbox DynamoDB table
298
+ */
299
+ static createMailboxTable(config: { slug: string }): Record<string, any> {
300
+ return {
301
+ [`${config.slug}SharedMailboxTable`]: {
302
+ Type: 'AWS::DynamoDB::Table',
303
+ Properties: {
304
+ TableName: `${config.slug}-shared-mailboxes`,
305
+ BillingMode: 'PAY_PER_REQUEST',
306
+ AttributeDefinitions: [
307
+ { AttributeName: 'id', AttributeType: 'S' },
308
+ { AttributeName: 'type', AttributeType: 'S' },
309
+ { AttributeName: 'mailboxId', AttributeType: 'S' },
310
+ ],
311
+ KeySchema: [
312
+ { AttributeName: 'id', KeyType: 'HASH' },
313
+ ],
314
+ GlobalSecondaryIndexes: [
315
+ {
316
+ IndexName: 'type-index',
317
+ KeySchema: [
318
+ { AttributeName: 'type', KeyType: 'HASH' },
319
+ ],
320
+ Projection: { ProjectionType: 'ALL' },
321
+ },
322
+ {
323
+ IndexName: 'mailbox-index',
324
+ KeySchema: [
325
+ { AttributeName: 'mailboxId', KeyType: 'HASH' },
326
+ { AttributeName: 'id', KeyType: 'RANGE' },
327
+ ],
328
+ Projection: { ProjectionType: 'ALL' },
329
+ },
330
+ ],
331
+ },
332
+ },
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Create shared mailbox Lambda
338
+ */
339
+ static createSharedMailboxLambda(config: {
340
+ slug: string
341
+ roleArn: string
342
+ emailBucket: string
343
+ mailboxTable: string
344
+ }): Record<string, any> {
345
+ return {
346
+ [`${config.slug}SharedMailboxLambda`]: {
347
+ Type: 'AWS::Lambda::Function',
348
+ Properties: {
349
+ FunctionName: `${config.slug}-shared-mailbox`,
350
+ Runtime: 'nodejs20.x',
351
+ Handler: 'index.handler',
352
+ Role: config.roleArn,
353
+ Timeout: 30,
354
+ MemorySize: 256,
355
+ Code: {
356
+ ZipFile: SharedMailboxes.SharedMailboxLambdaCode,
357
+ },
358
+ Environment: {
359
+ Variables: {
360
+ EMAIL_BUCKET: config.emailBucket,
361
+ MAILBOX_TABLE: config.mailboxTable,
362
+ },
363
+ },
364
+ },
365
+ },
366
+ }
367
+ }
368
+
369
+ /**
370
+ * Default permission sets
371
+ */
372
+ static readonly PermissionSets = {
373
+ owner: {
374
+ read: true,
375
+ send: true,
376
+ delete: true,
377
+ manage: true,
378
+ assignTo: true,
379
+ },
380
+ admin: {
381
+ read: true,
382
+ send: true,
383
+ delete: true,
384
+ manage: true,
385
+ assignTo: true,
386
+ },
387
+ member: {
388
+ read: true,
389
+ send: true,
390
+ delete: false,
391
+ manage: false,
392
+ assignTo: true,
393
+ },
394
+ viewer: {
395
+ read: true,
396
+ send: false,
397
+ delete: false,
398
+ manage: false,
399
+ assignTo: false,
400
+ },
401
+ } as const
402
+ }
403
+
404
+ export default SharedMailboxes