@remit/backend 0.0.136 → 0.0.137

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/backend",
3
- "version": "0.0.136",
3
+ "version": "0.0.137",
4
4
  "description": "Remit Mail Inspector API backend",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -29,6 +29,7 @@ import {
29
29
  assertSettleable,
30
30
  CalendarSuggestionActionOperations,
31
31
  CalendarSuggestionOperations,
32
+ MessageCalendarSuggestionOperations,
32
33
  type MuteSenderDeps,
33
34
  muteSender,
34
35
  settleSuggestion,
@@ -58,6 +59,7 @@ const suggestion = (
58
59
  zoneCertainty: "Explicit",
59
60
  icalData: "BEGIN:VCALENDAR\r\nEND:VCALENDAR\r\n",
60
61
  acceptedCalendarObjectId: "",
62
+ supersededByMessageId: "",
61
63
  createdAt: 1,
62
64
  updatedAt: 1,
63
65
  ...overrides,
@@ -308,12 +310,38 @@ const acceptSuggestion =
308
310
  CalendarSuggestionActionOperations.CalendarSuggestionActionOperations_acceptCalendarSuggestion as Handler;
309
311
  const dismissSuggestion =
310
312
  CalendarSuggestionActionOperations.CalendarSuggestionActionOperations_dismissCalendarSuggestion as Handler;
313
+ const listMessageSuggestions =
314
+ MessageCalendarSuggestionOperations.MessageCalendarSuggestionOperations_listMessageCalendarSuggestions as Handler;
311
315
 
312
316
  interface Card {
313
317
  suggestionId: string;
314
318
  state: string;
319
+ supersededByMessageId: string;
320
+ supersededByThreadId: string;
315
321
  }
316
322
 
323
+ const fileInThread = async (
324
+ accountConfigId: string,
325
+ messageId: string,
326
+ threadId: string,
327
+ ): Promise<void> => {
328
+ await client.threadMessage.create({
329
+ accountConfigId,
330
+ threadId,
331
+ messageId,
332
+ mailboxId: "mbx-inbox",
333
+ uid: 1,
334
+ referenceOrder: 0,
335
+ internalDate: 1,
336
+ sentDate: 1,
337
+ subject: "Invitation: Quarterly review",
338
+ isRead: false,
339
+ isDeleted: false,
340
+ hasAttachment: false,
341
+ hasStars: false,
342
+ });
343
+ };
344
+
317
345
  let client: RemitClient;
318
346
  let cleanup: () => void;
319
347
  let mintedSubs = 0;
@@ -473,6 +501,74 @@ describe("GET /calendar-suggestions", () => {
473
501
  });
474
502
  });
475
503
 
