@remit/backend 0.0.144 → 0.0.146

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 (91) hide show
  1. package/dist/src/api.d.ts +0 -2
  2. package/dist/src/api.js +9 -80
  3. package/dist/src/auth.d.ts +13 -19
  4. package/dist/src/auth.js +51 -43
  5. package/dist/src/config/api-config.d.ts +20 -0
  6. package/dist/src/config/api-config.js +1 -0
  7. package/dist/src/config/from-env.d.ts +2 -0
  8. package/dist/src/config/from-env.js +65 -0
  9. package/dist/src/config/msoauth-secrets-manager.d.ts +2 -0
  10. package/dist/src/config/msoauth-secrets-manager.js +28 -0
  11. package/dist/src/config/msoauth.d.ts +18 -29
  12. package/dist/src/config/msoauth.js +4 -28
  13. package/dist/src/derive/contentSignature.d.ts +3 -4
  14. package/dist/src/derive/contentSignature.js +4 -13
  15. package/dist/src/derive/contentUrl.d.ts +0 -13
  16. package/dist/src/derive/contentUrl.js +0 -19
  17. package/dist/src/handlers/account-oauth.d.ts +9 -3
  18. package/dist/src/handlers/account-oauth.js +197 -250
  19. package/dist/src/handlers/account.d.ts +13 -4
  20. package/dist/src/handlers/account.js +26 -39
  21. package/dist/src/handlers/address.d.ts +11 -3
  22. package/dist/src/handlers/address.js +11 -19
  23. package/dist/src/handlers/calendar-event.js +18 -26
  24. package/dist/src/handlers/calendar-feed.d.ts +2 -2
  25. package/dist/src/handlers/calendar-feed.js +24 -32
  26. package/dist/src/handlers/calendar-suggestion.js +18 -26
  27. package/dist/src/handlers/calendar.d.ts +1 -1
  28. package/dist/src/handlers/calendar.js +15 -22
  29. package/dist/src/handlers/config.d.ts +16 -6
  30. package/dist/src/handlers/config.js +23 -35
  31. package/dist/src/handlers/filter.d.ts +16 -3
  32. package/dist/src/handlers/filter.js +17 -32
  33. package/dist/src/handlers/folder-role.js +3 -6
  34. package/dist/src/handlers/index.d.ts +187 -2
  35. package/dist/src/handlers/index.js +6 -4
  36. package/dist/src/handlers/label.js +15 -22
  37. package/dist/src/handlers/mailbox.d.ts +20 -4
  38. package/dist/src/handlers/mailbox.js +18 -26
  39. package/dist/src/handlers/me.d.ts +10 -2
  40. package/dist/src/handlers/me.js +26 -47
  41. package/dist/src/handlers/message.d.ts +78 -6
  42. package/dist/src/handlers/message.js +34 -46
  43. package/dist/src/handlers/organize.d.ts +10 -4
  44. package/dist/src/handlers/organize.js +11 -20
  45. package/dist/src/handlers/outbox-attachment.d.ts +6 -5
  46. package/dist/src/handlers/outbox-attachment.js +11 -15
  47. package/dist/src/handlers/outbox.d.ts +25 -4
  48. package/dist/src/handlers/outbox.js +27 -35
  49. package/dist/src/handlers/sync.d.ts +19 -6
  50. package/dist/src/handlers/sync.js +13 -22
  51. package/dist/src/handlers/system-update.js +14 -27
  52. package/dist/src/handlers/thread.js +9 -14
  53. package/dist/src/handlers/unified-threads.js +3 -6
  54. package/dist/src/index.d.ts +4 -1
  55. package/dist/src/index.js +18 -2
  56. package/dist/src/jwt-auth.d.ts +9 -12
  57. package/dist/src/jwt-auth.js +19 -71
  58. package/dist/src/lambda.d.ts +13 -0
  59. package/dist/src/lambda.js +33 -0
  60. package/dist/src/request.d.ts +8 -2
  61. package/dist/src/request.js +16 -6
  62. package/dist/src/response.d.ts +20 -3
  63. package/dist/src/response.js +15 -22
  64. package/dist/src/serve.d.ts +31 -0
  65. package/dist/src/serve.js +117 -0
  66. package/dist/src/service/account-deletion.d.ts +2 -4
  67. package/dist/src/service/account-deletion.js +3 -9
  68. package/dist/src/service/compose-sqlite.d.ts +2 -1
  69. package/dist/src/service/compose-sqlite.js +5 -3
  70. package/dist/src/service/create-remit-client.d.ts +25 -11
  71. package/dist/src/service/create-remit-client.js +97 -116
  72. package/dist/src/service/data-client.js +3 -5
  73. package/dist/src/service/export-identity.d.ts +2 -1
  74. package/dist/src/service/export-identity.js +4 -6
  75. package/dist/src/service/fire-and-forget.js +1 -2
  76. package/dist/src/service/organize.d.ts +7 -10
  77. package/dist/src/service/organize.js +10 -27
  78. package/dist/src/service/queues.d.ts +12 -0
  79. package/dist/src/service/queues.js +1 -0
  80. package/dist/src/service/shared-deps.d.ts +6 -0
  81. package/dist/src/service/shared-deps.js +26 -0
  82. package/dist/src/service/trigger-sync.d.ts +11 -5
  83. package/dist/src/service/trigger-sync.js +10 -18
  84. package/dist/src/types.d.ts +24 -1
  85. package/package.json +24 -8
  86. package/dist/src/data-backend.d.ts +0 -12
  87. package/dist/src/data-backend.js +0 -12
  88. package/dist/src/request-context.d.ts +0 -9
  89. package/dist/src/request-context.js +0 -22
  90. package/dist/src/service/sqs.d.ts +0 -1
  91. package/dist/src/service/sqs.js +0 -3
