@remit/backend 0.0.143 → 0.0.144

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 (269) 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 +7 -0
  4. package/dist/src/api.js +144 -0
  5. package/dist/src/auth.d.ts +30 -0
  6. package/dist/src/auth.js +73 -0
  7. package/dist/src/config/msoauth.d.ts +30 -0
  8. package/dist/src/config/msoauth.js +30 -0
  9. package/{src/data-backend.ts → dist/src/data-backend.d.ts} +2 -4
  10. package/dist/src/data-backend.js +12 -0
  11. package/{src/derive/autoMoved.ts → dist/src/derive/autoMoved.d.ts} +1 -29
  12. package/dist/src/derive/autoMoved.js +49 -0
  13. package/dist/src/derive/contentSignature.d.ts +41 -0
  14. package/{src/derive/contentSignature.ts → dist/src/derive/contentSignature.js} +27 -72
  15. package/dist/src/derive/contentUrl.d.ts +46 -0
  16. package/dist/src/derive/contentUrl.js +46 -0
  17. package/{src/derive/deriveMuted.ts → dist/src/derive/deriveMuted.d.ts} +1 -3
  18. package/dist/src/derive/deriveMuted.js +7 -0
  19. package/dist/src/derive/enrichThreadRows.d.ts +118 -0
  20. package/dist/src/derive/enrichThreadRows.js +151 -0
  21. package/dist/src/derive/filterThreadCriteria.d.ts +23 -0
  22. package/dist/src/derive/filterThreadCriteria.js +24 -0
  23. package/{src/derive/pendingMoveCounts.ts → dist/src/derive/pendingMoveCounts.d.ts} +5 -53
  24. package/dist/src/derive/pendingMoveCounts.js +53 -0
  25. package/{src/derive/senderTrust.ts → dist/src/derive/senderTrust.d.ts} +1 -9
  26. package/dist/src/derive/senderTrust.js +19 -0
  27. package/dist/src/error.d.ts +21 -0
  28. package/dist/src/error.js +85 -0
  29. package/dist/src/handlers/account-guards.d.ts +36 -0
  30. package/dist/src/handlers/account-guards.js +107 -0
  31. package/dist/src/handlers/account-oauth.d.ts +14 -0
  32. package/dist/src/handlers/account-oauth.js +387 -0
  33. package/dist/src/handlers/account-overrides.d.ts +53 -0
  34. package/dist/src/handlers/account-overrides.js +233 -0
  35. package/dist/src/handlers/account-signature.d.ts +28 -0
  36. package/dist/src/handlers/account-signature.js +85 -0
  37. package/dist/src/handlers/account.d.ts +6 -0
  38. package/dist/src/handlers/account.js +350 -0
  39. package/dist/src/handlers/address.d.ts +35 -0
  40. package/dist/src/handlers/address.js +141 -0
  41. package/dist/src/handlers/calendar-event.d.ts +70 -0
  42. package/dist/src/handlers/calendar-event.js +425 -0
  43. package/dist/src/handlers/calendar-feed.d.ts +47 -0
  44. package/dist/src/handlers/calendar-feed.js +192 -0
  45. package/dist/src/handlers/calendar-suggestion.d.ts +47 -0
  46. package/dist/src/handlers/calendar-suggestion.js +212 -0
  47. package/dist/src/handlers/calendar.d.ts +116 -0
  48. package/dist/src/handlers/calendar.js +330 -0
  49. package/dist/src/handlers/config.d.ts +43 -0
  50. package/dist/src/handlers/config.js +176 -0
  51. package/dist/src/handlers/ensure-account-config.d.ts +9 -0
  52. package/dist/src/handlers/ensure-account-config.js +27 -0
  53. package/dist/src/handlers/filter.d.ts +3 -0
  54. package/dist/src/handlers/filter.js +103 -0
  55. package/dist/src/handlers/folder-role-appointments.d.ts +68 -0
  56. package/dist/src/handlers/folder-role-appointments.js +168 -0
  57. package/dist/src/handlers/folder-role-labels.d.ts +26 -0
  58. package/dist/src/handlers/folder-role-labels.js +40 -0
  59. package/dist/src/handlers/folder-role.d.ts +9 -0
  60. package/dist/src/handlers/folder-role.js +40 -0
  61. package/dist/src/handlers/index.d.ts +2 -0
  62. package/dist/src/handlers/index.js +60 -0
  63. package/dist/src/handlers/label.d.ts +43 -0
  64. package/dist/src/handlers/label.js +114 -0
  65. package/dist/src/handlers/mailbox-bindings.d.ts +41 -0
  66. package/dist/src/handlers/mailbox-bindings.js +61 -0
  67. package/dist/src/handlers/mailbox.d.ts +23 -0
  68. package/dist/src/handlers/mailbox.js +219 -0
  69. package/dist/src/handlers/me.d.ts +2 -0
  70. package/dist/src/handlers/me.js +138 -0
  71. package/dist/src/handlers/message.d.ts +84 -0
  72. package/dist/src/handlers/message.js +607 -0
  73. package/dist/src/handlers/organize.d.ts +10 -0
  74. package/dist/src/handlers/organize.js +112 -0
  75. package/dist/src/handlers/outbox-attachment.d.ts +23 -0
  76. package/dist/src/handlers/outbox-attachment.js +81 -0
  77. package/dist/src/handlers/outbox.d.ts +4 -0
  78. package/dist/src/handlers/outbox.js +144 -0
  79. package/dist/src/handlers/sync-progress.d.ts +46 -0
  80. package/dist/src/handlers/sync-progress.js +63 -0
  81. package/dist/src/handlers/sync.d.ts +28 -0
  82. package/dist/src/handlers/sync.js +82 -0
  83. package/dist/src/handlers/system-update.d.ts +2 -0
  84. package/dist/src/handlers/system-update.js +172 -0
  85. package/dist/src/handlers/thread.d.ts +148 -0
  86. package/dist/src/handlers/thread.js +233 -0
  87. package/dist/src/handlers/unified-threads.d.ts +247 -0
  88. package/dist/src/handlers/unified-threads.js +409 -0
  89. package/{src/handlers/vip-suggestions.ts → dist/src/handlers/vip-suggestions.d.ts} +1 -13
  90. package/dist/src/handlers/vip-suggestions.js +16 -0
  91. package/dist/src/index.d.ts +2 -0
  92. package/dist/src/index.js +37 -0
  93. package/{src/json.ts → dist/src/json.d.ts} +1 -4
  94. package/dist/src/json.js +10 -0
  95. package/dist/src/jwt-auth.d.ts +18 -0
  96. package/dist/src/jwt-auth.js +97 -0
  97. package/dist/src/request-context.d.ts +9 -0
  98. package/dist/src/request-context.js +22 -0
  99. package/dist/src/request.d.ts +3 -0
  100. package/dist/src/request.js +7 -0
  101. package/dist/src/response.d.ts +27 -0
  102. package/dist/src/response.js +87 -0
  103. package/dist/src/service/account-deletion.d.ts +22 -0
  104. package/dist/src/service/account-deletion.js +39 -0
  105. package/dist/src/service/compose-sqlite.d.ts +2 -0
  106. package/dist/src/service/compose-sqlite.js +11 -0
  107. package/dist/src/service/create-remit-client.d.ts +95 -0
  108. package/dist/src/service/create-remit-client.js +207 -0
  109. package/dist/src/service/data-client.d.ts +12 -0
  110. package/dist/src/service/data-client.js +44 -0
  111. package/dist/src/service/export-identity.d.ts +3 -0
  112. package/dist/src/service/export-identity.js +35 -0
  113. package/dist/src/service/fire-and-forget.d.ts +54 -0
  114. package/dist/src/service/fire-and-forget.js +38 -0
  115. package/dist/src/service/organize.d.ts +184 -0
  116. package/dist/src/service/organize.js +384 -0
  117. package/dist/src/service/refusal.d.ts +4 -0
  118. package/dist/src/service/refusal.js +20 -0
  119. package/dist/src/service/sender-category.d.ts +51 -0
  120. package/{src/service/sender-category.ts → dist/src/service/sender-category.js} +40 -81
  121. package/dist/src/service/sqs.d.ts +1 -0
  122. package/{src/service/sqs.ts → dist/src/service/sqs.js} +0 -1
  123. package/dist/src/service/trigger-sync.d.ts +51 -0
  124. package/dist/src/service/trigger-sync.js +39 -0
  125. package/dist/src/types.d.ts +49 -0
  126. package/dist/src/types.js +1 -0
  127. package/package.json +113 -98
  128. package/.env.test +0 -4
  129. package/dev-server/content-auth.test.ts +0 -113
  130. package/dev-server/content-auth.ts +0 -54
  131. package/dev-server/content-handler.test.ts +0 -105
  132. package/dev-server/content-handler.ts +0 -79
  133. package/dev-server/content-path.test.ts +0 -37
  134. package/dev-server/content-path.ts +0 -27
  135. package/dev-server/cors.test.ts +0 -48
  136. package/dev-server/cors.ts +0 -25
  137. package/dev-server/keep-alive.test.ts +0 -24
  138. package/dev-server/lambda-helpers.ts +0 -69
  139. package/dev-server/log-output.test.ts +0 -173
  140. package/dev-server/oauth-callback-route.test.ts +0 -66
  141. package/dev-server/relational-health.test.ts +0 -83
  142. package/dev-server/relational-health.ts +0 -39
  143. package/dev-server/server.ts +0 -384
  144. package/dev-server/sync-age.test.ts +0 -91
  145. package/dev-server/sync-age.ts +0 -55
  146. package/dev-server/upload-handler.ts +0 -132
  147. package/dev-server/upload-route.test.ts +0 -196
  148. package/scripts/backfill-classification.ts +0 -91
  149. package/scripts/backfill-list-id.ts +0 -83
  150. package/scripts/config-save.ts +0 -128
  151. package/src/auth.test.ts +0 -12
  152. package/src/auth.ts +0 -92
  153. package/src/config/msoauth.test.ts +0 -48
  154. package/src/config/msoauth.ts +0 -48
  155. package/src/data-backend.test.ts +0 -23
  156. package/src/derive/autoMoved.test.ts +0 -104
  157. package/src/derive/contentSignature.test.ts +0 -161
  158. package/src/derive/contentUrl.test.ts +0 -172
  159. package/src/derive/contentUrl.ts +0 -86
  160. package/src/derive/deriveMuted.test.ts +0 -34
  161. package/src/derive/enrichThreadRows.test.ts +0 -360
  162. package/src/derive/enrichThreadRows.ts +0 -234
  163. package/src/derive/filterThreadCriteria.test.ts +0 -126
  164. package/src/derive/filterThreadCriteria.ts +0 -51
  165. package/src/derive/senderTrust.test.ts +0 -67
  166. package/src/error.test.ts +0 -201
  167. package/src/error.ts +0 -123
  168. package/src/handlers/account-guards.test.ts +0 -67
  169. package/src/handlers/account-guards.ts +0 -169
  170. package/src/handlers/account-oauth-callback.test.ts +0 -155
  171. package/src/handlers/account-oauth-consent.test.ts +0 -336
  172. package/src/handlers/account-oauth-start.test.ts +0 -191
  173. package/src/handlers/account-oauth.test.ts +0 -439
  174. package/src/handlers/account-oauth.ts +0 -635
  175. package/src/handlers/account-overrides.test.ts +0 -88
  176. package/src/handlers/account-overrides.ts +0 -323
  177. package/src/handlers/account-ownership.ts +0 -25
  178. package/src/handlers/account-signature.ts +0 -117
  179. package/src/handlers/account-synced-services.test.ts +0 -245
  180. package/src/handlers/account.ts +0 -552
  181. package/src/handlers/address.test.ts +0 -381
  182. package/src/handlers/address.ts +0 -200
  183. package/src/handlers/calendar-event.test.ts +0 -685
  184. package/src/handlers/calendar-event.ts +0 -738
  185. package/src/handlers/calendar-feed-validators.test.ts +0 -228
  186. package/src/handlers/calendar-feed.test.ts +0 -439
  187. package/src/handlers/calendar-feed.ts +0 -291
  188. package/src/handlers/calendar-sqlite-fixture.ts +0 -36
  189. package/src/handlers/calendar-suggestion.test.ts +0 -1269
  190. package/src/handlers/calendar-suggestion.ts +0 -425
  191. package/src/handlers/calendar.test.ts +0 -1080
  192. package/src/handlers/calendar.ts +0 -517
  193. package/src/handlers/config.test.ts +0 -245
  194. package/src/handlers/config.ts +0 -332
  195. package/src/handlers/ensure-account-config.ts +0 -30
  196. package/src/handlers/filter.test.ts +0 -644
  197. package/src/handlers/filter.ts +0 -518
  198. package/src/handlers/folder-role-appointments.test.ts +0 -438
  199. package/src/handlers/folder-role-appointments.ts +0 -249
  200. package/src/handlers/folder-role-labels.ts +0 -63
  201. package/src/handlers/folder-role.test.ts +0 -209
  202. package/src/handlers/folder-role.ts +0 -80
  203. package/src/handlers/index.ts +0 -83
  204. package/src/handlers/label.test.ts +0 -112
  205. package/src/handlers/label.ts +0 -210
  206. package/src/handlers/mailbox-bindings.ts +0 -111
  207. package/src/handlers/mailbox-rename-refusal.test.ts +0 -247
  208. package/src/handlers/mailbox-settled-target.test.ts +0 -251
  209. package/src/handlers/mailbox.test.ts +0 -280
  210. package/src/handlers/mailbox.ts +0 -581
  211. package/src/handlers/me.test.ts +0 -81
  212. package/src/handlers/me.ts +0 -203
  213. package/src/handlers/message-read-backfill.test.ts +0 -103
  214. package/src/handlers/message.test.ts +0 -131
  215. package/src/handlers/message.ts +0 -1131
  216. package/src/handlers/organize.test.ts +0 -277
  217. package/src/handlers/organize.ts +0 -197
  218. package/src/handlers/outbox-attachment.test.ts +0 -765
  219. package/src/handlers/outbox-attachment.ts +0 -126
  220. package/src/handlers/outbox-list.test.ts +0 -179
  221. package/src/handlers/outbox.test.ts +0 -772
  222. package/src/handlers/outbox.ts +0 -258
  223. package/src/handlers/search.test.ts +0 -161
  224. package/src/handlers/search.ts +0 -105
  225. package/src/handlers/sync-progress.test.ts +0 -205
  226. package/src/handlers/sync-progress.ts +0 -99
  227. package/src/handlers/sync.test.ts +0 -168
  228. package/src/handlers/sync.ts +0 -118
  229. package/src/handlers/system-update.test.ts +0 -497
  230. package/src/handlers/system-update.ts +0 -230
  231. package/src/handlers/thread.test.ts +0 -396
  232. package/src/handlers/thread.ts +0 -427
  233. package/src/handlers/unified-threads-mail-sources.sqlite.test.ts +0 -197
  234. package/src/handlers/unified-threads.test.ts +0 -785
  235. package/src/handlers/unified-threads.ts +0 -669
  236. package/src/index.test.ts +0 -83
  237. package/src/index.ts +0 -228
  238. package/src/jwt-auth.test.ts +0 -152
  239. package/src/jwt-auth.ts +0 -132
  240. package/src/log-redaction.test.ts +0 -144
  241. package/src/openapi-spec.test.ts +0 -118
  242. package/src/request-context.test.ts +0 -61
  243. package/src/request-context.ts +0 -33
  244. package/src/request-pipeline.test.ts +0 -88
  245. package/src/request.ts +0 -10
  246. package/src/response.test.ts +0 -130
  247. package/src/response.ts +0 -144
  248. package/src/service/compose-sqlite.ts +0 -98
  249. package/src/service/config-import.ts +0 -39
  250. package/src/service/create-remit-client.ts +0 -522
  251. package/src/service/data-client.test.ts +0 -97
  252. package/src/service/data-client.ts +0 -58
  253. package/src/service/export-identity.ts +0 -39
  254. package/src/service/filter.ts +0 -40
  255. package/src/service/fire-and-forget.test.ts +0 -126
  256. package/src/service/fire-and-forget.ts +0 -79
  257. package/src/service/localhost-env-config.test.ts +0 -36
  258. package/src/service/organize-queue.ts +0 -98
  259. package/src/service/organize.test.ts +0 -1451
  260. package/src/service/organize.ts +0 -1025
  261. package/src/service/read-path-filter-config.test.ts +0 -243
  262. package/src/service/semantic-capability.test.ts +0 -78
  263. package/src/service/semantic-capability.ts +0 -95
  264. package/src/service/sender-category.test.ts +0 -235
  265. package/src/service/trigger-sync.test.ts +0 -205
  266. package/src/service/trigger-sync.ts +0 -100
  267. package/src/stdout-capture-fixture.ts +0 -40
  268. package/src/types.ts +0 -271
  269. package/tsconfig.json +0 -7