504
+ describe("GET /messages/{messageId}/calendar-suggestions", () => {
505
+ test("names the conversation of the revision that retired a card", async () => {
506
+ const { accountConfigId, event } = anAccount();
507
+ const older = await putSuggestion(accountConfigId, "msg-revision-0");
508
+ await client.calendarSuggestion.supersedeIfPending(
509
+ accountConfigId,
510
+ older.suggestionId,
511
+ "msg-revision-1",
512
+ );
513
+ await fileInThread(accountConfigId, "msg-revision-1", "thread-revision-1");
514
+
515
+ const listed = (await listMessageSuggestions(
516
+ contextOf({ params: { messageId: "msg-revision-0" } }),
517
+ event,
518
+ )) as unknown as { items: Card[] };
519
+
520
+ assert.deepEqual(
521
+ listed.items.map((card) => [
522
+ card.state,
523
+ card.supersededByMessageId,
524
+ card.supersededByThreadId,
525
+ ]),
526
+ [
527
+ [
528
+ CalendarSuggestionState.Superseded,
529
+ "msg-revision-1",
530
+ "thread-revision-1",
531
+ ],
532
+ ],
533
+ );
534
+ });
535
+
536
+ test("names no conversation when the newer message sits in none", async () => {
537
+ const { accountConfigId, event } = anAccount();
538
+ const older = await putSuggestion(accountConfigId, "msg-orphan-0");
539
+ await client.calendarSuggestion.supersedeIfPending(
540
+ accountConfigId,
541
+ older.suggestionId,
542
+ "msg-orphan-1",
543
+ );
544
+
545
+ const listed = (await listMessageSuggestions(
546
+ contextOf({ params: { messageId: "msg-orphan-0" } }),
547
+ event,
548
+ )) as unknown as { items: Card[] };
549
+
550
+ assert.equal(listed.items[0]?.supersededByThreadId, "");
551
+ });
552
+
553
+ test("names no conversation for a card nothing retired", async () => {
554
+ const { accountConfigId, event } = anAccount();
555
+ await putSuggestion(accountConfigId, "msg-current");
556
+
557
+ const listed = (await listMessageSuggestions(
558
+ contextOf({ params: { messageId: "msg-current" } }),
559
+ event,
560
+ )) as unknown as { items: Card[] };
561
+
562
+ assert.deepEqual(
563
+ listed.items.map((card) => [
564
+ card.supersededByMessageId,
565
+ card.supersededByThreadId,
566
+ ]),
567
+ [["", ""]],
568
+ );
569
+ });
570
+ });
571
+
476
572
  describe("POST /calendar-suggestions/{suggestionId}/accept", () => {
477
573
  test("answers not-found for a calendar on another account, before writing anything", async () => {
478
574
  const stranger = anAccount();
@@ -12,6 +12,7 @@ import {
12
12
  type ICalendarSuggestionRepository,
13
13
  type IEnvelopeRepository,
14
14
  type IFilterRepository,
15
+ type IThreadMessageRepository,
15
16
  isSenderMuted,
16
17
  } from "@remit/data-ports";
17
18
  import { BadRequestError } from "@remit/data-ports/errors";
@@ -45,9 +46,26 @@ export const toCalendarSuggestionResponse = (
45
46
  item: CalendarSuggestionItem,
46
47
  ): CalendarSuggestionResponse => {
47
48
  const { icalData: _icalData, ...response } = item;
48
- return response;
49
+ return { ...response, supersededByThreadId: "" };
49
50
  };
50
51
 
52
+ export const toCalendarSuggestionResponses = (
53
+ threads: Pick<IThreadMessageRepository, "findByMessageId">,
54
+ accountConfigId: string,
55
+ items: CalendarSuggestionItem[],
56
+ ): Promise<CalendarSuggestionResponse[]> =>
57
+ Promise.all(
58
+ items.map(async (item) => {
59
+ const response = toCalendarSuggestionResponse(item);
60
+ if (item.supersededByMessageId === "") return response;
61
+ const newer = await threads.findByMessageId(
62
+ accountConfigId,
63
+ item.supersededByMessageId,
64
+ );
65
+ return { ...response, supersededByThreadId: newer?.threadId ?? "" };
66
+ }),
67
+ );
68
+
51
69
  /**
52
70
  * The states a person can move a pending card into. `Superseded` is the
53
71
  * producer's alone — a revision retires a card, a person never does — and the
@@ -177,7 +195,11 @@ export const CalendarSuggestionOperations: Record<
177
195
  );
178
196
 
179
197
  return {
180
- items: page.items.map(toCalendarSuggestionResponse),
198
+ items: await toCalendarSuggestionResponses(
199
+ client.threadMessage,
200
+ accountConfigId,
201
+ page.items,
202
+ ),
181
203
  continuationToken: page.continuationToken,
182
204
  };
183
205
  },
@@ -202,7 +224,11 @@ export const MessageCalendarSuggestionOperations: Record<
202
224
  );
203
225
 
204
226
  return {
205
- items: items.map(toCalendarSuggestionResponse),
227
+ items: await toCalendarSuggestionResponses(
228
+ client.threadMessage,
229
+ accountConfigId,
230
+ items,
231
+ ),
206
232
  continuationToken: undefined,
207
233
  };
208
234
  },