@@ -1,6 +1,7 @@
1
1
  import type { AddressResponse, UpdateAddressInput } from "@remit/api-openapi-types";
2
2
  import type { AddressFlags, AddressItem, FlagsMergePatch } from "@remit/data-ports";
3
- import type { AddressDetailOperationIds, AddressOperationIds, OperationHandler } from "../types.js";
3
+ import type { Context } from "openapi-backend";
4
+ import type { HandlerContext } from "../types.js";
4
5
  export declare const toAddressResponse: (item: AddressItem) => AddressResponse;
5
6
  /**
6
7
  * Translate the wire-format `UpdateAddressInput` into a service-level
@@ -31,5 +32,12 @@ export declare const buildFlagsPatch: (input: UpdateAddressInput | undefined) =>
31
32
  * one standing on the Address.
32
33
  */
33
34
  export declare const backApplyCategoryFlag: (patch: FlagsMergePatch) => NonNullable<AddressFlags["category"]> | undefined;
34
- export declare const AddressOperations: Record<AddressOperationIds, OperationHandler<AddressOperationIds>>;
35
- export declare const AddressDetailOperations: Record<AddressDetailOperationIds, OperationHandler<AddressDetailOperationIds>>;
35
+ export declare const AddressOperations: {
36
+ AddressOperations_searchAddresses: (context: Context, ctx: HandlerContext) => Promise<{
37
+ items: import("@remit/api-openapi-types").Components.Schemas.AddressResponse[];
38
+ continuationToken: string | undefined;
39
+ }>;
40
+ };
41
+ export declare const AddressDetailOperations: {
42
+ AddressDetailOperations_updateAddress: (context: Context, ctx: HandlerContext<"accountFanout">) => Promise<import("@remit/api-openapi-types").Components.Schemas.AddressResponse>;
43
+ };
@@ -1,10 +1,5 @@
1
- import { SendMessageCommand } from "@aws-sdk/client-sqs";
2
1
  import { ForbiddenError } from "@remit/data-ports/errors";
3
2
  import { AddressFlagKey } from "@remit/domain-enums";
