@remit/backend 0.0.143 → 0.0.145

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 (279) hide show
  1. package/dist/dev-server/content-handler.d.ts +38 -0
  2. package/dist/dev-server/content-handler.js +46 -0
  3. package/dist/src/api.d.ts +5 -0
  4. package/dist/src/api.js +73 -0
  5. package/dist/src/auth.d.ts +24 -0
  6. package/dist/src/auth.js +81 -0
  7. package/dist/src/config/api-config.d.ts +20 -0
  8. package/dist/src/config/api-config.js +1 -0
  9. package/dist/src/config/from-env.d.ts +2 -0
  10. package/dist/src/config/from-env.js +65 -0
  11. package/dist/src/config/msoauth-secrets-manager.d.ts +2 -0
  12. package/dist/src/config/msoauth-secrets-manager.js +28 -0
  13. package/dist/src/config/msoauth.d.ts +19 -0
  14. package/dist/src/config/msoauth.js +6 -0
  15. package/{src/derive/autoMoved.ts → dist/src/derive/autoMoved.d.ts} +1 -29
  16. package/dist/src/derive/autoMoved.js +49 -0
  17. package/dist/src/derive/contentSignature.d.ts +40 -0
  18. package/{src/derive/contentSignature.ts → dist/src/derive/contentSignature.js} +23 -77
  19. package/dist/src/derive/contentUrl.d.ts +33 -0
  20. package/dist/src/derive/contentUrl.js +27 -0
  21. package/{src/derive/deriveMuted.ts → dist/src/derive/deriveMuted.d.ts} +1 -3
  22. package/dist/src/derive/deriveMuted.js +7 -0
  23. package/dist/src/derive/enrichThreadRows.d.ts +118 -0
  24. package/dist/src/derive/enrichThreadRows.js +151 -0
  25. package/dist/src/derive/filterThreadCriteria.d.ts +23 -0
  26. package/dist/src/derive/filterThreadCriteria.js +24 -0
  27. package/{src/derive/pendingMoveCounts.ts → dist/src/derive/pendingMoveCounts.d.ts} +5 -53
  28. package/dist/src/derive/pendingMoveCounts.js +53 -0
  29. package/{src/derive/senderTrust.ts → dist/src/derive/senderTrust.d.ts} +1 -9
  30. package/dist/src/derive/senderTrust.js +19 -0
  31. package/dist/src/error.d.ts +21 -0
  32. package/dist/src/error.js +85 -0
  33. package/dist/src/handlers/account-guards.d.ts +36 -0
  34. package/dist/src/handlers/account-guards.js +107 -0
  35. package/dist/src/handlers/account-oauth.d.ts +15 -0
  36. package/dist/src/handlers/account-oauth.js +334 -0
  37. package/dist/src/handlers/account-overrides.d.ts +53 -0
  38. package/dist/src/handlers/account-overrides.js +233 -0
  39. package/dist/src/handlers/account-signature.d.ts +28 -0
  40. package/dist/src/handlers/account-signature.js +85 -0
  41. package/dist/src/handlers/account.d.ts +7 -0
  42. package/dist/src/handlers/account.js +337 -0
  43. package/dist/src/handlers/address.d.ts +35 -0
  44. package/dist/src/handlers/address.js +133 -0
  45. package/dist/src/handlers/calendar-event.d.ts +70 -0
  46. package/dist/src/handlers/calendar-event.js +417 -0
  47. package/dist/src/handlers/calendar-feed.d.ts +47 -0
  48. package/dist/src/handlers/calendar-feed.js +184 -0
  49. package/dist/src/handlers/calendar-suggestion.d.ts +47 -0
  50. package/dist/src/handlers/calendar-suggestion.js +204 -0
  51. package/dist/src/handlers/calendar.d.ts +116 -0
  52. package/dist/src/handlers/calendar.js +323 -0
  53. package/dist/src/handlers/config.d.ts +43 -0
  54. package/dist/src/handlers/config.js +164 -0
  55. package/dist/src/handlers/ensure-account-config.d.ts +9 -0
  56. package/dist/src/handlers/ensure-account-config.js +27 -0
  57. package/dist/src/handlers/filter.d.ts +3 -0
  58. package/dist/src/handlers/filter.js +88 -0
  59. package/dist/src/handlers/folder-role-appointments.d.ts +68 -0
  60. package/dist/src/handlers/folder-role-appointments.js +168 -0
  61. package/dist/src/handlers/folder-role-labels.d.ts +26 -0
  62. package/dist/src/handlers/folder-role-labels.js +40 -0
  63. package/dist/src/handlers/folder-role.d.ts +9 -0
  64. package/dist/src/handlers/folder-role.js +37 -0
  65. package/dist/src/handlers/index.d.ts +88 -0
  66. package/dist/src/handlers/index.js +62 -0
  67. package/dist/src/handlers/label.d.ts +43 -0
  68. package/dist/src/handlers/label.js +107 -0
  69. package/dist/src/handlers/mailbox-bindings.d.ts +41 -0
  70. package/dist/src/handlers/mailbox-bindings.js +61 -0
  71. package/dist/src/handlers/mailbox.d.ts +23 -0
  72. package/dist/src/handlers/mailbox.js +211 -0
  73. package/dist/src/handlers/me.d.ts +2 -0
  74. package/dist/src/handlers/me.js +117 -0
  75. package/dist/src/handlers/message.d.ts +82 -0
  76. package/dist/src/handlers/message.js +595 -0
  77. package/dist/src/handlers/organize.d.ts +10 -0
  78. package/dist/src/handlers/organize.js +103 -0
  79. package/dist/src/handlers/outbox-attachment.d.ts +25 -0
  80. package/dist/src/handlers/outbox-attachment.js +77 -0
  81. package/dist/src/handlers/outbox.d.ts +4 -0
  82. package/dist/src/handlers/outbox.js +136 -0
  83. package/dist/src/handlers/sync-progress.d.ts +46 -0
  84. package/dist/src/handlers/sync-progress.js +63 -0
  85. package/dist/src/handlers/sync.d.ts +28 -0
  86. package/dist/src/handlers/sync.js +73 -0
  87. package/dist/src/handlers/system-update.d.ts +2 -0
  88. package/dist/src/handlers/system-update.js +159 -0
  89. package/dist/src/handlers/thread.d.ts +148 -0
  90. package/dist/src/handlers/thread.js +228 -0
  91. package/dist/src/handlers/unified-threads.d.ts +247 -0
  92. package/dist/src/handlers/unified-threads.js +406 -0
  93. package/{src/handlers/vip-suggestions.ts → dist/src/handlers/vip-suggestions.d.ts} +1 -13
  94. package/dist/src/handlers/vip-suggestions.js +16 -0
  95. package/dist/src/index.d.ts +5 -0
  96. package/dist/src/index.js +53 -0
  97. package/{src/json.ts → dist/src/json.d.ts} +1 -4
  98. package/dist/src/json.js +10 -0
  99. package/dist/src/jwt-auth.d.ts +15 -0
  100. package/dist/src/jwt-auth.js +45 -0
  101. package/dist/src/lambda.d.ts +13 -0
  102. package/dist/src/lambda.js +33 -0
  103. package/dist/src/request.d.ts +9 -0
  104. package/dist/src/request.js +17 -0
  105. package/dist/src/response.d.ts +44 -0
  106. package/dist/src/response.js +80 -0
  107. package/dist/src/serve.d.ts +31 -0
  108. package/dist/src/serve.js +117 -0
  109. package/dist/src/service/account-deletion.d.ts +20 -0
  110. package/dist/src/service/account-deletion.js +33 -0
  111. package/dist/src/service/compose-sqlite.d.ts +3 -0
  112. package/dist/src/service/compose-sqlite.js +13 -0
  113. package/dist/src/service/create-remit-client.d.ts +109 -0
  114. package/dist/src/service/create-remit-client.js +188 -0
  115. package/dist/src/service/data-client.d.ts +12 -0
  116. package/dist/src/service/data-client.js +42 -0
  117. package/dist/src/service/export-identity.d.ts +4 -0
  118. package/dist/src/service/export-identity.js +33 -0
  119. package/dist/src/service/fire-and-forget.d.ts +54 -0
  120. package/dist/src/service/fire-and-forget.js +37 -0
  121. package/dist/src/service/organize.d.ts +181 -0
  122. package/dist/src/service/organize.js +367 -0
  123. package/dist/src/service/queues.d.ts +12 -0
  124. package/dist/src/service/queues.js +1 -0
  125. package/dist/src/service/refusal.d.ts +4 -0
  126. package/dist/src/service/refusal.js +20 -0
  127. package/dist/src/service/sender-category.d.ts +51 -0
  128. package/{src/service/sender-category.ts → dist/src/service/sender-category.js} +40 -81
  129. package/dist/src/service/shared-deps.d.ts +6 -0
  130. package/dist/src/service/shared-deps.js +24 -0
  131. package/dist/src/service/trigger-sync.d.ts +57 -0
  132. package/dist/src/service/trigger-sync.js +31 -0
  133. package/dist/src/types.d.ts +72 -0
  134. package/dist/src/types.js +1 -0
  135. package/package.json +125 -98
  136. package/.env.test +0 -4
  137. package/dev-server/content-auth.test.ts +0 -113
  138. package/dev-server/content-auth.ts +0 -54
  139. package/dev-server/content-handler.test.ts +0 -105
  140. package/dev-server/content-handler.ts +0 -79
  141. package/dev-server/content-path.test.ts +0 -37
  142. package/dev-server/content-path.ts +0 -27
  143. package/dev-server/cors.test.ts +0 -48
  144. package/dev-server/cors.ts +0 -25
  145. package/dev-server/keep-alive.test.ts +0 -24
  146. package/dev-server/lambda-helpers.ts +0 -69
  147. package/dev-server/log-output.test.ts +0 -173
  148. package/dev-server/oauth-callback-route.test.ts +0 -66
  149. package/dev-server/relational-health.test.ts +0 -83
  150. package/dev-server/relational-health.ts +0 -39
  151. package/dev-server/server.ts +0 -384
  152. package/dev-server/sync-age.test.ts +0 -91
  153. package/dev-server/sync-age.ts +0 -55
  154. package/dev-server/upload-handler.ts +0 -132
  155. package/dev-server/upload-route.test.ts +0 -196
  156. package/scripts/backfill-classification.ts +0 -91
  157. package/scripts/backfill-list-id.ts +0 -83
  158. package/scripts/config-save.ts +0 -128
  159. package/src/auth.test.ts +0 -12
  160. package/src/auth.ts +0 -92
  161. package/src/config/msoauth.test.ts +0 -48
  162. package/src/config/msoauth.ts +0 -48
  163. package/src/data-backend.test.ts +0 -23
  164. package/src/data-backend.ts +0 -14
  165. package/src/derive/autoMoved.test.ts +0 -104
  166. package/src/derive/contentSignature.test.ts +0 -161
  167. package/src/derive/contentUrl.test.ts +0 -172
  168. package/src/derive/contentUrl.ts +0 -86
  169. package/src/derive/deriveMuted.test.ts +0 -34
  170. package/src/derive/enrichThreadRows.test.ts +0 -360
  171. package/src/derive/enrichThreadRows.ts +0 -234
  172. package/src/derive/filterThreadCriteria.test.ts +0 -126
  173. package/src/derive/filterThreadCriteria.ts +0 -51
  174. package/src/derive/senderTrust.test.ts +0 -67
  175. package/src/error.test.ts +0 -201
  176. package/src/error.ts +0 -123
  177. package/src/handlers/account-guards.test.ts +0 -67
  178. package/src/handlers/account-guards.ts +0 -169
  179. package/src/handlers/account-oauth-callback.test.ts +0 -155
  180. package/src/handlers/account-oauth-consent.test.ts +0 -336
  181. package/src/handlers/account-oauth-start.test.ts +0 -191
  182. package/src/handlers/account-oauth.test.ts +0 -439
  183. package/src/handlers/account-oauth.ts +0 -635
  184. package/src/handlers/account-overrides.test.ts +0 -88
  185. package/src/handlers/account-overrides.ts +0 -323
  186. package/src/handlers/account-ownership.ts +0 -25
  187. package/src/handlers/account-signature.ts +0 -117
  188. package/src/handlers/account-synced-services.test.ts +0 -245
  189. package/src/handlers/account.ts +0 -552
  190. package/src/handlers/address.test.ts +0 -381
  191. package/src/handlers/address.ts +0 -200
  192. package/src/handlers/calendar-event.test.ts +0 -685
  193. package/src/handlers/calendar-event.ts +0 -738
  194. package/src/handlers/calendar-feed-validators.test.ts +0 -228
  195. package/src/handlers/calendar-feed.test.ts +0 -439
  196. package/src/handlers/calendar-feed.ts +0 -291
  197. package/src/handlers/calendar-sqlite-fixture.ts +0 -36
  198. package/src/handlers/calendar-suggestion.test.ts +0 -1269
  199. package/src/handlers/calendar-suggestion.ts +0 -425
  200. package/src/handlers/calendar.test.ts +0 -1080
  201. package/src/handlers/calendar.ts +0 -517
  202. package/src/handlers/config.test.ts +0 -245
  203. package/src/handlers/config.ts +0 -332
  204. package/src/handlers/ensure-account-config.ts +0 -30
  205. package/src/handlers/filter.test.ts +0 -644
  206. package/src/handlers/filter.ts +0 -518
  207. package/src/handlers/folder-role-appointments.test.ts +0 -438
  208. package/src/handlers/folder-role-appointments.ts +0 -249
  209. package/src/handlers/folder-role-labels.ts +0 -63
  210. package/src/handlers/folder-role.test.ts +0 -209
  211. package/src/handlers/folder-role.ts +0 -80
  212. package/src/handlers/index.ts +0 -83
  213. package/src/handlers/label.test.ts +0 -112
  214. package/src/handlers/label.ts +0 -210
  215. package/src/handlers/mailbox-bindings.ts +0 -111
  216. package/src/handlers/mailbox-rename-refusal.test.ts +0 -247
  217. package/src/handlers/mailbox-settled-target.test.ts +0 -251
  218. package/src/handlers/mailbox.test.ts +0 -280
  219. package/src/handlers/mailbox.ts +0 -581
  220. package/src/handlers/me.test.ts +0 -81
  221. package/src/handlers/me.ts +0 -203
  222. package/src/handlers/message-read-backfill.test.ts +0 -103
  223. package/src/handlers/message.test.ts +0 -131
  224. package/src/handlers/message.ts +0 -1131
  225. package/src/handlers/organize.test.ts +0 -277
  226. package/src/handlers/organize.ts +0 -197
  227. package/src/handlers/outbox-attachment.test.ts +0 -765
  228. package/src/handlers/outbox-attachment.ts +0 -126
  229. package/src/handlers/outbox-list.test.ts +0 -179
  230. package/src/handlers/outbox.test.ts +0 -772
  231. package/src/handlers/outbox.ts +0 -258
  232. package/src/handlers/search.test.ts +0 -161
  233. package/src/handlers/search.ts +0 -105
  234. package/src/handlers/sync-progress.test.ts +0 -205
  235. package/src/handlers/sync-progress.ts +0 -99
  236. package/src/handlers/sync.test.ts +0 -168
  237. package/src/handlers/sync.ts +0 -118
  238. package/src/handlers/system-update.test.ts +0 -497
  239. package/src/handlers/system-update.ts +0 -230
  240. package/src/handlers/thread.test.ts +0 -396
  241. package/src/handlers/thread.ts +0 -427
  242. package/src/handlers/unified-threads-mail-sources.sqlite.test.ts +0 -197
  243. package/src/handlers/unified-threads.test.ts +0 -785
  244. package/src/handlers/unified-threads.ts +0 -669
  245. package/src/index.test.ts +0 -83
  246. package/src/index.ts +0 -228
  247. package/src/jwt-auth.test.ts +0 -152
  248. package/src/jwt-auth.ts +0 -132
  249. package/src/log-redaction.test.ts +0 -144
  250. package/src/openapi-spec.test.ts +0 -118
  251. package/src/request-context.test.ts +0 -61
  252. package/src/request-context.ts +0 -33
  253. package/src/request-pipeline.test.ts +0 -88
  254. package/src/request.ts +0 -10
  255. package/src/response.test.ts +0 -130
  256. package/src/response.ts +0 -144
  257. package/src/service/compose-sqlite.ts +0 -98
  258. package/src/service/config-import.ts +0 -39
  259. package/src/service/create-remit-client.ts +0 -522
  260. package/src/service/data-client.test.ts +0 -97
  261. package/src/service/data-client.ts +0 -58
  262. package/src/service/export-identity.ts +0 -39
  263. package/src/service/filter.ts +0 -40
  264. package/src/service/fire-and-forget.test.ts +0 -126
  265. package/src/service/fire-and-forget.ts +0 -79
  266. package/src/service/localhost-env-config.test.ts +0 -36
  267. package/src/service/organize-queue.ts +0 -98
  268. package/src/service/organize.test.ts +0 -1451
  269. package/src/service/organize.ts +0 -1025
  270. package/src/service/read-path-filter-config.test.ts +0 -243
  271. package/src/service/semantic-capability.test.ts +0 -78
  272. package/src/service/semantic-capability.ts +0 -95
  273. package/src/service/sender-category.test.ts +0 -235
  274. package/src/service/sqs.ts +0 -4
  275. package/src/service/trigger-sync.test.ts +0 -205
  276. package/src/service/trigger-sync.ts +0 -100
  277. package/src/stdout-capture-fixture.ts +0 -40
  278. package/src/types.ts +0 -271
  279. package/tsconfig.json +0 -7