@@ -1,258 +0,0 @@
1
- import type {
2
- CreateOutboxMessageInput,
3
- OutboxMessageResponse,
4
- UpdateOutboxMessageInput,
5
- } from "@remit/api-openapi-types";
6
- import type {
7
- OutboxAttachmentItem,
8
- OutboxMessageItem,
9
- } from "@remit/data-ports";
10
- import { ForbiddenError } from "@remit/data-ports/errors";
11
- import type { APIGatewayProxyEvent } from "aws-lambda";
12
- import type { Context } from "openapi-backend";
13
- import { getAccountConfigIdFromEvent } from "../auth.js";
14
- import { getClient } from "../service/data-client.js";
15
- import type {
16
- OperationHandler,
17
- OutboxAttachmentOperationIds,
18
- OutboxDetailOperationIds,
19
- OutboxOperationIds,
20
- } from "../types.js";
21
- import {
22
- completeOutboxAttachment,
23
- mintOutboxAttachment,
24
- toOutboxAttachmentResponse,
25
- } from "./outbox-attachment.js";
26
-
27
- const toOutboxMessageResponse = (
28
- item: OutboxMessageItem,
29
- attachments: OutboxAttachmentItem[] = [],
30
- ): OutboxMessageResponse => ({
31
- attachments: attachments.map(toOutboxAttachmentResponse),
32
- outboxMessageId: item.outboxMessageId,
33
- accountId: item.accountId,
34
- fromAddress: item.fromAddress,
35
- fromName: item.fromName,
36
- toAddresses: item.toAddresses,
37
- ccAddresses: item.ccAddresses ?? [],
38
- bccAddresses: item.bccAddresses ?? [],
39
- subject: item.subject,
40
- textBody: item.textBody,
41
- htmlBody: item.htmlBody,
42
- inReplyTo: item.inReplyTo,
43
- references: item.references ?? [],
44
- status: item.status,
45
- lastError: item.lastError,
46
- sentAt: item.sentAt,
47
- createdAt: item.createdAt,
48
- updatedAt: item.updatedAt,
49
- });
50
-
51
- export const OutboxOperations: Record<
52
- OutboxOperationIds,
53
- OperationHandler<OutboxOperationIds>
54
- > = {
55
- OutboxOperations_createOutboxMessage: async (
56
- _context: Context,
57
- ...args: unknown[]
58
- ): Promise<OutboxMessageResponse> => {
59
- const event = args[0] as APIGatewayProxyEvent;
60
- const accountConfigId = getAccountConfigIdFromEvent(event);
61
- const input = JSON.parse(event.body ?? "{}") as CreateOutboxMessageInput;
62
-
63
- const client = await getClient();
64
-
65
- const account = await client.account.get(input.accountId);
66
- if (account.accountConfigId !== accountConfigId) {
67
- throw new ForbiddenError(
68
- `Account ${input.accountId} not in account config`,
69
- );
70
- }
71
-
72
- const fromAddress = account.email;
73
-
74
- if (input.sendImmediately) {
75
- const outbox = await client.outboxQueue.createAndSend({
76
- accountId: input.accountId,
77
- accountConfigId,
78
- fromAddress,
79
-
80
- toAddresses: input.toAddresses,
81
- ccAddresses: input.ccAddresses,
82
- bccAddresses: input.bccAddresses,
83
- subject: input.subject,
84
- textBody: input.textBody,
85
- htmlBody: input.htmlBody,
86
- inReplyTo: input.inReplyTo,
87
- references: input.references,
88
- });
89
- return toOutboxMessageResponse(outbox);
90
- }
91
-
92
- const outbox = await client.outboxQueue.createDraft({
93
- accountId: input.accountId,
94
- accountConfigId,
95
- fromAddress,
96
-
97
- toAddresses: input.toAddresses,
98
- ccAddresses: input.ccAddresses,
99
- bccAddresses: input.bccAddresses,
100
- subject: input.subject,
101
- textBody: input.textBody,
102
- htmlBody: input.htmlBody,
103
- inReplyTo: input.inReplyTo,
104
- references: input.references,
105
- });
106
- return toOutboxMessageResponse(outbox);
107
- },
108
-
109
- OutboxOperations_listOutboxMessages: async (
110
- context: Context,
111
- ...args: unknown[]
112
- ) => {
113
- const event = args[0] as APIGatewayProxyEvent;
114
- const accountConfigId = getAccountConfigIdFromEvent(event);
115
- const { continuationToken } = context.request.query as {
116
- continuationToken?: string;
117
- };
118
-
119
- const client = await getClient();
120
-
121
- const accounts =
122
- await client.account.listAllByAccountConfig(accountConfigId);
123
- if (accounts.length === 0) {
124
- return { items: [], continuationToken: null };
125
- }
126
-
127
- const result = await client.outboxMessage.listByAccounts(
128
- accounts.map((account) => account.accountId),
129
- { continuationToken },
130
- );
131
-
132
- return {
133
- items: result.items.map((item) => toOutboxMessageResponse(item)),
134
- continuationToken: result.continuationToken,
135
- };
136
- },
137
- };
138
-
139
- export const OutboxDetailOperations: Record<
140
- OutboxDetailOperationIds,
141
- OperationHandler<OutboxDetailOperationIds>
142
- > = {
143
- OutboxDetailOperations_getOutboxMessage: async (
144
- context: Context,
145
- ...args: unknown[]
146
- ): Promise<OutboxMessageResponse> => {
147
- const event = args[0] as APIGatewayProxyEvent;
148
- const accountConfigId = getAccountConfigIdFromEvent(event);
149
- const { outboxMessageId } = context.request.params as {
150
- outboxMessageId: string;
151
- };
152
-
153
- const client = await getClient();
154
- // Default mode "read": the scoped get refuses a foreign message with
155
- // NotFound (404, no existence leak) — no separate check needed.
156
- const outbox = await client.outboxMessage.get(
157
- accountConfigId,
158
- outboxMessageId,
159
- );
160
- return toOutboxMessageResponse(
161
- outbox,
162
- await client.outboxAttachment.listFor(accountConfigId, outboxMessageId),
163
- );
164
- },
165
-
166
- OutboxDetailOperations_updateOutboxMessage: async (
167
- context: Context,
168
- ...args: unknown[]
169
- ): Promise<OutboxMessageResponse> => {
170
- const event = args[0] as APIGatewayProxyEvent;
171
- const accountConfigId = getAccountConfigIdFromEvent(event);
172
- const { outboxMessageId } = context.request.params as {
173
- outboxMessageId: string;
174
- };
175
- const input = context.request.requestBody as UpdateOutboxMessageInput;
176
-
177
- const client = await getClient();
178
- // updateDraft's own scoped get uses mode "act": a foreign message is
179
- // denied with Forbidden (403), not feigned as NotFound.
180
- const updated = await client.outboxQueue.updateDraft(
181
- accountConfigId,
182
- outboxMessageId,
183
- {
184
- toAddresses: input.toAddresses,
185
- ccAddresses: input.ccAddresses,
186
- bccAddresses: input.bccAddresses,
187
- subject: input.subject,
188
- textBody: input.textBody,
189
- htmlBody: input.htmlBody,
190
- inReplyTo: input.inReplyTo,
191
- references: input.references,
192
- },
193
- );
194
-
195
- // Absent means "leave the files alone" — a body that only carries a subject
196
- // must not strip them. Present states exactly what the draft keeps, so an
197
- // empty list is a real instruction to remove them all.
198
- if (input.attachmentIds !== undefined) {
199
- await client.outboxAttachment.retainOnly(
200
- accountConfigId,
201
- updated.accountId,
202
- outboxMessageId,
203
- input.attachmentIds,
204
- );
205
- }
206
-
207
- return toOutboxMessageResponse(
208
- updated,
209
- await client.outboxAttachment.listFor(accountConfigId, outboxMessageId),
210
- );
211
- },
212
-
213
- OutboxDetailOperations_deleteOutboxMessage: async (
214
- context: Context,
215
- ...args: unknown[]
216
- ) => {
217
- const event = args[0] as APIGatewayProxyEvent;
218
- const accountConfigId = getAccountConfigIdFromEvent(event);
219
- const { outboxMessageId } = context.request.params as {
220
- outboxMessageId: string;
221
- };
222
-
223
- const client = await getClient();
224
- // deleteDraft's own scoped get uses mode "act": a foreign message is
225
- // denied with Forbidden (403), not feigned as NotFound.
226
- await client.outboxQueue.deleteDraft(accountConfigId, outboxMessageId);
227
- return { statusCode: 204 };
228
- },
229
-
230
- OutboxDetailOperations_sendOutboxMessage: async (
231
- context: Context,
232
- ...args: unknown[]
233
- ): Promise<OutboxMessageResponse> => {
234
- const event = args[0] as APIGatewayProxyEvent;
235
- const accountConfigId = getAccountConfigIdFromEvent(event);
236
- const { outboxMessageId } = context.request.params as {
237
- outboxMessageId: string;
238
- };
239
-
240
- const client = await getClient();
241
- // send's own scoped get uses mode "act": a foreign message is denied
242
- // with Forbidden (403), not feigned as NotFound.
243
- const sent = await client.outboxQueue.send(
244
- accountConfigId,
245
- outboxMessageId,
246
- );
247
- return toOutboxMessageResponse(sent);
248
- },
249
-
250
- OutboxDetailOperations_mintOutboxAttachment: mintOutboxAttachment,
251
- };
252
-
253
- export const OutboxAttachmentOperations: Record<
254
- OutboxAttachmentOperationIds,
255
- OperationHandler<OutboxAttachmentOperationIds>
256
- > = {
257
- OutboxAttachmentOperations_completeOutboxAttachment: completeOutboxAttachment,
258
- };
@@ -1,161 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import type {
4
- SearchParams,
5
- SearchResult,
6
- SearchService,
7
- } from "@remit/search-service";
8
- import { toResponse } from "./search.js";
9
-
10
- interface CapturedSearch {
11
- calls: SearchParams[];
12
- }
13
-
14
- const buildFakeSearch = (
15
- results: SearchResult[],
16
- ): { service: SearchService; captured: CapturedSearch } => {
17
- const captured: CapturedSearch = { calls: [] };
18
- const service: SearchService = {
19
- index: async () => {},
20
- prepareVectors: async () => [],
21
- upsertVectors: async () => ({ upserted: 0, skipped: 0 }),
22
- indexIncremental: async () => ({ upserted: 0, skipped: 0 }),
23
- delete: async () => {},
24
- search: async (params) => {
25
- captured.calls.push(params);
26
- return results;
27
- },
28
- };
29
- return { service, captured };
30
- };
31
-
32
- describe("SemanticSearch handler response mapping", () => {
33
- it("maps SearchResult into SemanticSearchResult preserving all fields", () => {
34
- const item: SearchResult = {
35
- messageId: "msg-alice",
36
- threadId: "thread-a",
37
- score: 0.87,
38
- matchedChunkType: "sender",
39
- mailboxIds: ["mb-inbox", "mb-archive"],
40
- sentDate: 1_700_000_000,
41
- };
42
- const out = toResponse(item);
43
- assert.equal(out.messageId, "msg-alice");
44
- assert.equal(out.threadId, "thread-a");
45
- assert.equal(out.score, 0.87);
46
- assert.equal(out.matchedChunkType, "sender");
47
- assert.deepEqual(out.mailboxIds, ["mb-inbox", "mb-archive"]);
48
- assert.equal(out.sentDate, 1_700_000_000);
49
- });
50
-
51
- it("includes fromName and subject when present in SearchResult", () => {
52
- const item: SearchResult = {
53
- messageId: "msg-bob",
54
- threadId: "thread-b",
55
- score: 0.72,
56
- matchedChunkType: "body",
57
- mailboxIds: ["mb-inbox"],
58
- sentDate: 1_700_001_000,
59
- fromName: "Bob Smith",
60
- subject: "Weekly sync",
61
- };
62
- const out = toResponse(item);
63
- assert.equal(out.fromName, "Bob Smith");
64
- assert.equal(out.subject, "Weekly sync");
65
- assert.equal(out.sentDate, 1_700_001_000);
66
- });
67
-
68
- it("echoes category back when present in SearchResult", () => {
69
- const item: SearchResult = {
70
- messageId: "msg-news",
71
- threadId: "thread-news",
72
- score: 0.81,
73
- matchedChunkType: "body",
74
- mailboxIds: ["mb-inbox"],
75
- sentDate: 1_700_003_000,
76
- category: "newsletter",
77
- };
78
- const out = toResponse(item);
79
- assert.equal(out.category, "newsletter");
80
- });
81
-
82
- it("omits category when absent (pre-enrichment vectors)", () => {
83
- const item: SearchResult = {
84
- messageId: "msg-legacy",
85
- threadId: "thread-legacy",
86
- score: 0.4,
87
- matchedChunkType: "body",
88
- mailboxIds: ["mb-archive"],
89
- sentDate: 1_600_000_000,
90
- };
91
- const out = toResponse(item);
92
- assert.equal(out.category, undefined);
93
- });
94
-
95
- it("omits fromName when it is null (sender has no display name)", () => {
96
- const item: SearchResult = {
97
- messageId: "msg-carol",
98
- threadId: "thread-c",
99
- score: 0.6,
100
- matchedChunkType: "sender",
101
- mailboxIds: ["mb-inbox"],
102
- sentDate: 1_700_002_000,
103
- fromName: null,
104
- subject: "No-name sender",
105
- };
106
- const out = toResponse(item);
107
- assert.equal(out.fromName, undefined);
108
- assert.equal(out.subject, "No-name sender");
109
- });
110
-
111
- it("omits fromName and subject when absent (pre-enrichment vectors)", () => {
112
- const item: SearchResult = {
113
- messageId: "msg-legacy",
114
- threadId: "thread-legacy",
115
- score: 0.5,
116
- matchedChunkType: "body",
117
- mailboxIds: ["mb-archive"],
118
- sentDate: 1_600_000_000,
119
- };
120
- const out = toResponse(item);
121
- assert.equal(out.fromName, undefined);
122
- assert.equal(out.subject, undefined);
123
- assert.equal(out.sentDate, 1_600_000_000);
124
- });
125
- });
126
-
127
- describe("SemanticSearch handler search invocation", () => {
128
- it("forwards filters from the request to the search service", async () => {
129
- const { service, captured } = buildFakeSearch([
130
- {
131
- messageId: "msg-bob",
132
- threadId: "thread-b",
133
- score: 0.5,
134
- matchedChunkType: "body",
135
- mailboxIds: ["mb-inbox"],
136
- sentDate: 1_700_000_000,
137
- },
138
- ]);
139
-
140
- const results = await service.search({
141
- query: "alice",
142
- accountConfigId: "acct-1",
143
- mailboxId: "mb-inbox",
144
- sentDateRange: { from: 100, to: 200 },
145
- hasAttachment: true,
146
- category: "newsletter",
147
- limit: 10,
148
- });
149
-
150
- assert.equal(results.length, 1);
151
- assert.equal(captured.calls.length, 1);
152
- const call = captured.calls[0];
153
- assert.equal(call.query, "alice");
154
- assert.equal(call.accountConfigId, "acct-1");
155
- assert.equal(call.mailboxId, "mb-inbox");
156
- assert.deepEqual(call.sentDateRange, { from: 100, to: 200 });
157
- assert.equal(call.hasAttachment, true);
158
- assert.equal(call.category, "newsletter");
159
- assert.equal(call.limit, 10);
160
- });
161
- });
@@ -1,105 +0,0 @@
1
- import type {
2
- MessageCategory,
3
- SemanticSearchResult,
4
- } from "@remit/api-openapi-types";
5
- import type { SearchResult } from "@remit/search-service";
6
- import type { APIGatewayProxyEvent } from "aws-lambda";
7
- import type { Context } from "openapi-backend";
8
- import { getAccountConfigIdFromEvent } from "../auth.js";
9
- import { getClient } from "../service/data-client.js";
10
- import {
11
- isSemanticSearchUnavailable,
12
- noteSemanticCapabilityAbsence,
13
- } from "../service/semantic-capability.js";
14
- import type { OperationHandler, SemanticSearchOperationIds } from "../types.js";
15
-
16
- const DEFAULT_LIMIT = 25;
17
-
18
- export const toResponse = (item: SearchResult): SemanticSearchResult => {
19
- const result: SemanticSearchResult = {
20
- messageId: item.messageId,
21
- threadId: item.threadId,
22
- score: item.score,
23
- matchedChunkType: item.matchedChunkType,
24
- mailboxIds: item.mailboxIds,
25
- sentDate: item.sentDate,
26
- };
27
- // fromName is null for messages with no sender name; exclude undefined (absent from old vectors)
28
- if (item.fromName !== undefined) {
29
- result.fromName = item.fromName ?? undefined;
30
- }
31
- if (item.subject !== undefined) {
32
- result.subject = item.subject;
33
- }
34
- if (item.category !== undefined) {
35
- result.category = item.category;
36
- }
37
- return result;
38
- };
39
-
40
- export const SemanticSearchOperations: Record<
41
- SemanticSearchOperationIds,
42
- OperationHandler<SemanticSearchOperationIds>
43
- > = {
44
- SemanticSearchOperations_semanticSearch: async (
45
- context: Context,
46
- ...args: unknown[]
47
- ) => {
48
- const event = args[0] as APIGatewayProxyEvent;
49
- const accountConfigId = getAccountConfigIdFromEvent(event);
50
- const {
51
- query,
52
- mailboxId,
53
- sentDateFrom,
54
- sentDateTo,
55
- hasAttachment,
56
- hasStars,
57
- isRead,
58
- category,
59
- limit,
60
- } = context.request.query as {
61
- query: string;
62
- mailboxId?: string;
63
- sentDateFrom?: number;
64
- sentDateTo?: number;
65
- hasAttachment?: boolean;
66
- hasStars?: boolean;
67
- isRead?: boolean;
68
- category?: MessageCategory;
69
- limit?: number;
70
- };
71
-
72
- const sentDateRange =
73
- sentDateFrom !== undefined || sentDateTo !== undefined
74
- ? { from: sentDateFrom, to: sentDateTo }
75
- : undefined;
76
-
77
- // Capability gate for the self-host compose profiles, whose backend
78
- // image cannot run the semantic pipeline — see semantic-capability.ts.
79
- if (isSemanticSearchUnavailable()) {
80
- return { items: [] };
81
- }
82
-
83
- let results: SearchResult[];
84
- try {
85
- results = await (await getClient()).search.search({
86
- query,
87
- accountConfigId,
88
- mailboxId,
89
- sentDateRange,
90
- hasAttachment,
91
- hasStars,
92
- isRead,
93
- category,
94
- limit: limit ?? DEFAULT_LIMIT,
95
- });
96
- } catch (error) {
97
- if (!noteSemanticCapabilityAbsence(error)) throw error;
98
- return { items: [] };
99
- }
100
-
101
- return {
102
- items: results.map(toResponse),
103
- };
104
- },
105
- };