4
- import { env } from "expect-env";
5
- import { getAccountConfigIdFromEvent } from "../auth.js";
6
- import { getClient } from "../service/data-client.js";
7
- import { sqsClient } from "../service/sqs.js";
8
3
  export const toAddressResponse = (item) => ({
9
4
  addressId: item.addressId,
10
5
  accountConfigId: item.accountConfigId,
@@ -82,11 +77,10 @@ export const backApplyCategoryFlag = (patch) => {
82
77
  return flag;
83
78
  };
84
79
  export const AddressOperations = {
85
- AddressOperations_searchAddresses: async (context, ...args) => {
86
- const event = args[0];
87
- const accountConfigId = getAccountConfigIdFromEvent(event);
80
+ AddressOperations_searchAddresses: async (context, ctx) => {
81
+ const accountConfigId = ctx.identity.accountConfigId;
88
82
  const { q, limit } = context.request.query;
89
- const client = await getClient();
83
+ const client = ctx.client;
90
84
  const result = await client.address.listByAccountConfig({
91
85
  accountConfigId,
92
86
  search: q.toLowerCase(),
@@ -99,12 +93,11 @@ export const AddressOperations = {
99
93
  },
100
94
  };
101
95
  export const AddressDetailOperations = {
102
- AddressDetailOperations_updateAddress: async (context, ...args) => {
103
- const event = args[0];
104
- const accountConfigId = getAccountConfigIdFromEvent(event);
96
+ AddressDetailOperations_updateAddress: async (context, ctx) => {
97
+ const accountConfigId = ctx.identity.accountConfigId;
105
98
  const { addressId } = context.request.params;
106
99
  const body = (context.request.requestBody ?? {});
107
- const client = await getClient();
100
+ const client = ctx.client;
108
101
  // Authorize: address must belong to the caller's accountConfig
109
102
  const existing = await client.address.getAddress(accountConfigId, addressId);
110
103
  if (existing.accountConfigId !== accountConfigId) {
@@ -120,18 +113,17 @@ export const AddressDetailOperations = {
120
113
  // The flag itself is already durable. A queue failure here costs the
121
114
  // user the retroactive pass and nothing else, so the 500 says so and
122
115
  // names the retry — re-sending the same category enqueues a fresh job.
123
- await sqsClient
124
- .send(new SendMessageCommand({
125
- QueueUrl: env.SQS_QUEUE_URL_ACCOUNT_FANOUT,
126
- MessageBody: JSON.stringify({
116
+ await client.queues.accountFanout
117
+ .send({
118
+ body: {
127
119
  type: "SenderCategoryBackApply",
128
120
  accountConfigId,
129
121
  addressId,
130
122
  normalizedEmail: updated.normalizedEmail,
131
123
  category: flag.value,
132
124
  categorySetAt: flag.setAt,
133
- }),
134
- }))
125
+ },
126
+ })
135
127
  .catch((cause) => {
136
128
  throw new Error(`The ${flag.value} override is saved and applies to this sender's next message, but the pass over their existing mail could not be started. Setting the same category again retries it.`, { cause });
137
129
  });
@@ -1,8 +1,6 @@
1
1
  import { applyScopedDelete, applyScopedUpdate, buildEventCalendar, deleteCalendarObject, followingUidOf, listBusySpans, listCalendarInstances, listObjectInstances, OFFSET_BEARING, parseCalendar, prepareCalendarObject, putCalendarObject, readWrittenObject, toOffsetIso, toUtcIso, } from "@remit/calendar-service";
2
2
  import { base36uuid } from "@remit/data-ports/id";
3
3
  import { RecurrenceScope } from "@remit/domain-enums";
4
- import { getAccountConfigIdFromEvent } from "../auth.js";
5
- import { getClient } from "../service/data-client.js";
6
4
  import { badRequest, calendarDepsOf, findCalendarFor, findWritableCalendarFor, listCalendarsFor, notFound, preconditionFailed, refuseCalendar, } from "./calendar.js";
7
5
  /**
8
6
  * The widest window a single read may ask for. A year covers every view the
@@ -323,14 +321,13 @@ const scopedRequestOf = (context) => {
323
321
  };
324
322
  };
325
323
  export const CalendarEventOperations = {
326
- CalendarEventOperations_listCalendarEvents: async (context, ...args) => {
327
- const event = args[0];
328
- const accountConfigId = getAccountConfigIdFromEvent(event);
324
+ CalendarEventOperations_listCalendarEvents: async (context, ctx) => {
325
+ const accountConfigId = ctx.identity.accountConfigId;
329
326
  const query = context.request.query;
330
327
  const window = readWindow(query.from, query.to);
331
328
  if (!window.ok)
332
329
  return badRequest(window.error);
333
- const deps = calendarDepsOf(await getClient());
330
+ const deps = calendarDepsOf(ctx.client);
334
331
  const collections = await collectionsForListing(deps, accountConfigId, readCalendarIds(query.calendarId));
335
332
  if (!collections.ok)
336
333
  return answerRefusal(collections.error);
@@ -344,11 +341,10 @@ export const CalendarEventOperations = {
344
341
  const instances = await listCalendarInstances(deps, collections.value, window.value);
345
342
  return { items: instances.map(toInstanceResponse) };
346
343
  },
347
- CalendarEventOperations_createCalendarEvent: async (context, ...args) => {
348
- const event = args[0];
349
- const accountConfigId = getAccountConfigIdFromEvent(event);
344
+ CalendarEventOperations_createCalendarEvent: async (context, ctx) => {
345
+ const accountConfigId = ctx.identity.accountConfigId;
350
346
  const input = context.request.requestBody;
351
- const deps = calendarEventDepsOf(calendarDepsOf(await getClient()));
347
+ const deps = calendarEventDepsOf(calendarDepsOf(ctx.client));
352
348
  const created = await createCalendarEventFor(deps, accountConfigId, input);
353
349
  if (!created.ok)
354
350
  return answerRefusal(created.error);
@@ -356,13 +352,12 @@ export const CalendarEventOperations = {
356
352
  },
357
353
  };
358
354
  export const CalendarEventDetailOperations = {
359
- CalendarEventDetailOperations_getCalendarEvent: async (context, ...args) => {
360
- const event = args[0];
361
- const accountConfigId = getAccountConfigIdFromEvent(event);
355
+ CalendarEventDetailOperations_getCalendarEvent: async (context, ctx) => {
356
+ const accountConfigId = ctx.identity.accountConfigId;
362
357
  const request = scopedRequestOf(context);
363
358
  if (!request.ok)
364
359
  return badRequest(request.error);
365
- const deps = calendarEventDepsOf(calendarDepsOf(await getClient()));
360
+ const deps = calendarEventDepsOf(calendarDepsOf(ctx.client));
366
361
  if (request.value.calendarId === "") {
367
362
  const located = await locateResource(deps, await listCalendarsFor(deps, accountConfigId), request.value.calendarObjectId);
368
363
  if (!located) {
@@ -375,15 +370,14 @@ export const CalendarEventDetailOperations = {
375
370
  return answerRefusal(resolved.error);
376
371
  return toEventResponse(resolved.value.object);
377
372
  },
378
- CalendarEventDetailOperations_updateCalendarEvent: async (context, ...args) => {
379
- const event = args[0];
380
- const accountConfigId = getAccountConfigIdFromEvent(event);
373
+ CalendarEventDetailOperations_updateCalendarEvent: async (context, ctx) => {
374
+ const accountConfigId = ctx.identity.accountConfigId;
381
375
  const body = context.request
382
376
  .requestBody;
383
377
  const request = scopedRequestOf(context);
384
378
  if (!request.ok)
385
379
  return badRequest(request.error);
386
- const deps = calendarEventDepsOf(calendarDepsOf(await getClient()));
380
+ const deps = calendarEventDepsOf(calendarDepsOf(ctx.client));
387
381
  const updated = await updateCalendarEventFor(deps, accountConfigId, request.value, pickEventUpdate(body));
388
382
  if (!updated.ok)
389
383
  return answerRefusal(updated.error);
@@ -392,13 +386,12 @@ export const CalendarEventDetailOperations = {
392
386
  }
393
387
  return toEventResponse(updated.value);
394
388
  },
395
- CalendarEventDetailOperations_deleteCalendarEvent: async (context, ...args) => {
396
- const event = args[0];
397
- const accountConfigId = getAccountConfigIdFromEvent(event);
389
+ CalendarEventDetailOperations_deleteCalendarEvent: async (context, ctx) => {
390
+ const accountConfigId = ctx.identity.accountConfigId;
398
391
  const request = scopedRequestOf(context);
399
392
  if (!request.ok)
400
393
  return badRequest(request.error);
401
- const deps = calendarEventDepsOf(calendarDepsOf(await getClient()));
394
+ const deps = calendarEventDepsOf(calendarDepsOf(ctx.client));
402
395
  const removed = await deleteCalendarEventFor(deps, accountConfigId, request.value);
403
396
  if (!removed.ok)
404
397
  return answerRefusal(removed.error);
@@ -406,14 +399,13 @@ export const CalendarEventDetailOperations = {
406
399
  },
407
400
  };
408
401
  export const CalendarFreeBusyOperations = {
409
- CalendarFreeBusyOperations_listCalendarFreeBusy: async (context, ...args) => {
410
- const event = args[0];
411
- const accountConfigId = getAccountConfigIdFromEvent(event);
402
+ CalendarFreeBusyOperations_listCalendarFreeBusy: async (context, ctx) => {
403
+ const accountConfigId = ctx.identity.accountConfigId;
412
404
  const query = context.request.query;
413
405
  const window = readWindow(query.from, query.to);
414
406
  if (!window.ok)
415
407
  return badRequest(window.error);
416
- const deps = calendarDepsOf(await getClient());
408
+ const deps = calendarDepsOf(ctx.client);
417
409
  const collections = await listCalendarsFor(deps, accountConfigId);
418
410
  const spans = await listBusySpans(deps, collections, window.value);
419
411
  const items = spans.map((span) => ({
@@ -1,6 +1,6 @@
1
1
  import type { CalendarFeedResponse, CalendarFeedStateResponse } from "@remit/api-openapi-types";
2
2
  import { type RawApiResponse } from "../response.js";
3
- import type { CalendarDetailOperationIds, CalendarFeedDetailOperationIds, CalendarFeedOperationIds, OperationHandler } from "../types.js";
3
+ import type { CalendarDetailOperationIds, CalendarFeedDetailOperationIds, OperationHandler, PublicOperationHandler } from "../types.js";
4
4
  import { type CalendarDeps, type CalendarOutcome } from "./calendar.js";
5
5
  /**
6
6
  * Mints the calendar's feed address, or replaces the one it has.
@@ -44,4 +44,4 @@ export declare const serveCalendarFeed: (deps: CalendarDeps, feedToken: string,
44
44
  ifModifiedSince: string | undefined;
45
45
  }) => Promise<RawApiResponse>;
46
46
  export declare const CalendarFeedDetailOperations: Record<CalendarFeedDetailOperationIds, OperationHandler<CalendarDetailOperationIds>>;
47
- export declare const CalendarFeedOperations: Record<CalendarFeedOperationIds, OperationHandler<CalendarFeedOperationIds>>;
47
+ export declare const getCalendarFeedIcal: PublicOperationHandler;
@@ -1,8 +1,6 @@
1
1
  import { buildCalendarFeed, calendarFeedIsUnchanged, calendarFeedIsUnmodifiedSince, hashCalendarFeedToken, isCalendarFeedToken, mintCalendarFeedToken, readCalendarFeedToken, } from "@remit/calendar-service";
2
2
  import { NotFoundError } from "@remit/data-ports/errors";
3
- import { getAccountConfigIdFromEvent } from "../auth.js";
4
3
  import { rawApiResponse } from "../response.js";
5
- import { getClient } from "../service/data-client.js";
6
4
  import { calendarDepsOf, findCalendarFor, notFound, refuseCalendar, } from "./calendar.js";
7
5
  const toFeedState = (token) => ({
8
6
  calendarId: token.calendarId,
@@ -140,53 +138,47 @@ export const serveCalendarFeed = async (deps, feedToken, conditions) => {
140
138
  });
141
139
  };
142
140
  export const CalendarFeedDetailOperations = {
143
- CalendarDetailOperations_getCalendarFeed: async (context, ...args) => {
144
- const event = args[0];
145
- const accountConfigId = getAccountConfigIdFromEvent(event);
141
+ CalendarDetailOperations_getCalendarFeed: async (context, ctx) => {
142
+ const accountConfigId = ctx.identity.accountConfigId;
146
143
  const { calendarId } = context.request.params;
147
- const deps = calendarDepsOf(await getClient());
144
+ const deps = calendarDepsOf(ctx.client);
148
145
  const found = await findCalendarFeedFor(deps, accountConfigId, calendarId);
149
146
  if (!found.ok)
150
147
  return notFound(found.error.message);
151
148
  return found.value;
152
149
  },
153
- CalendarDetailOperations_putCalendarFeed: async (context, ...args) => {
154
- const event = args[0];
155
- const accountConfigId = getAccountConfigIdFromEvent(event);
150
+ CalendarDetailOperations_putCalendarFeed: async (context, ctx) => {
151
+ const accountConfigId = ctx.identity.accountConfigId;
156
152
  const { calendarId } = context.request.params;
157
- const deps = calendarDepsOf(await getClient());
153
+ const deps = calendarDepsOf(ctx.client);
158
154
  const minted = await putCalendarFeedFor(deps, accountConfigId, calendarId);
159
155
  if (!minted.ok)
160
156
  return notFound(minted.error.message);
161
157
  return minted.value;
162
158
  },
163
- CalendarDetailOperations_revokeCalendarFeed: async (context, ...args) => {
164
- const event = args[0];
165
- const accountConfigId = getAccountConfigIdFromEvent(event);
159
+ CalendarDetailOperations_revokeCalendarFeed: async (context, ctx) => {
160
+ const accountConfigId = ctx.identity.accountConfigId;
166
161
  const { calendarId } = context.request.params;
167
- const deps = calendarDepsOf(await getClient());
162
+ const deps = calendarDepsOf(ctx.client);
168
163
  const revoked = await revokeCalendarFeedFor(deps, accountConfigId, calendarId);
169
164
  if (!revoked.ok)
170
165
  return notFound(revoked.error.message);
171
166
  return { statusCode: 204 };
172
167
  },
173
168
  };
174
- export const CalendarFeedOperations = {
175
- CalendarFeedOperations_getCalendarFeedIcal: async (context, ...args) => {
176
- // From the raw path, not from the router's captured parameter: the matcher
177
- // substitutes the parameter into the literal path and leaves the dot of
178
- // ".ics" as a regex dot, so /feeds/calendar/<token>Xics routes here too —
179
- // and answering it would serve the feed at an address nobody was handed.
180
- const event = args[0];
181
- const feedToken = readCalendarFeedToken(event.path);
182
- if (feedToken === null)
183
- return feedNotFound();
184
- const ifNoneMatch = context.request.headers["if-none-match"];
185
- const ifModifiedSince = context.request.headers["if-modified-since"];
186
- const deps = calendarDepsOf(await getClient());
187
- return serveCalendarFeed(deps, feedToken, {
188
- ifNoneMatch: typeof ifNoneMatch === "string" ? ifNoneMatch : undefined,
189
- ifModifiedSince: typeof ifModifiedSince === "string" ? ifModifiedSince : undefined,
190
- });
191
- },
169
+ export const getCalendarFeedIcal = async (context, ctx) => {
170
+ // From the raw path, not from the router's captured parameter: the matcher
171
+ // substitutes the parameter into the literal path and leaves the dot of
172
+ // ".ics" as a regex dot, so /feeds/calendar/<token>Xics routes here too —
173
+ // and answering it would serve the feed at an address nobody was handed.
174
+ const feedToken = readCalendarFeedToken(context.request.path);
175
+ if (feedToken === null)
176
+ return feedNotFound();
177
+ const ifNoneMatch = context.request.headers["if-none-match"];
178
+ const ifModifiedSince = context.request.headers["if-modified-since"];
179
+ const deps = calendarDepsOf(ctx.client);
180
+ return serveCalendarFeed(deps, feedToken, {
181
+ ifNoneMatch: typeof ifNoneMatch === "string" ? ifNoneMatch : undefined,
182
+ ifModifiedSince: typeof ifModifiedSince === "string" ? ifModifiedSince : undefined,
183
+ });
192
184
  };
@@ -2,8 +2,6 @@ import { acceptCalendarSuggestion, answersOvertakenBy, correctCalendarSuggestion
2
2
  import { isSenderMuted, } from "@remit/data-ports";
3
3
  import { BadRequestError } from "@remit/data-ports/errors";
4
4
  import { CalendarInviteAnswer, CalendarInviteMethod, CalendarSource, CalendarSuggestionState, FilterClauseField, FilterMatchOperator, FilterScope, FilterState, } from "@remit/domain-enums";
5
- import { getAccountConfigIdFromEvent } from "../auth.js";
6
- import { getClient } from "../service/data-client.js";
7
5
  import { pickEventUpdate } from "./calendar-event.js";
8
6
  /**
9
7
  * The raw invitation bytes stay on the server. A client renders the projected
@@ -102,11 +100,10 @@ export const settleSuggestion = async (repo, accountConfigId, suggestionId, stat
102
100
  });
103
101
  };
104
102
  export const CalendarSuggestionOperations = {
105
- CalendarSuggestionOperations_listCalendarSuggestions: async (context, ...args) => {
106
- const event = args[0];
107
- const accountConfigId = getAccountConfigIdFromEvent(event);
103
+ CalendarSuggestionOperations_listCalendarSuggestions: async (context, ctx) => {
104
+ const accountConfigId = ctx.identity.accountConfigId;
108
105
  const { state, continuationToken } = context.request.query;
109
- const client = await getClient();
106
+ const client = ctx.client;
110
107
  const page = await client.calendarSuggestion.listByState(accountConfigId, state, {
111
108
  continuationToken,
112
109
  endsAfter: state === CalendarSuggestionState.Pending
@@ -120,11 +117,10 @@ export const CalendarSuggestionOperations = {
120
117
  },
121
118
  };
122
119
  export const MessageCalendarSuggestionOperations = {
123
- MessageCalendarSuggestionOperations_listMessageCalendarSuggestions: async (context, ...args) => {
124
- const event = args[0];
125
- const accountConfigId = getAccountConfigIdFromEvent(event);
120
+ MessageCalendarSuggestionOperations_listMessageCalendarSuggestions: async (context, ctx) => {
121
+ const accountConfigId = ctx.identity.accountConfigId;
126
122
  const { messageId } = context.request.params;
127
- const client = await getClient();
123
+ const client = ctx.client;
128
124
  const items = await client.calendarSuggestion.listByMessage(accountConfigId, messageId);
129
125
  return {
130
126
  items: await toCalendarSuggestionResponses(client, accountConfigId, items),
@@ -133,13 +129,12 @@ export const MessageCalendarSuggestionOperations = {
133
129
  },
134
130
  };
135
131
  export const CalendarSuggestionActionOperations = {
136
- CalendarSuggestionActionOperations_acceptCalendarSuggestion: async (context, ...args) => {
137
- const event = args[0];
138
- const accountConfigId = getAccountConfigIdFromEvent(event);
132
+ CalendarSuggestionActionOperations_acceptCalendarSuggestion: async (context, ctx) => {
133
+ const accountConfigId = ctx.identity.accountConfigId;
139
134
  const { suggestionId } = context.request.params;
140
135
  const { calendarId, answer = CalendarInviteAnswer.Accepted } = context
141
136
  .request.requestBody;
142
- const client = await getClient();
137
+ const client = ctx.client;
143
138
  const suggestion = await client.calendarSuggestion.get(accountConfigId, suggestionId);
144
139
  if (answer === CalendarInviteAnswer.Tentative &&
145
140
  suggestion.method === CalendarInviteMethod.Cancel) {
@@ -174,31 +169,28 @@ export const CalendarSuggestionActionOperations = {
174
169
  }
175
170
  return respondOne(client, accountConfigId, accepted.value.suggestion);
176
171
  },
177
- CalendarSuggestionActionOperations_declineCalendarSuggestion: async (context, ...args) => {
178
- const event = args[0];
179
- const accountConfigId = getAccountConfigIdFromEvent(event);
172
+ CalendarSuggestionActionOperations_declineCalendarSuggestion: async (context, ctx) => {
173
+ const accountConfigId = ctx.identity.accountConfigId;
180
174
  const { suggestionId } = context.request.params;
181
- const client = await getClient();
175
+ const client = ctx.client;
182
176
  const declined = await settleSuggestion(client.calendarSuggestion, accountConfigId, suggestionId, CalendarSuggestionState.Declined);
183
177
  return respondOne(client, accountConfigId, declined);
184
178
  },
185
- CalendarSuggestionActionOperations_dismissCalendarSuggestion: async (context, ...args) => {
186
- const event = args[0];
187
- const accountConfigId = getAccountConfigIdFromEvent(event);
179
+ CalendarSuggestionActionOperations_dismissCalendarSuggestion: async (context, ctx) => {
180
+ const accountConfigId = ctx.identity.accountConfigId;
188
181
  const { suggestionId } = context.request.params;
189
182
  const body = (context.request.requestBody ?? {});
190
- const client = await getClient();
183
+ const client = ctx.client;
191
184
  const dismissed = await settleSuggestion(client.calendarSuggestion, accountConfigId, suggestionId, CalendarSuggestionState.Dismissed);
192
185
  if (body.muteSender) {
193
186
  await muteSender(client, accountConfigId, dismissed.messageId);
194
187
  }
195
188
  return respondOne(client, accountConfigId, dismissed);
196
189
  },
197
- CalendarSuggestionActionOperations_reopenCalendarSuggestion: async (context, ...args) => {
198
- const event = args[0];
199
- const accountConfigId = getAccountConfigIdFromEvent(event);
190
+ CalendarSuggestionActionOperations_reopenCalendarSuggestion: async (context, ctx) => {
191
+ const accountConfigId = ctx.identity.accountConfigId;
200
192
  const { suggestionId } = context.request.params;
201
- const client = await getClient();
193
+ const client = ctx.client;
202
194
  const suggestion = await client.calendarSuggestion.get(accountConfigId, suggestionId);
203
195
  const reopened = await reopenCalendarSuggestion(client.calendarStore, {
204
196
  accountConfigId,
@@ -58,7 +58,7 @@ export declare const preconditionFailed: (message: string) => {
58
58
  };
59
59
  };
60
60
  /** The calendar half of the client, named so a handler takes only what it uses. */
61
- export declare const calendarDepsOf: (client: RemitClient) => CalendarDeps;
61
+ export declare const calendarDepsOf: (client: RemitClient<never>) => CalendarDeps;
62
62
  /**
63
63
  * Every collection the account config holds, provisioning the default one when
64
64
  * it holds none.
@@ -1,9 +1,7 @@
1
1
  import { DEFAULT_CALENDAR_URL_SEGMENT, isResolvableZone, prepareCalendarObject, provisionDefaultCalendar, readCalendarFeed, readSubscriptionUrl, writeCalendarFeed, } from "@remit/calendar-service";
2
2
  import { normalizeCalendarUrlSegment } from "@remit/data-ports/id";
3
3
  import { CalendarSource } from "@remit/domain-enums";
4
- import { getAccountConfigIdFromEvent } from "../auth.js";
5
4
  import { defaultErrorCode } from "../error.js";
6
- import { getClient } from "../service/data-client.js";
7
5
  export const refuseCalendar = (code, message) => ({ ok: false, error: { code, message } });
8
6
  /**
9
7
  * `CalendarRefusal.code` is this module's and `@remit/calendar-service`'s own
@@ -271,18 +269,16 @@ export const updateCalendarFor = async (deps, accountConfigId, calendarId, body)
271
269
  };
272
270
  };
273
271
  export const CalendarOperations = {
274
- CalendarOperations_listCalendars: async (_context, ...args) => {
275
- const event = args[0];
276
- const accountConfigId = getAccountConfigIdFromEvent(event);
277
- const deps = calendarDepsOf(await getClient());
272
+ CalendarOperations_listCalendars: async (_context, ctx) => {
273
+ const accountConfigId = ctx.identity.accountConfigId;
274
+ const deps = calendarDepsOf(ctx.client);
278
275
  const items = await listCalendarsFor(deps, accountConfigId);
279
276
  return { items: items.map(toCalendarResponse) };
280
277
  },
281
- CalendarOperations_createCalendar: async (context, ...args) => {
282
- const event = args[0];
283
- const accountConfigId = getAccountConfigIdFromEvent(event);
278
+ CalendarOperations_createCalendar: async (context, ctx) => {
279
+ const accountConfigId = ctx.identity.accountConfigId;
284
280
  const input = context.request.requestBody;
285
- const deps = calendarDepsOf(await getClient());
281
+ const deps = calendarDepsOf(ctx.client);
286
282
  const created = await createCalendarFor(deps, accountConfigId, input);
287
283
  if (!created.ok)
288
284
  return badRequest(created.error);
@@ -290,22 +286,20 @@ export const CalendarOperations = {
290
286
  },
291
287
  };
292
288
  export const CalendarDetailOperations = {
293
- CalendarDetailOperations_getCalendar: async (context, ...args) => {
294
- const event = args[0];
295
- const accountConfigId = getAccountConfigIdFromEvent(event);
289
+ CalendarDetailOperations_getCalendar: async (context, ctx) => {
290
+ const accountConfigId = ctx.identity.accountConfigId;
296
291
  const { calendarId } = context.request.params;
297
- const deps = calendarDepsOf(await getClient());
292
+ const deps = calendarDepsOf(ctx.client);
298
293
  const found = await findCalendarFor(deps, accountConfigId, calendarId);
299
294
  if (!found.ok)
300
295
  return notFound(found.error.message);
301
296
  return toCalendarResponse(found.value);
302
297
  },
303
- CalendarDetailOperations_updateCalendar: async (context, ...args) => {
304
- const event = args[0];
305
- const accountConfigId = getAccountConfigIdFromEvent(event);
298
+ CalendarDetailOperations_updateCalendar: async (context, ctx) => {
299
+ const accountConfigId = ctx.identity.accountConfigId;
306
300
  const { calendarId } = context.request.params;
307
301
  const body = context.request.requestBody;
308
- const deps = calendarDepsOf(await getClient());
302
+ const deps = calendarDepsOf(ctx.client);
309
303
  const updated = await updateCalendarFor(deps, accountConfigId, calendarId, body);
310
304
  if (!updated.ok) {
311
305
  return updated.error.code === "NotFound"
@@ -314,11 +308,10 @@ export const CalendarDetailOperations = {
314
308
  }
315
309
  return toCalendarResponse(updated.value);
316
310
  },
317
- CalendarDetailOperations_deleteCalendar: async (context, ...args) => {
318
- const event = args[0];
319
- const accountConfigId = getAccountConfigIdFromEvent(event);
311
+ CalendarDetailOperations_deleteCalendar: async (context, ctx) => {
312
+ const accountConfigId = ctx.identity.accountConfigId;
320
313
  const { calendarId } = context.request.params;
321
- const deps = calendarDepsOf(await getClient());
314
+ const deps = calendarDepsOf(ctx.client);
322
315
  const removed = await deleteCalendarFor(deps, accountConfigId, calendarId);
323
316
  if (!removed.ok) {
324
317
  return removed.error.code === "NotFound"
@@ -1,10 +1,13 @@
1
- import type { SQSClient } from "@aws-sdk/client-sqs";
1
+ import type { ConfigDescriptionResponse, ConfigImportReport } from "@remit/api-openapi-types";
2
+ import type { ReaderConfigDocument } from "@remit/config-format";
3
+ import type { FifoQueueProducer } from "@remit/data-ports";
2
4
  import { type StoredCredentialFields } from "@remit/mailbox-service/account-credentials";
3
- import type { ConfigOperationIds, OperationHandler } from "../types.js";
5
+ import type { Context } from "openapi-backend";
6
+ import { type SyncMailboxesEvent } from "../service/trigger-sync.js";
7
+ import type { HandlerContext } from "../types.js";
4
8
  type StructuredLog = (fields: Record<string, unknown>, message: string) => void;
5
9
  interface ConfigSyncTriggerDeps {
6
- sqsClient: SQSClient;
7
- queueUrl: string;
10
+ queue: FifoQueueProducer<SyncMailboxesEvent>;
8
11
  logger: {
9
12
  info: StructuredLog;
10
13
  error: StructuredLog;
@@ -38,6 +41,13 @@ interface ConfigSyncTriggerDeps {
38
41
  */
39
42
  export declare const triggerConfigLoadSyncs: (accountConfigId: string, accounts: ReadonlyArray<{
40
43
  accountId: string;
41
- } & StoredCredentialFields>, deps?: ConfigSyncTriggerDeps) => Promise<void>;
42
- export declare const ConfigOperations: Record<ConfigOperationIds, OperationHandler<ConfigOperationIds>>;
44
+ } & StoredCredentialFields>, deps: ConfigSyncTriggerDeps) => Promise<void>;
45
+ export declare const ConfigOperations: {
46
+ ConfigOperations_getConfig: (_context: Context, ctx: HandlerContext<"sync">) => Promise<ConfigDescriptionResponse>;
47
+ ConfigOperations_exportConfig: (_context: Context, ctx: HandlerContext) => Promise<{
48
+ schemaVersion: number;
49
+ document: ReaderConfigDocument;
50
+ }>;
51
+ ConfigOperations_importConfig: (context: Context, ctx: HandlerContext) => Promise<ConfigImportReport>;
52
+ };
43
53
  export {};