@remit/imap-worker 0.0.89 → 0.0.91

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 (171) hide show
  1. package/dist/account-check.d.ts +27 -0
  2. package/dist/account-check.js +70 -0
  3. package/dist/body-sync-gate.d.ts +12 -0
  4. package/dist/body-sync-gate.js +53 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +193 -0
  7. package/dist/config-env.d.ts +5 -0
  8. package/dist/config-env.js +37 -0
  9. package/dist/connection-pool.d.ts +22 -0
  10. package/dist/connection-pool.js +97 -0
  11. package/dist/connection-scope.d.ts +8 -0
  12. package/dist/connection-scope.js +10 -0
  13. package/dist/context.d.ts +46 -0
  14. package/dist/context.js +15 -0
  15. package/dist/e2e-processor-shim.d.ts +2 -0
  16. package/dist/e2e-processor-shim.js +181 -0
  17. package/dist/emit.d.ts +15 -0
  18. package/dist/emit.js +76 -0
  19. package/dist/events.d.ts +203 -0
  20. package/dist/events.js +1 -0
  21. package/dist/failure-kind.d.ts +10 -0
  22. package/{src/failure-kind.ts → dist/failure-kind.js} +6 -6
  23. package/dist/handlers/append-sent-message.d.ts +3 -0
  24. package/dist/handlers/append-sent-message.js +152 -0
  25. package/dist/handlers/delete-account-objects.d.ts +3 -0
  26. package/dist/handlers/delete-account-objects.js +35 -0
  27. package/dist/handlers/empty-trash.d.ts +14 -0
  28. package/dist/handlers/empty-trash.js +217 -0
  29. package/dist/handlers/flag-push.d.ts +38 -0
  30. package/dist/handlers/flag-push.js +195 -0
  31. package/dist/handlers/imported-folder.d.ts +4 -0
  32. package/dist/handlers/imported-folder.js +23 -0
  33. package/dist/handlers/mailbox-management.d.ts +6 -0
  34. package/dist/handlers/mailbox-management.js +294 -0
  35. package/dist/handlers/mailbox-sync-order.d.ts +21 -0
  36. package/dist/handlers/mailbox-sync-order.js +50 -0
  37. package/dist/handlers/message-copy.d.ts +40 -0
  38. package/dist/handlers/message-copy.js +371 -0
  39. package/dist/handlers/message-delete-terminal.d.ts +60 -0
  40. package/dist/handlers/message-delete-terminal.js +77 -0
  41. package/dist/handlers/message-delete.d.ts +57 -0
  42. package/dist/handlers/message-delete.js +520 -0
  43. package/{src/handlers/message-move-terminal.ts → dist/handlers/message-move-terminal.d.ts} +18 -105
  44. package/dist/handlers/message-move-terminal.js +94 -0
  45. package/dist/handlers/message-move.d.ts +146 -0
  46. package/dist/handlers/message-move.js +490 -0
  47. package/dist/handlers/placement-move-push.d.ts +62 -0
  48. package/dist/handlers/placement-move-push.js +307 -0
  49. package/dist/handlers/probe-message-id.d.ts +2 -0
  50. package/dist/handlers/probe-message-id.js +6 -0
  51. package/dist/handlers/sync-mailboxes.d.ts +45 -0
  52. package/dist/handlers/sync-mailboxes.js +233 -0
  53. package/dist/handlers/sync-message-body.d.ts +23 -0
  54. package/dist/handlers/sync-message-body.js +182 -0
  55. package/dist/handlers/sync-messages.d.ts +29 -0
  56. package/dist/handlers/sync-messages.js +285 -0
  57. package/dist/index.d.ts +9 -0
  58. package/dist/index.js +67 -0
  59. package/dist/lambda-context.d.ts +8 -0
  60. package/dist/lambda-context.js +33 -0
  61. package/dist/mailbox-row.d.ts +9 -0
  62. package/dist/mailbox-row.js +6 -0
  63. package/dist/poller.d.ts +1 -0
  64. package/dist/poller.js +51 -0
  65. package/dist/process.d.ts +6 -0
  66. package/dist/process.js +3 -0
  67. package/dist/processor.d.ts +3 -0
  68. package/dist/processor.js +44 -0
  69. package/dist/queues.d.ts +10 -0
  70. package/dist/queues.js +1 -0
  71. package/dist/s3-account-objects.d.ts +3 -0
  72. package/dist/s3-account-objects.js +26 -0
  73. package/dist/scheduler/attachment-sweep.d.ts +11 -0
  74. package/dist/scheduler/attachment-sweep.js +23 -0
  75. package/dist/scheduler/calendar-subscriptions.d.ts +26 -0
  76. package/dist/scheduler/calendar-subscriptions.js +35 -0
  77. package/dist/scheduler/config.d.ts +27 -0
  78. package/{src/scheduler/config.ts → dist/scheduler/config.js} +7 -26
  79. package/{src/scheduler/decide-due.ts → dist/scheduler/decide-due.d.ts} +3 -12
  80. package/dist/scheduler/decide-due.js +17 -0
  81. package/dist/scheduler/handler.d.ts +21 -0
  82. package/{src/scheduler/handler.ts → dist/scheduler/handler.js} +24 -36
  83. package/{src/scheduler/loop.ts → dist/scheduler/loop.d.ts} +7 -23
  84. package/dist/scheduler/loop.js +8 -0
  85. package/dist/scheduler/run-tick.d.ts +62 -0
  86. package/dist/scheduler/run-tick.js +164 -0
  87. package/dist/scheduler/runner.d.ts +2 -0
  88. package/{src/scheduler/runner.ts → dist/scheduler/runner.js} +58 -84
  89. package/dist/scheduler/stranded-placement-redrive.d.ts +16 -0
  90. package/dist/scheduler/stranded-placement-redrive.js +172 -0
  91. package/dist/sqs-queues.d.ts +4 -0
  92. package/dist/sqs-queues.js +22 -0
  93. package/dist/with-oauth-lifecycle-deps.d.ts +5 -0
  94. package/dist/with-oauth-lifecycle-deps.js +17 -0
  95. package/dist/with-oauth-lifecycle.d.ts +56 -0
  96. package/dist/with-oauth-lifecycle.js +92 -0
  97. package/{src/worker-version.ts → dist/worker-version.d.ts} +1 -2
  98. package/dist/worker-version.js +12 -0
  99. package/package.json +75 -69
  100. package/src/account-check.test.ts +0 -149
  101. package/src/account-check.ts +0 -101
  102. package/src/body-sync-gate.test.ts +0 -185
  103. package/src/body-sync-gate.ts +0 -86
  104. package/src/cli.ts +0 -224
  105. package/src/connection-scope.test.ts +0 -266
  106. package/src/connection-scope.ts +0 -314
  107. package/src/credential-less-sync-fence.test.ts +0 -152
  108. package/src/e2e-processor-shim.ts +0 -232
  109. package/src/emit.test.ts +0 -127
  110. package/src/emit.ts +0 -117
  111. package/src/events.ts +0 -252
  112. package/src/failure-kind.test.ts +0 -42
  113. package/src/handlers/append-sent-message.sqlite.test.ts +0 -176
  114. package/src/handlers/append-sent-message.ts +0 -264
  115. package/src/handlers/delete-account-objects.test.ts +0 -128
  116. package/src/handlers/delete-account-objects.ts +0 -94
  117. package/src/handlers/empty-trash.sqlite.test.ts +0 -209
  118. package/src/handlers/empty-trash.ts +0 -352
  119. package/src/handlers/flag-push.ts +0 -285
  120. package/src/handlers/imported-folder.test.ts +0 -63
  121. package/src/handlers/imported-folder.ts +0 -38
  122. package/src/handlers/mailbox-management.sqlite.test.ts +0 -265
  123. package/src/handlers/mailbox-management.ts +0 -486
  124. package/src/handlers/mailbox-sync-order.test.ts +0 -93
  125. package/src/handlers/mailbox-sync-order.ts +0 -65
  126. package/src/handlers/message-copy.sqlite.test.ts +0 -298
  127. package/src/handlers/message-copy.ts +0 -566
  128. package/src/handlers/message-delete-terminal.ts +0 -147
  129. package/src/handlers/message-delete.sqlite.test.ts +0 -291
  130. package/src/handlers/message-delete.ts +0 -885
  131. package/src/handlers/message-move.sqlite.test.ts +0 -271
  132. package/src/handlers/message-move.test.ts +0 -216
  133. package/src/handlers/message-move.ts +0 -752
  134. package/src/handlers/placement-move-push.test.ts +0 -137
  135. package/src/handlers/placement-move-push.ts +0 -475
  136. package/src/handlers/placement-push.sqlite.test.ts +0 -298
  137. package/src/handlers/probe-message-id.sqlite.test.ts +0 -192
  138. package/src/handlers/probe-message-id.ts +0 -15
  139. package/src/handlers/sync-mailboxes.test.ts +0 -183
  140. package/src/handlers/sync-mailboxes.ts +0 -421
  141. package/src/handlers/sync-message-body.sqlite.test.ts +0 -314
  142. package/src/handlers/sync-message-body.test.ts +0 -150
  143. package/src/handlers/sync-message-body.ts +0 -365
  144. package/src/handlers/sync-messages.sqlite.test.ts +0 -183
  145. package/src/handlers/sync-messages.ts +0 -525
  146. package/src/index.test.ts +0 -22
  147. package/src/index.ts +0 -86
  148. package/src/mail-sync-selection.sqlite.test.ts +0 -234
  149. package/src/mailbox-row.ts +0 -20
  150. package/src/pending-sync.sqlite.test.ts +0 -166
  151. package/src/poller.ts +0 -55
  152. package/src/processor.ts +0 -60
  153. package/src/queues.ts +0 -49
  154. package/src/scheduler/attachment-sweep.sqlite.test.ts +0 -75
  155. package/src/scheduler/attachment-sweep.ts +0 -46
  156. package/src/scheduler/calendar-subscriptions.sqlite.test.ts +0 -147
  157. package/src/scheduler/calendar-subscriptions.ts +0 -103
  158. package/src/scheduler/config.test.ts +0 -40
  159. package/src/scheduler/decide-due.test.ts +0 -44
  160. package/src/scheduler/half-deleted-accounts.sqlite.test.ts +0 -196
  161. package/src/scheduler/loop.test.ts +0 -143
  162. package/src/scheduler/run-tick.sqlite.test.ts +0 -191
  163. package/src/scheduler/run-tick.ts +0 -281
  164. package/src/scheduler/stranded-placement-redrive.ts +0 -265
  165. package/src/stranded-placement.sqlite.test.ts +0 -794
  166. package/src/test-helpers/test-world.ts +0 -427
  167. package/src/thread-join.sqlite.test.ts +0 -106
  168. package/src/with-oauth-lifecycle-deps.sqlite.test.ts +0 -269
  169. package/src/with-oauth-lifecycle-deps.ts +0 -71
  170. package/src/with-oauth-lifecycle.ts +0 -158
  171. package/tsconfig.json +0 -8