@@ -1,205 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { SendMessageCommand, type SQSClient } from "@aws-sdk/client-sqs";
4
- import {
5
- buildScheduledSyncDedupId,
6
- buildSyncMailboxesCommand,
7
- triggerAccountSync,
8
- } from "./trigger-sync.js";
9
-
10
- const FIFO_QUEUE_URL =
11
- "https://sqs.eu-west-1.amazonaws.com/123456789012/remit-dev-mailboxes.fifo";
12
- const STANDARD_QUEUE_URL =
13
- "http://localhost:9324/000000000000/remit-dev-mailboxes";
14
-
15
- const parseBody = (cmd: SendMessageCommand): Record<string, unknown> => {
16
- const body = cmd.input.MessageBody ?? "{}";
17
- return JSON.parse(body) as Record<string, unknown>;
18
- };
19
-
20
- describe("buildSyncMailboxesCommand", () => {
21
- it("sets MessageGroupId to accountId for FIFO queues", () => {
22
- const cmd = buildSyncMailboxesCommand({
23
- queueUrl: FIFO_QUEUE_URL,
24
- accountId: "account-abc",
25
- });
26
-
27
- assert.equal(cmd.input.MessageGroupId, "account-abc");
28
- });
29
-
30
- it("defaults MessageDeduplicationId to the event's own id for FIFO queues", () => {
31
- const cmd = buildSyncMailboxesCommand({
32
- queueUrl: FIFO_QUEUE_URL,
33
- accountId: "account-abc",
34
- });
35
-
36
- assert.equal(cmd.input.MessageDeduplicationId, parseBody(cmd).eventId);
37
- });
38
-
39
- // Issue #37: a shared, time-bucketed dedup id let SQS FIFO's 5-minute
40
- // window discard the second sync of an account, so mail that arrived after
41
- // a sync stayed invisible until the window elapsed. Back-to-back triggers
42
- // must each reach the queue.
43
- it("gives two triggers for one account distinct dedup ids", () => {
44
- const first = buildSyncMailboxesCommand({
45
- queueUrl: FIFO_QUEUE_URL,
46
- accountId: "account-abc",
47
- });
48
- const second = buildSyncMailboxesCommand({
49
- queueUrl: FIFO_QUEUE_URL,
50
- accountId: "account-abc",
51
- });
52
-
53
- assert.notEqual(
54
- first.input.MessageDeduplicationId,
55
- second.input.MessageDeduplicationId,
56
- );
57
- });
58
-
59
- // The worker's fan-out gate reads this off the event: it is what lets a
60
- // sync asked for by name cover every folder while a side-effect trigger
61
- // skips the ones that were just enumerated.
62
- it("marks an explicitly-requested trigger on the event", () => {
63
- const cmd = buildSyncMailboxesCommand({
64
- queueUrl: FIFO_QUEUE_URL,
65
- accountId: "account-abc",
66
- explicitRequest: true,
67
- });
68
-
69
- assert.equal(parseBody(cmd).explicitRequest, true);
70
- });
71
-
72
- it("leaves a side-effect trigger unmarked", () => {
73
- const cmd = buildSyncMailboxesCommand({
74
- queueUrl: FIFO_QUEUE_URL,
75
- accountId: "account-abc",
76
- });
77
-
78
- assert.equal(parseBody(cmd).explicitRequest, undefined);
79
- });
80
-
81
- it("does not set FIFO params for standard queues", () => {
82
- const cmd = buildSyncMailboxesCommand({
83
- queueUrl: STANDARD_QUEUE_URL,
84
- accountId: "account-abc",
85
- });
86
-
87
- assert.equal(cmd.input.MessageGroupId, undefined);
88
- assert.equal(cmd.input.MessageDeduplicationId, undefined);
89
- });
90
-
91
- it("builds a SYNC_MAILBOXES event body with accountId and eventId", () => {
92
- const cmd = buildSyncMailboxesCommand({
93
- queueUrl: FIFO_QUEUE_URL,
94
- accountId: "account-abc",
95
- });
96
-
97
- const event = parseBody(cmd);
98
- assert.equal(event.type, "SYNC_MAILBOXES");
99
- assert.equal(event.accountId, "account-abc");
100
- assert.equal(typeof event.eventId, "string");
101
- assert.equal(typeof event.timestamp, "number");
102
- });
103
-
104
- it("targets the configured queue url", () => {
105
- const cmd = buildSyncMailboxesCommand({
106
- queueUrl: FIFO_QUEUE_URL,
107
- accountId: "account-abc",
108
- });
109
-
110
- assert.equal(cmd.input.QueueUrl, FIFO_QUEUE_URL);
111
- });
112
-
113
- it("uses the caller-supplied dedupId instead of the manual default", () => {
114
- const cmd = buildSyncMailboxesCommand({
115
- queueUrl: FIFO_QUEUE_URL,
116
- accountId: "account-abc",
117
- dedupId: "SYNC_MAILBOXES:scheduled:account-abc:12345",
118
- });
119
-
120
- assert.equal(
121
- cmd.input.MessageDeduplicationId,
122
- "SYNC_MAILBOXES:scheduled:account-abc:12345",
123
- );
124
- });
125
- });
126
-
127
- describe("buildScheduledSyncDedupId", () => {
128
- const FIVE_MINUTES_MS = 5 * 60 * 1000;
129
-
130
- it("is stable within the same time bucket (dedupes a retried tick)", () => {
131
- const bucketStart = 10 * FIVE_MINUTES_MS;
132
-
133
- const first = buildScheduledSyncDedupId(
134
- "account-abc",
135
- bucketStart,
136
- FIVE_MINUTES_MS,
137
- );
138
- const second = buildScheduledSyncDedupId(
139
- "account-abc",
140
- bucketStart + 1_000,
141
- FIVE_MINUTES_MS,
142
- );
143
-
144
- assert.equal(first, second);
145
- });
146
-
147
- it("changes across a bucket boundary (never dedupes two ticks apart)", () => {
148
- const bucketStart = 10 * FIVE_MINUTES_MS;
149
-
150
- const thisTick = buildScheduledSyncDedupId(
151
- "account-abc",
152
- bucketStart,
153
- FIVE_MINUTES_MS,
154
- );
155
- const nextTick = buildScheduledSyncDedupId(
156
- "account-abc",
157
- bucketStart + FIVE_MINUTES_MS,
158
- FIVE_MINUTES_MS,
159
- );
160
-
161
- assert.notEqual(thisTick, nextTick);
162
- });
163
- });
164
-
165
- describe("triggerAccountSync", () => {
166
- it("sends a SendMessageCommand to the client", async () => {
167
- const sent: SendMessageCommand[] = [];
168
- const sqsClient = {
169
- send: async (cmd: SendMessageCommand) => {
170
- sent.push(cmd);
171
- return {};
172
- },
173
- } as unknown as SQSClient;
174
-
175
- const result = await triggerAccountSync({
176
- sqsClient,
177
- queueUrl: FIFO_QUEUE_URL,
178
- accountId: "account-xyz",
179
- });
180
-
181
- assert.equal(sent.length, 1);
182
- const cmd = sent[0];
183
- if (!cmd) throw new Error("expected command");
184
- assert.ok(cmd instanceof SendMessageCommand);
185
- assert.equal(cmd.input.MessageGroupId, "account-xyz");
186
- assert.equal(typeof result.eventId, "string");
187
- });
188
-
189
- it("propagates SQS send errors to the caller", async () => {
190
- const sqsClient = {
191
- send: async () => {
192
- throw new Error("MissingRequiredParameterException");
193
- },
194
- } as unknown as SQSClient;
195
-
196
- await assert.rejects(
197
- triggerAccountSync({
198
- sqsClient,
199
- queueUrl: FIFO_QUEUE_URL,
200
- accountId: "account-xyz",
201
- }),
202
- /MissingRequiredParameterException/,
203
- );
204
- });
205
- });
@@ -1,100 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { SendMessageCommand, type SQSClient } from "@aws-sdk/client-sqs";
3
-
4
- interface SyncMailboxesEvent {
5
- type: "SYNC_MAILBOXES";
6
- eventId: string;
7
- timestamp: number;
8
- accountId: string;
9
- explicitRequest?: boolean;
10
- }
11
-
12
- interface TriggerAccountSyncInput {
13
- sqsClient: SQSClient;
14
- queueUrl: string;
15
- accountId: string;
16
- /**
17
- * Set by POST /sync, whose callers ask for a sync of one named account: the
18
- * refresh control, pull-to-refresh, and the web client's automatic poll
19
- * (`useStaleAccountSync`) — a timer, not a person. It travels on the event
20
- * and makes the worker's fan-out sync every mailbox even if one just ran.
21
- *
22
- * Everything else triggers a sync as a side effect of doing something else
23
- * (config load, OAuth connect, account create, the scheduled tick), leaves
24
- * this unset, and takes the freshness gate — see `mailboxNeedsSync` in
25
- * imap-worker's sync-mailboxes handler.
26
- *
27
- * How often a timer may do that is bounded on the client, by the poll's own
28
- * floor (`MIN_POLL_INTERVAL_MS` in the client hook, 30s) rather than by the
29
- * gate: `mailboxPollIntervalSeconds` can lengthen the interval, never
30
- * shorten it past that.
31
- */
32
- explicitRequest?: boolean;
33
- /**
34
- * Override the FIFO `MessageDeduplicationId`. Defaults to the event's own
35
- * id, so the queue suppresses a re-send of one event and nothing else —
36
- * every manual call site (POST /sync, OAuth connect, config load,
37
- * pull-to-refresh, the client's online-poll) always enqueues. A shared,
38
- * time-bucketed id instead turned SQS's 5-minute window into a rate limiter
39
- * and silently discarded a sync the user asked for whenever one had run
40
- * recently (issue #37). What a trigger costs is bounded in the worker's
41
- * fan-out (`mailboxNeedsSync`), by skipping mailboxes not worth
42
- * re-enumerating — never by dropping the trigger.
43
- *
44
- * The scheduled-sync tick (#1247) passes `buildScheduledSyncDedupId()`,
45
- * which is bucketed by the tick's own cadence: there it collapses a
46
- * re-invocation of a single tick, never two ticks or a manual trigger.
47
- */
48
- dedupId?: string;
49
- }
50
-
51
- const isFifoQueue = (queueUrl: string): boolean => queueUrl.endsWith(".fifo");
52
-
53
- /**
54
- * Build the scheduler's own dedup namespace, bucketed by tick interval so
55
- * consecutive ticks each get a fresh id (never colliding with each other)
56
- * while still deduping a genuine double-invocation of the same tick (e.g. a
57
- * retried Lambda) — see `dedupId` above.
58
- */
59
- export const buildScheduledSyncDedupId = (
60
- accountId: string,
61
- now: number,
62
- bucketMs: number,
63
- ): string => {
64
- const bucket = Math.floor(now / bucketMs);
65
- return `SYNC_MAILBOXES:scheduled:${accountId}:${bucket}`;
66
- };
67
-
68
- export const buildSyncMailboxesCommand = (
69
- input: Omit<TriggerAccountSyncInput, "sqsClient">,
70
- ): SendMessageCommand => {
71
- const { queueUrl, accountId, dedupId, explicitRequest } = input;
72
- const event: SyncMailboxesEvent = {
73
- type: "SYNC_MAILBOXES",
74
- eventId: randomUUID(),
75
- timestamp: Date.now(),
76
- accountId,
77
- ...(explicitRequest && { explicitRequest }),
78
- };
79
-
80
- const useFifo = isFifoQueue(queueUrl);
81
-
82
- return new SendMessageCommand({
83
- QueueUrl: queueUrl,
84
- MessageBody: JSON.stringify(event),
85
- ...(useFifo && {
86
- MessageGroupId: accountId,
87
- MessageDeduplicationId: dedupId ?? event.eventId,
88
- }),
89
- });
90
- };
91
-
92
- export const triggerAccountSync = async (
93
- input: TriggerAccountSyncInput,
94
- ): Promise<{ eventId: string }> => {
95
- const command = buildSyncMailboxesCommand(input);
96
- await input.sqsClient.send(command);
97
- const body = command.input.MessageBody ?? "{}";
98
- const parsed = JSON.parse(body) as SyncMailboxesEvent;
99
- return { eventId: parsed.eventId };
100
- };
@@ -1,40 +0,0 @@
1
- /**
2
- * A test's view of what a request wrote to the log.
3
- *
4
- * pino writes through `process.stdout` once its `write` is replaced, so the hook
5
- * is installed when this module is evaluated — import it above anything that
6
- * pulls in the logger. Writes pass through whenever nothing is capturing, so the
7
- * test runner's own output still reaches the terminal.
8
- */
9
-
10
- const originalWrite = process.stdout.write.bind(process.stdout);
11
- const written: string[] = [];
12
- let capturing = false;
13
-
14
- process.stdout.write = ((
15
- chunk: string | Uint8Array,
16
- ...rest: unknown[]
17
- ): boolean => {
18
- if (capturing && typeof chunk === "string") {
19
- written.push(chunk);
20
- return true;
21
- }
22
- return (originalWrite as (...args: unknown[]) => boolean)(chunk, ...rest);
23
- }) as typeof process.stdout.write;
24
-
25
- export const captureStdout = async <T>(
26
- run: () => Promise<T>,
27
- ): Promise<{ result: T; logged: string }> => {
28
- written.length = 0;
29
- capturing = true;
30
- try {
31
- const result = await run();
32
- return { result, logged: written.join("") };
33
- } finally {
34
- capturing = false;
35
- }
36
- };
37
-
38
- export const restoreStdout = (): void => {
39
- process.stdout.write = originalWrite as typeof process.stdout.write;
40
- };
package/src/types.ts DELETED
@@ -1,271 +0,0 @@
1
- import type { Context } from "openapi-backend";
2
-
3
- type MatchPrefix<
4
- Prefix extends string,
5
- S extends string,
6
- > = S extends `${Prefix}${infer _}` ? S : never;
7
-
8
- export type OperationIds =
9
- | "MeOperations_deleteMe"
10
- | "MeOperations_listVipSuggestions"
11
- | "MeOperations_createExport"
12
- | "MeOperations_getExport"
13
- | "MeOperations_listQuarantine"
14
- | "ConfigOperations_getConfig"
15
- | "ConfigOperations_exportConfig"
16
- | "ConfigOperations_importConfig"
17
- | "SystemOperations_getSystemUpdate"
18
- | "SystemOperations_applySystemUpdate"
19
- | "AccountOperations_createAccount"
20
- | "AccountOperations_testConnection"
21
- | "AccountDetailOperations_updateAccount"
22
- | "AccountDetailOperations_deleteAccount"
23
- | "MicrosoftOAuthOperations_microsoftOAuthStart"
24
- | "MicrosoftOAuthOperations_microsoftOAuthCallback"
25
- | "MailboxOperations_listMailboxes"
26
- | "MailboxOperations_createMailbox"
27
- | "MailboxDetailOperations_getMailbox"
28
- | "MailboxDetailOperations_renameMailbox"
29
- | "MailboxDetailOperations_deleteMailbox"
30
- | "FolderRoleOperations_appointFolderRole"
31
- | "FilterOperations_listFilters"
32
- | "FilterOperations_createFilter"
33
- | "FilterDetailOperations_getFilter"
34
- | "FilterDetailOperations_updateFilter"
35
- | "FilterDetailOperations_deleteFilter"
36
- | "LabelOperations_listLabels"
37
- | "LabelOperations_createLabel"
38
- | "LabelDetailOperations_getLabel"
39
- | "LabelDetailOperations_updateLabel"
40
- | "LabelDetailOperations_deleteLabel"
41
- | "OrganizeOperations_createOrganizeJob"
42
- | "OrganizeOperations_previewOrganize"
43
- | "OrganizeJobDetailOperations_getOrganizeJob"
44
- | "SyncOperations_triggerSync"
45
- | "SyncOperations_getSyncStatus"
46
- | "SemanticSearchOperations_semanticSearch"
47
- | "ThreadDetailOperations_listThreadMessages"
48
- | "UnifiedThreadOperations_listAllThreads"
49
- | "ThreadOperations_listThreads"
50
- | "ThreadOperations_searchThreads"
51
- | "MessageOperations_describeMessage"
52
- | "MessageOperations_getRawMessage"
53
- | "MessageOperations_updateMessageFlags"
54
- | "MessageBulkOperations_deleteMessages"
55
- | "MessageBulkOperations_moveMessages"
56
- | "MessageBulkOperations_updateFlags"
57
- | "MessageBulkOperations_copyMessages"
58
- | "MessageBulkOperations_updateMessageLabels"
59
- | "MessageBulkOperations_reportSpam"
60
- | "MessageBulkOperations_notSpam"
61
- | "CalendarOperations_listCalendars"
62
- | "CalendarOperations_createCalendar"
63
- | "CalendarDetailOperations_getCalendar"
64
- | "CalendarDetailOperations_updateCalendar"
65
- | "CalendarDetailOperations_deleteCalendar"
66
- | "CalendarDetailOperations_getCalendarFeed"
67
- | "CalendarDetailOperations_putCalendarFeed"
68
- | "CalendarDetailOperations_revokeCalendarFeed"
69
- | "CalendarFeedOperations_getCalendarFeedIcal"
70
- | "CalendarEventOperations_listCalendarEvents"
71
- | "CalendarEventOperations_createCalendarEvent"
72
- | "CalendarEventDetailOperations_getCalendarEvent"
73
- | "CalendarEventDetailOperations_updateCalendarEvent"
74
- | "CalendarEventDetailOperations_deleteCalendarEvent"
75
- | "CalendarFreeBusyOperations_listCalendarFreeBusy"
76
- | "TrashOperations_emptyTrash"
77
- | "OutboxOperations_createOutboxMessage"
78
- | "OutboxOperations_listOutboxMessages"
79
- | "OutboxDetailOperations_getOutboxMessage"
80
- | "OutboxDetailOperations_updateOutboxMessage"
81
- | "OutboxDetailOperations_deleteOutboxMessage"
82
- | "OutboxDetailOperations_sendOutboxMessage"
83
- | "OutboxDetailOperations_mintOutboxAttachment"
84
- | "OutboxAttachmentOperations_completeOutboxAttachment"
85
- | "AddressOperations_searchAddresses"
86
- | "AddressDetailOperations_updateAddress"
87
- | "CalendarSuggestionOperations_listCalendarSuggestions"
88
- | "MessageCalendarSuggestionOperations_listMessageCalendarSuggestions"
89
- | "CalendarSuggestionActionOperations_acceptCalendarSuggestion"
90
- | "CalendarSuggestionActionOperations_declineCalendarSuggestion"
91
- | "CalendarSuggestionActionOperations_dismissCalendarSuggestion"
92
- | "CalendarSuggestionActionOperations_reopenCalendarSuggestion";
93
-
94
- export type MeOperationIds = MatchPrefix<"MeOperations_", OperationIds>;
95
-
96
- export type ConfigOperationIds = MatchPrefix<"ConfigOperations_", OperationIds>;
97
-
98
- export type SystemOperationIds = MatchPrefix<"SystemOperations_", OperationIds>;
99
-
100
- export type AccountOperationIds = MatchPrefix<
101
- "AccountOperations_",
102
- OperationIds
103
- >;
104
-
105
- export type AccountDetailOperationIds = MatchPrefix<
106
- "AccountDetailOperations_",
107
- OperationIds
108
- >;
109
-
110
- export type MailboxOperationIds = MatchPrefix<
111
- "MailboxOperations_",
112
- OperationIds
113
- >;
114
-
115
- export type MailboxDetailOperationIds = MatchPrefix<
116
- "MailboxDetailOperations_",
117
- OperationIds
118
- >;
119
-
120
- export type FolderRoleOperationIds = MatchPrefix<
121
- "FolderRoleOperations_",
122
- OperationIds
123
- >;
124
-
125
- export type FilterOperationIds = MatchPrefix<"FilterOperations_", OperationIds>;
126
-
127
- export type FilterDetailOperationIds = MatchPrefix<
128
- "FilterDetailOperations_",
129
- OperationIds
130
- >;
131
-
132
- export type LabelOperationIds = MatchPrefix<"LabelOperations_", OperationIds>;
133
-
134
- export type LabelDetailOperationIds = MatchPrefix<
135
- "LabelDetailOperations_",
136
- OperationIds
137
- >;
138
-
139
- export type OrganizeOperationIds = MatchPrefix<
140
- "OrganizeOperations_",
141
- OperationIds
142
- >;
143
-
144
- export type OrganizeJobDetailOperationIds = MatchPrefix<
145
- "OrganizeJobDetailOperations_",
146
- OperationIds
147
- >;
148
-
149
- export type SyncOperationIds = MatchPrefix<"SyncOperations_", OperationIds>;
150
-
151
- export type ThreadDetailOperationIds = MatchPrefix<
152
- "ThreadDetailOperations_",
153
- OperationIds
154
- >;
155
-
156
- export type UnifiedThreadOperationIds = MatchPrefix<
157
- "UnifiedThreadOperations_",
158
- OperationIds
159
- >;
160
-
161
- export type ThreadOperationIds = MatchPrefix<"ThreadOperations_", OperationIds>;
162
-
163
- export type SemanticSearchOperationIds = MatchPrefix<
164
- "SemanticSearchOperations_",
165
- OperationIds
166
- >;
167
-
168
- export type MessageOperationIds = MatchPrefix<
169
- "MessageOperations_",
170
- OperationIds
171
- >;
172
-
173
- export type MessageBulkOperationIds = MatchPrefix<
174
- "MessageBulkOperations_",
175
- OperationIds
176
- >;
177
-
178
- export type CalendarOperationIds = MatchPrefix<
179
- "CalendarOperations_",
180
- OperationIds
181
- >;
182
-
183
- export type CalendarDetailOperationIds = MatchPrefix<
184
- "CalendarDetailOperations_",
185
- OperationIds
186
- >;
187
-
188
- /**
189
- * The feed sub-resource of `/calendars/{calendarId}`, handled beside the
190
- * collection itself rather than inside it: minting a credential and serving one
191
- * calendar's settings are different jobs on the same path.
192
- */
193
- export type CalendarFeedDetailOperationIds =
194
- | "CalendarDetailOperations_getCalendarFeed"
195
- | "CalendarDetailOperations_putCalendarFeed"
196
- | "CalendarDetailOperations_revokeCalendarFeed";
197
-
198
- export type CalendarCollectionDetailOperationIds = Exclude<
199
- CalendarDetailOperationIds,
200
- CalendarFeedDetailOperationIds
201
- >;
202
-
203
- export type CalendarFeedOperationIds = MatchPrefix<
204
- "CalendarFeedOperations_",
205
- OperationIds
206
- >;
207
-
208
- export type CalendarEventOperationIds = MatchPrefix<
209
- "CalendarEventOperations_",
210
- OperationIds
211
- >;
212
-
213
- export type CalendarEventDetailOperationIds = MatchPrefix<
214
- "CalendarEventDetailOperations_",
215
- OperationIds
216
- >;
217
-
218
- export type CalendarFreeBusyOperationIds = MatchPrefix<
219
- "CalendarFreeBusyOperations_",
220
- OperationIds
221
- >;
222
-
223
- export type TrashOperationIds = MatchPrefix<"TrashOperations_", OperationIds>;
224
-
225
- export type OutboxOperationIds = MatchPrefix<"OutboxOperations_", OperationIds>;
226
-
227
- export type OutboxDetailOperationIds = MatchPrefix<
228
- "OutboxDetailOperations_",
229
- OperationIds
230
- >;
231
-
232
- export type OutboxAttachmentOperationIds = MatchPrefix<
233
- "OutboxAttachmentOperations_",
234
- OperationIds
235
- >;
236
-
237
- export type AddressOperationIds = MatchPrefix<
238
- "AddressOperations_",
239
- OperationIds
240
- >;
241
-
242
- export type AddressDetailOperationIds = MatchPrefix<
243
- "AddressDetailOperations_",
244
- OperationIds
245
- >;
246
-
247
- export type MicrosoftOAuthOperationIds = MatchPrefix<
248
- "MicrosoftOAuthOperations_",
249
- OperationIds
250
- >;
251
-
252
- export type CalendarSuggestionOperationIds = MatchPrefix<
253
- "CalendarSuggestionOperations_",
254
- OperationIds
255
- >;
256
-
257
- export type MessageCalendarSuggestionOperationIds = MatchPrefix<
258
- "MessageCalendarSuggestionOperations_",
259
- OperationIds
260
- >;
261
-
262
- export type CalendarSuggestionActionOperationIds = MatchPrefix<
263
- "CalendarSuggestionActionOperations_",
264
- OperationIds
265
- >;
266
-
267
- // biome-ignore lint/suspicious/noExplicitAny: handler responses vary by operation
268
- type HandlerResponse = Record<string, any>;
269
- export type OperationHandler<_T extends OperationIds = OperationIds> = (
270
- context: Context,
271
- ) => Promise<HandlerResponse>;
package/tsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist"
5
- },
6
- "include": ["src/**/*.ts", "dev-server/**/*.ts", "scripts/**/*.ts"]
7
- }