@@ -1,185 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { afterEach, beforeEach, describe, it } from "node:test";
3
- import {
4
- GetParameterCommand,
5
- ParameterNotFound,
6
- SSMClient,
7
- } from "@aws-sdk/client-ssm";
8
- import type { Logger } from "@remit/logger";
9
- import { mockClient } from "aws-sdk-client-mock";
10
- import { isBodySyncEnabled, resetBodySyncGateCache } from "./body-sync-gate.js";
11
-
12
- const parameterName = "/dev/Remit/bodySyncEnabled";
13
-
14
- interface CapturedWarn {
15
- args: unknown[];
16
- }
17
-
18
- const createCapturingLogger = (): {
19
- log: Logger;
20
- warnCalls: CapturedWarn[];
21
- } => {
22
- const warnCalls: CapturedWarn[] = [];
23
- const noop = () => {};
24
- const log = {
25
- info: noop,
26
- warn: (...args: unknown[]) => warnCalls.push({ args }),
27
- error: noop,
28
- debug: noop,
29
- fatal: noop,
30
- trace: noop,
31
- child: () => log,
32
- } as unknown as Logger;
33
- return { log, warnCalls };
34
- };
35
-
36
- const warnMessage = (warn: CapturedWarn): string => String(warn.args[1]);
37
-
38
- describe("isBodySyncEnabled", () => {
39
- beforeEach(() => {
40
- resetBodySyncGateCache();
41
- });
42
-
43
- afterEach(() => {
44
- mockClient(SSMClient).reset();
45
- resetBodySyncGateCache();
46
- });
47
-
48
- it("returns true when the parameter is 'true'", async () => {
49
- const ssmMock = mockClient(SSMClient);
50
- ssmMock
51
- .on(GetParameterCommand, { Name: parameterName })
52
- .resolves({ Parameter: { Value: "true" } });
53
- const { log } = createCapturingLogger();
54
-
55
- const enabled = await isBodySyncEnabled(
56
- parameterName,
57
- log,
58
- ssmMock as unknown as SSMClient,
59
- );
60
-
61
- assert.equal(enabled, true);
62
- });
63
-
64
- it("returns false when the parameter is 'false'", async () => {
65
- const ssmMock = mockClient(SSMClient);
66
- ssmMock
67
- .on(GetParameterCommand, { Name: parameterName })
68
- .resolves({ Parameter: { Value: "false" } });
69
- const { log } = createCapturingLogger();
70
-
71
- const enabled = await isBodySyncEnabled(
72
- parameterName,
73
- log,
74
- ssmMock as unknown as SSMClient,
75
- );
76
-
77
- assert.equal(enabled, false);
78
- });
79
-
80
- it("treats casing and whitespace as disabled for ' FALSE '", async () => {
81
- const ssmMock = mockClient(SSMClient);
82
- ssmMock
83
- .on(GetParameterCommand, { Name: parameterName })
84
- .resolves({ Parameter: { Value: " FALSE " } });
85
- const { log } = createCapturingLogger();
86
-
87
- const enabled = await isBodySyncEnabled(
88
- parameterName,
89
- log,
90
- ssmMock as unknown as SSMClient,
91
- );
92
-
93
- assert.equal(enabled, false);
94
- });
95
-
96
- it("fails open with a warning when the parameter does not exist", async () => {
97
- const ssmMock = mockClient(SSMClient);
98
- ssmMock
99
- .on(GetParameterCommand, { Name: parameterName })
100
- .rejects(new ParameterNotFound({ message: "not found", $metadata: {} }));
101
- const { log, warnCalls } = createCapturingLogger();
102
-
103
- const enabled = await isBodySyncEnabled(
104
- parameterName,
105
- log,
106
- ssmMock as unknown as SSMClient,
107
- );
108
-
109
- assert.equal(enabled, true);
110
- assert.equal(warnCalls.length, 1);
111
- assert.match(warnMessage(warnCalls[0]), /failing open/i);
112
- });
113
-
114
- it("fails open with a warning when the parameter has no value", async () => {
115
- const ssmMock = mockClient(SSMClient);
116
- ssmMock
117
- .on(GetParameterCommand, { Name: parameterName })
118
- .resolves({ Parameter: {} });
119
- const { log, warnCalls } = createCapturingLogger();
120
-
121
- const enabled = await isBodySyncEnabled(
122
- parameterName,
123
- log,
124
- ssmMock as unknown as SSMClient,
125
- );
126
-
127
- assert.equal(enabled, true);
128
- assert.equal(warnCalls.length, 1);
129
- assert.match(warnMessage(warnCalls[0]), /missing a value/i);
130
- });
131
-
132
- it("caches the result within the TTL — second call does not re-fetch", async () => {
133
- const ssmMock = mockClient(SSMClient);
134
- ssmMock
135
- .on(GetParameterCommand, { Name: parameterName })
136
- .resolves({ Parameter: { Value: "false" } });
137
- const { log } = createCapturingLogger();
138
-
139
- const first = await isBodySyncEnabled(
140
- parameterName,
141
- log,
142
- ssmMock as unknown as SSMClient,
143
- );
144
- const second = await isBodySyncEnabled(
145
- parameterName,
146
- log,
147
- ssmMock as unknown as SSMClient,
148
- );
149
-
150
- assert.equal(first, false);
151
- assert.equal(second, false);
152
- assert.equal(ssmMock.commandCalls(GetParameterCommand).length, 1);
153
- });
154
-
155
- it("coalesces concurrent cold-cache calls into a single GetParameter", async () => {
156
- const ssmMock = mockClient(SSMClient);
157
- let resolveSend:
158
- | ((value: { Parameter: { Value: string } }) => void)
159
- | undefined;
160
- ssmMock.on(GetParameterCommand, { Name: parameterName }).callsFake(
161
- () =>
162
- new Promise((resolve) => {
163
- resolveSend = resolve;
164
- }),
165
- );
166
- const { log } = createCapturingLogger();
167
-
168
- const a = isBodySyncEnabled(
169
- parameterName,
170
- log,
171
- ssmMock as unknown as SSMClient,
172
- );
173
- const b = isBodySyncEnabled(
174
- parameterName,
175
- log,
176
- ssmMock as unknown as SSMClient,
177
- );
178
-
179
- assert.ok(resolveSend, "GetParameter should have been invoked");
180
- resolveSend?.({ Parameter: { Value: "true" } });
181
-
182
- assert.deepEqual(await Promise.all([a, b]), [true, true]);
183
- assert.equal(ssmMock.commandCalls(GetParameterCommand).length, 1);
184
- });
185
- });
@@ -1,86 +0,0 @@
1
- import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
2
- import type { Logger } from "@remit/logger";
3
-
4
- const CACHE_TTL_MS = 30_000;
5
-
6
- interface CacheEntry {
7
- readonly enabled: boolean;
8
- readonly expiresAt: number;
9
- }
10
-
11
- let cache: CacheEntry | undefined;
12
- let inFlight: Promise<boolean> | undefined;
13
- let defaultClient: SSMClient | undefined;
14
-
15
- const getDefaultClient = (): SSMClient => {
16
- if (!defaultClient) {
17
- defaultClient = new SSMClient({});
18
- }
19
- return defaultClient;
20
- };
21
-
22
- /**
23
- * Test seam — clears the module-scope TTL cache between unit tests.
24
- */
25
- export const resetBodySyncGateCache = (): void => {
26
- cache = undefined;
27
- inFlight = undefined;
28
- };
29
-
30
- const readParameter = async (
31
- ssm: SSMClient,
32
- parameterName: string,
33
- log: Logger,
34
- ): Promise<boolean> => {
35
- const result = await ssm.send(
36
- new GetParameterCommand({ Name: parameterName }),
37
- );
38
- const value = result.Parameter?.Value;
39
-
40
- if (value === undefined) {
41
- log.warn(
42
- { parameterName },
43
- "Body-sync toggle parameter missing a value, failing open (enabled)",
44
- );
45
- return true;
46
- }
47
-
48
- return value.trim().toLowerCase() !== "false";
49
- };
50
-
51
- /**
52
- * Reads the `/{stage}/Remit/bodySyncEnabled` SSM parameter, cached at module
53
- * scope for a short TTL. Returns `true` (enabled) when the parameter is absent
54
- * or unreadable — body sync fails open so a missing toggle never halts prod.
55
- */
56
- export const isBodySyncEnabled = async (
57
- parameterName: string,
58
- log: Logger,
59
- ssm: SSMClient = getDefaultClient(),
60
- ): Promise<boolean> => {
61
- if (cache && cache.expiresAt > Date.now()) {
62
- return cache.enabled;
63
- }
64
-
65
- if (inFlight) {
66
- return inFlight;
67
- }
68
-
69
- inFlight = readParameter(ssm, parameterName, log)
70
- .catch((error) => {
71
- log.warn(
72
- { parameterName, error },
73
- "Failed to read body-sync toggle parameter, failing open (enabled)",
74
- );
75
- return true;
76
- })
77
- .then((enabled) => {
78
- cache = { enabled, expiresAt: Date.now() + CACHE_TTL_MS };
79
- return enabled;
80
- })
81
- .finally(() => {
82
- inFlight = undefined;
83
- });
84
-
85
- return inFlight;
86
- };
package/src/cli.ts DELETED
@@ -1,224 +0,0 @@
1
- #!/usr/bin/env node
2
- // Plain text on purpose, and the one deliberate exception to the log field
3
- // contract in deploy/vps/README.md ("Logs"). That contract covers what a
4
- // container's log driver ships; this file is the `remit-worker` bin, run by hand
5
- // against a terminal, and is not an entrypoint of any image (see the target list
6
- // in npm-scripts/docker-bundle.mjs). Do not route it through the logger — usage
7
- // text and argument errors are for the person who typed the command.
8
- import { parseArgs } from "node:util";
9
- import { emitEvent } from "./emit.js";
10
- import {
11
- setWorkerQueues,
12
- sqsWorkerQueues,
13
- workerQueueUrlsFromEnv,
14
- } from "./queues.js";
15
-
16
- const HELP = `
17
- remit-imap-worker - Process IMAP sync events
18
-
19
- USAGE:
20
- remit-worker -t <type> -a <accountId> [options]
21
-
22
- OPTIONS:
23
- -t, --type <type> Event type (required)
24
- -a, --accountId <id> Account ID (required)
25
- -m, --mailboxId <id> Mailbox ID (required for some event types)
26
- --messageIds <ids> Comma-separated message IDs (required for SYNC_MESSAGE_BODY)
27
- --fullSync Force full sync, ignoring lastSyncUid (SYNC_MESSAGES only)
28
- --path <path> Mailbox path (required for MAILBOX_CREATE, MAILBOX_DELETE)
29
- --oldPath <path> Old mailbox path (required for MAILBOX_RENAME)
30
- --newPath <path> New mailbox path (required for MAILBOX_RENAME)
31
- --subscribe Subscribe to mailbox after creation (MAILBOX_CREATE only)
32
- -h, --help Show this help message
33
-
34
- EVENT TYPES:
35
- SYNC_MAILBOXES Sync all mailboxes for an account
36
- SYNC_MESSAGES Sync messages in a specific mailbox
37
- SYNC_MESSAGE_BODY Fetch and store message bodies in batch
38
- MAILBOX_CREATE Create a new mailbox
39
- MAILBOX_RENAME Rename a mailbox
40
- MAILBOX_DELETE Delete a mailbox
41
-
42
- EXAMPLES:
43
- # Sync all mailboxes for an account
44
- remit-worker -t SYNC_MAILBOXES -a account-123
45
-
46
- # Sync messages in a mailbox
47
- remit-worker -t SYNC_MESSAGES -a account-123 -m mailbox-456
48
-
49
- # Force a full sync of messages (ignore lastSyncUid)
50
- remit-worker -t SYNC_MESSAGES -a account-123 -m mailbox-456 --fullSync
51
-
52
- # Sync message bodies for specific messages
53
- remit-worker -t SYNC_MESSAGE_BODY -a account-123 -m mailbox-456 --messageIds id1,id2,id3
54
-
55
- # Create a new mailbox
56
- remit-worker -t MAILBOX_CREATE -a account-123 -m mailbox-id --path Work/Projects --subscribe
57
-
58
- # Rename a mailbox
59
- remit-worker -t MAILBOX_RENAME -a account-123 -m mailbox-id --oldPath Work/Projects --newPath Archive/Projects
60
-
61
- # Delete a mailbox
62
- remit-worker -t MAILBOX_DELETE -a account-123 -m mailbox-id --path Work/Projects
63
- `;
64
-
65
- const { values } = parseArgs({
66
- options: {
67
- type: { type: "string", short: "t" },
68
- accountId: { type: "string", short: "a" },
69
- mailboxId: { type: "string", short: "m" },
70
- messageIds: { type: "string" },
71
- fullSync: { type: "boolean", default: false },
72
- path: { type: "string" },
73
- oldPath: { type: "string" },
74
- newPath: { type: "string" },
75
- subscribe: { type: "boolean", default: false },
76
- help: { type: "boolean", short: "h", default: false },
77
- },
78
- });
79
-
80
- if (values.help) {
81
- console.log(HELP);
82
- process.exit(0);
83
- }
84
-
85
- if (!values.type || !values.accountId) {
86
- console.error("Error: --type and --accountId are required\n");
87
- console.log(HELP);
88
- process.exit(0);
89
- }
90
-
91
- const validTypes = [
92
- "SYNC_MAILBOXES",
93
- "SYNC_MESSAGES",
94
- "SYNC_MESSAGE_BODY",
95
- "MAILBOX_CREATE",
96
- "MAILBOX_RENAME",
97
- "MAILBOX_DELETE",
98
- ];
99
- if (!validTypes.includes(values.type)) {
100
- console.error(
101
- `Error: Invalid type "${values.type}". Must be one of: ${validTypes.join(", ")}\n`,
102
- );
103
- process.exit(1);
104
- }
105
-
106
- if (
107
- ["SYNC_MESSAGES", "SYNC_MESSAGE_BODY"].includes(values.type) &&
108
- !values.mailboxId
109
- ) {
110
- console.error(`Error: --mailboxId is required for ${values.type}\n`);
111
- process.exit(1);
112
- }
113
-
114
- if (values.type === "SYNC_MESSAGE_BODY" && !values.messageIds) {
115
- console.error(`Error: --messageIds is required for ${values.type}\n`);
116
- process.exit(1);
117
- }
118
-
119
- // Validation for mailbox management events
120
- if (
121
- ["MAILBOX_CREATE", "MAILBOX_DELETE"].includes(values.type) &&
122
- !values.path
123
- ) {
124
- console.error(`Error: --path is required for ${values.type}\n`);
125
- process.exit(1);
126
- }
127
-
128
- if (
129
- ["MAILBOX_CREATE", "MAILBOX_RENAME", "MAILBOX_DELETE"].includes(
130
- values.type,
131
- ) &&
132
- !values.mailboxId
133
- ) {
134
- console.error(`Error: --mailboxId is required for ${values.type}\n`);
135
- process.exit(1);
136
- }
137
-
138
- if (values.type === "MAILBOX_RENAME" && (!values.oldPath || !values.newPath)) {
139
- console.error(
140
- `Error: --oldPath and --newPath are required for ${values.type}\n`,
141
- );
142
- process.exit(1);
143
- }
144
-
145
- // Build the event based on type
146
- const buildEvent = () => {
147
- switch (values.type) {
148
- case "SYNC_MAILBOXES":
149
- return {
150
- type: "SYNC_MAILBOXES" as const,
151
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
152
- accountId: values.accountId!,
153
- };
154
- case "SYNC_MESSAGES":
155
- return {
156
- type: "SYNC_MESSAGES" as const,
157
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
158
- accountId: values.accountId!,
159
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
160
- mailboxId: values.mailboxId!,
161
- fullSync: values.fullSync,
162
- };
163
- case "SYNC_MESSAGE_BODY":
164
- return {
165
- type: "SYNC_MESSAGE_BODY" as const,
166
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
167
- accountId: values.accountId!,
168
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
169
- mailboxId: values.mailboxId!,
170
- messageIds: values.messageIds?.split(",").map((id) => id.trim()),
171
- };
172
- case "MAILBOX_CREATE":
173
- return {
174
- type: "MAILBOX_CREATE" as const,
175
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
176
- accountId: values.accountId!,
177
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
178
- mailboxId: values.mailboxId!,
179
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
180
- path: values.path!,
181
- subscribe: values.subscribe,
182
- };
183
- case "MAILBOX_RENAME":
184
- return {
185
- type: "MAILBOX_RENAME" as const,
186
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
187
- accountId: values.accountId!,
188
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
189
- mailboxId: values.mailboxId!,
190
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
191
- oldPath: values.oldPath!,
192
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
193
- newPath: values.newPath!,
194
- };
195
- case "MAILBOX_DELETE":
196
- return {
197
- type: "MAILBOX_DELETE" as const,
198
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
199
- accountId: values.accountId!,
200
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
201
- mailboxId: values.mailboxId!,
202
- // biome-ignore lint/style/noNonNullAssertion: value is guaranteed by caller contract
203
- path: values.path!,
204
- };
205
- default:
206
- throw new Error(`Unknown event type: ${values.type}`);
207
- }
208
- };
209
-
210
- const event = buildEvent();
211
-
212
- setWorkerQueues(sqsWorkerQueues(workerQueueUrlsFromEnv()));
213
-
214
- console.log(`Enqueueing ${event.type} event for account ${event.accountId}...`);
215
-
216
- emitEvent(event)
217
- .then(() => {
218
- console.log("Event enqueued successfully");
219
- process.exit(0);
220
- })
221
- .catch((error) => {
222
- console.error("Failed to enqueue event:", error);
223
- process.exit(1);
224
- });