@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.
- package/dist/dev-server/content-handler.d.ts +38 -0
- package/dist/dev-server/content-handler.js +46 -0
- package/dist/src/api.d.ts +7 -0
- package/dist/src/api.js +144 -0
- package/dist/src/auth.d.ts +30 -0
- package/dist/src/auth.js +73 -0
- package/dist/src/config/msoauth.d.ts +30 -0
- package/dist/src/config/msoauth.js +30 -0
- package/{src/data-backend.ts → dist/src/data-backend.d.ts} +2 -4
- package/dist/src/data-backend.js +12 -0
- package/{src/derive/autoMoved.ts → dist/src/derive/autoMoved.d.ts} +1 -29
- package/dist/src/derive/autoMoved.js +49 -0
- package/dist/src/derive/contentSignature.d.ts +41 -0
- package/{src/derive/contentSignature.ts → dist/src/derive/contentSignature.js} +27 -72
- package/dist/src/derive/contentUrl.d.ts +46 -0
- package/dist/src/derive/contentUrl.js +46 -0
- package/{src/derive/deriveMuted.ts → dist/src/derive/deriveMuted.d.ts} +1 -3
- package/dist/src/derive/deriveMuted.js +7 -0
- package/dist/src/derive/enrichThreadRows.d.ts +118 -0
- package/dist/src/derive/enrichThreadRows.js +151 -0
- package/dist/src/derive/filterThreadCriteria.d.ts +23 -0
- package/dist/src/derive/filterThreadCriteria.js +24 -0
- package/{src/derive/pendingMoveCounts.ts → dist/src/derive/pendingMoveCounts.d.ts} +5 -53
- package/dist/src/derive/pendingMoveCounts.js +53 -0
- package/{src/derive/senderTrust.ts → dist/src/derive/senderTrust.d.ts} +1 -9
- package/dist/src/derive/senderTrust.js +19 -0
- package/dist/src/error.d.ts +21 -0
- package/dist/src/error.js +85 -0
- package/dist/src/handlers/account-guards.d.ts +36 -0
- package/dist/src/handlers/account-guards.js +107 -0
- package/dist/src/handlers/account-oauth.d.ts +14 -0
- package/dist/src/handlers/account-oauth.js +387 -0
- package/dist/src/handlers/account-overrides.d.ts +53 -0
- package/dist/src/handlers/account-overrides.js +233 -0
- package/dist/src/handlers/account-signature.d.ts +28 -0
- package/dist/src/handlers/account-signature.js +85 -0
- package/dist/src/handlers/account.d.ts +6 -0
- package/dist/src/handlers/account.js +350 -0
- package/dist/src/handlers/address.d.ts +35 -0
- package/dist/src/handlers/address.js +141 -0
- package/dist/src/handlers/calendar-event.d.ts +70 -0
- package/dist/src/handlers/calendar-event.js +425 -0
- package/dist/src/handlers/calendar-feed.d.ts +47 -0
- package/dist/src/handlers/calendar-feed.js +192 -0
- package/dist/src/handlers/calendar-suggestion.d.ts +47 -0
- package/dist/src/handlers/calendar-suggestion.js +212 -0
- package/dist/src/handlers/calendar.d.ts +116 -0
- package/dist/src/handlers/calendar.js +330 -0
- package/dist/src/handlers/config.d.ts +43 -0
- package/dist/src/handlers/config.js +176 -0
- package/dist/src/handlers/ensure-account-config.d.ts +9 -0
- package/dist/src/handlers/ensure-account-config.js +27 -0
- package/dist/src/handlers/filter.d.ts +3 -0
- package/dist/src/handlers/filter.js +103 -0
- package/dist/src/handlers/folder-role-appointments.d.ts +68 -0
- package/dist/src/handlers/folder-role-appointments.js +168 -0
- package/dist/src/handlers/folder-role-labels.d.ts +26 -0
- package/dist/src/handlers/folder-role-labels.js +40 -0
- package/dist/src/handlers/folder-role.d.ts +9 -0
- package/dist/src/handlers/folder-role.js +40 -0
- package/dist/src/handlers/index.d.ts +2 -0
- package/dist/src/handlers/index.js +60 -0
- package/dist/src/handlers/label.d.ts +43 -0
- package/dist/src/handlers/label.js +114 -0
- package/dist/src/handlers/mailbox-bindings.d.ts +41 -0
- package/dist/src/handlers/mailbox-bindings.js +61 -0
- package/dist/src/handlers/mailbox.d.ts +23 -0
- package/dist/src/handlers/mailbox.js +219 -0
- package/dist/src/handlers/me.d.ts +2 -0
- package/dist/src/handlers/me.js +138 -0
- package/dist/src/handlers/message.d.ts +84 -0
- package/dist/src/handlers/message.js +607 -0
- package/dist/src/handlers/organize.d.ts +10 -0
- package/dist/src/handlers/organize.js +112 -0
- package/dist/src/handlers/outbox-attachment.d.ts +23 -0
- package/dist/src/handlers/outbox-attachment.js +81 -0
- package/dist/src/handlers/outbox.d.ts +4 -0
- package/dist/src/handlers/outbox.js +144 -0
- package/dist/src/handlers/sync-progress.d.ts +46 -0
- package/dist/src/handlers/sync-progress.js +63 -0
- package/dist/src/handlers/sync.d.ts +28 -0
- package/dist/src/handlers/sync.js +82 -0
- package/dist/src/handlers/system-update.d.ts +2 -0
- package/dist/src/handlers/system-update.js +172 -0
- package/dist/src/handlers/thread.d.ts +148 -0
- package/dist/src/handlers/thread.js +233 -0
- package/dist/src/handlers/unified-threads.d.ts +247 -0
- package/dist/src/handlers/unified-threads.js +409 -0
- package/{src/handlers/vip-suggestions.ts → dist/src/handlers/vip-suggestions.d.ts} +1 -13
- package/dist/src/handlers/vip-suggestions.js +16 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +37 -0
- package/{src/json.ts → dist/src/json.d.ts} +1 -4
- package/dist/src/json.js +10 -0
- package/dist/src/jwt-auth.d.ts +18 -0
- package/dist/src/jwt-auth.js +97 -0
- package/dist/src/request-context.d.ts +9 -0
- package/dist/src/request-context.js +22 -0
- package/dist/src/request.d.ts +3 -0
- package/dist/src/request.js +7 -0
- package/dist/src/response.d.ts +27 -0
- package/dist/src/response.js +87 -0
- package/dist/src/service/account-deletion.d.ts +22 -0
- package/dist/src/service/account-deletion.js +39 -0
- package/dist/src/service/compose-sqlite.d.ts +2 -0
- package/dist/src/service/compose-sqlite.js +11 -0
- package/dist/src/service/create-remit-client.d.ts +95 -0
- package/dist/src/service/create-remit-client.js +207 -0
- package/dist/src/service/data-client.d.ts +12 -0
- package/dist/src/service/data-client.js +44 -0
- package/dist/src/service/export-identity.d.ts +3 -0
- package/dist/src/service/export-identity.js +35 -0
- package/dist/src/service/fire-and-forget.d.ts +54 -0
- package/dist/src/service/fire-and-forget.js +38 -0
- package/dist/src/service/organize.d.ts +184 -0
- package/dist/src/service/organize.js +384 -0
- package/dist/src/service/refusal.d.ts +4 -0
- package/dist/src/service/refusal.js +20 -0
- package/dist/src/service/sender-category.d.ts +51 -0
- package/{src/service/sender-category.ts → dist/src/service/sender-category.js} +40 -81
- package/dist/src/service/sqs.d.ts +1 -0
- package/{src/service/sqs.ts → dist/src/service/sqs.js} +0 -1
- package/dist/src/service/trigger-sync.d.ts +51 -0
- package/dist/src/service/trigger-sync.js +39 -0
- package/dist/src/types.d.ts +49 -0
- package/dist/src/types.js +1 -0
- package/package.json +113 -98
- package/.env.test +0 -4
- package/dev-server/content-auth.test.ts +0 -113
- package/dev-server/content-auth.ts +0 -54
- package/dev-server/content-handler.test.ts +0 -105
- package/dev-server/content-handler.ts +0 -79
- package/dev-server/content-path.test.ts +0 -37
- package/dev-server/content-path.ts +0 -27
- package/dev-server/cors.test.ts +0 -48
- package/dev-server/cors.ts +0 -25
- package/dev-server/keep-alive.test.ts +0 -24
- package/dev-server/lambda-helpers.ts +0 -69
- package/dev-server/log-output.test.ts +0 -173
- package/dev-server/oauth-callback-route.test.ts +0 -66
- package/dev-server/relational-health.test.ts +0 -83
- package/dev-server/relational-health.ts +0 -39
- package/dev-server/server.ts +0 -384
- package/dev-server/sync-age.test.ts +0 -91
- package/dev-server/sync-age.ts +0 -55
- package/dev-server/upload-handler.ts +0 -132
- package/dev-server/upload-route.test.ts +0 -196
- package/scripts/backfill-classification.ts +0 -91
- package/scripts/backfill-list-id.ts +0 -83
- package/scripts/config-save.ts +0 -128
- package/src/auth.test.ts +0 -12
- package/src/auth.ts +0 -92
- package/src/config/msoauth.test.ts +0 -48
- package/src/config/msoauth.ts +0 -48
- package/src/data-backend.test.ts +0 -23
- package/src/derive/autoMoved.test.ts +0 -104
- package/src/derive/contentSignature.test.ts +0 -161
- package/src/derive/contentUrl.test.ts +0 -172
- package/src/derive/contentUrl.ts +0 -86
- package/src/derive/deriveMuted.test.ts +0 -34
- package/src/derive/enrichThreadRows.test.ts +0 -360
- package/src/derive/enrichThreadRows.ts +0 -234
- package/src/derive/filterThreadCriteria.test.ts +0 -126
- package/src/derive/filterThreadCriteria.ts +0 -51
- package/src/derive/senderTrust.test.ts +0 -67
- package/src/error.test.ts +0 -201
- package/src/error.ts +0 -123
- package/src/handlers/account-guards.test.ts +0 -67
- package/src/handlers/account-guards.ts +0 -169
- package/src/handlers/account-oauth-callback.test.ts +0 -155
- package/src/handlers/account-oauth-consent.test.ts +0 -336
- package/src/handlers/account-oauth-start.test.ts +0 -191
- package/src/handlers/account-oauth.test.ts +0 -439
- package/src/handlers/account-oauth.ts +0 -635
- package/src/handlers/account-overrides.test.ts +0 -88
- package/src/handlers/account-overrides.ts +0 -323
- package/src/handlers/account-ownership.ts +0 -25
- package/src/handlers/account-signature.ts +0 -117
- package/src/handlers/account-synced-services.test.ts +0 -245
- package/src/handlers/account.ts +0 -552
- package/src/handlers/address.test.ts +0 -381
- package/src/handlers/address.ts +0 -200
- package/src/handlers/calendar-event.test.ts +0 -685
- package/src/handlers/calendar-event.ts +0 -738
- package/src/handlers/calendar-feed-validators.test.ts +0 -228
- package/src/handlers/calendar-feed.test.ts +0 -439
- package/src/handlers/calendar-feed.ts +0 -291
- package/src/handlers/calendar-sqlite-fixture.ts +0 -36
- package/src/handlers/calendar-suggestion.test.ts +0 -1269
- package/src/handlers/calendar-suggestion.ts +0 -425
- package/src/handlers/calendar.test.ts +0 -1080
- package/src/handlers/calendar.ts +0 -517
- package/src/handlers/config.test.ts +0 -245
- package/src/handlers/config.ts +0 -332
- package/src/handlers/ensure-account-config.ts +0 -30
- package/src/handlers/filter.test.ts +0 -644
- package/src/handlers/filter.ts +0 -518
- package/src/handlers/folder-role-appointments.test.ts +0 -438
- package/src/handlers/folder-role-appointments.ts +0 -249
- package/src/handlers/folder-role-labels.ts +0 -63
- package/src/handlers/folder-role.test.ts +0 -209
- package/src/handlers/folder-role.ts +0 -80
- package/src/handlers/index.ts +0 -83
- package/src/handlers/label.test.ts +0 -112
- package/src/handlers/label.ts +0 -210
- package/src/handlers/mailbox-bindings.ts +0 -111
- package/src/handlers/mailbox-rename-refusal.test.ts +0 -247
- package/src/handlers/mailbox-settled-target.test.ts +0 -251
- package/src/handlers/mailbox.test.ts +0 -280
- package/src/handlers/mailbox.ts +0 -581
- package/src/handlers/me.test.ts +0 -81
- package/src/handlers/me.ts +0 -203
- package/src/handlers/message-read-backfill.test.ts +0 -103
- package/src/handlers/message.test.ts +0 -131
- package/src/handlers/message.ts +0 -1131
- package/src/handlers/organize.test.ts +0 -277
- package/src/handlers/organize.ts +0 -197
- package/src/handlers/outbox-attachment.test.ts +0 -765
- package/src/handlers/outbox-attachment.ts +0 -126
- package/src/handlers/outbox-list.test.ts +0 -179
- package/src/handlers/outbox.test.ts +0 -772
- package/src/handlers/outbox.ts +0 -258
- package/src/handlers/search.test.ts +0 -161
- package/src/handlers/search.ts +0 -105
- package/src/handlers/sync-progress.test.ts +0 -205
- package/src/handlers/sync-progress.ts +0 -99
- package/src/handlers/sync.test.ts +0 -168
- package/src/handlers/sync.ts +0 -118
- package/src/handlers/system-update.test.ts +0 -497
- package/src/handlers/system-update.ts +0 -230
- package/src/handlers/thread.test.ts +0 -396
- package/src/handlers/thread.ts +0 -427
- package/src/handlers/unified-threads-mail-sources.sqlite.test.ts +0 -197
- package/src/handlers/unified-threads.test.ts +0 -785
- package/src/handlers/unified-threads.ts +0 -669
- package/src/index.test.ts +0 -83
- package/src/index.ts +0 -228
- package/src/jwt-auth.test.ts +0 -152
- package/src/jwt-auth.ts +0 -132
- package/src/log-redaction.test.ts +0 -144
- package/src/openapi-spec.test.ts +0 -118
- package/src/request-context.test.ts +0 -61
- package/src/request-context.ts +0 -33
- package/src/request-pipeline.test.ts +0 -88
- package/src/request.ts +0 -10
- package/src/response.test.ts +0 -130
- package/src/response.ts +0 -144
- package/src/service/compose-sqlite.ts +0 -98
- package/src/service/config-import.ts +0 -39
- package/src/service/create-remit-client.ts +0 -522
- package/src/service/data-client.test.ts +0 -97
- package/src/service/data-client.ts +0 -58
- package/src/service/export-identity.ts +0 -39
- package/src/service/filter.ts +0 -40
- package/src/service/fire-and-forget.test.ts +0 -126
- package/src/service/fire-and-forget.ts +0 -79
- package/src/service/localhost-env-config.test.ts +0 -36
- package/src/service/organize-queue.ts +0 -98
- package/src/service/organize.test.ts +0 -1451
- package/src/service/organize.ts +0 -1025
- package/src/service/read-path-filter-config.test.ts +0 -243
- package/src/service/semantic-capability.test.ts +0 -78
- package/src/service/semantic-capability.ts +0 -95
- package/src/service/sender-category.test.ts +0 -235
- package/src/service/trigger-sync.test.ts +0 -205
- package/src/service/trigger-sync.ts +0 -100
- package/src/stdout-capture-fixture.ts +0 -40
- package/src/types.ts +0 -271
- package/tsconfig.json +0 -7
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
CalendarFeedResponse,
|
|
3
|
-
CalendarFeedStateResponse,
|
|
4
|
-
} from "@remit/api-openapi-types";
|
|
5
|
-
import {
|
|
6
|
-
buildCalendarFeed,
|
|
7
|
-
calendarFeedIsUnchanged,
|
|
8
|
-
calendarFeedIsUnmodifiedSince,
|
|
9
|
-
hashCalendarFeedToken,
|
|
10
|
-
isCalendarFeedToken,
|
|
11
|
-
mintCalendarFeedToken,
|
|
12
|
-
readCalendarFeedToken,
|
|
13
|
-
} from "@remit/calendar-service";
|
|
14
|
-
import type { CalendarFeedTokenItem } from "@remit/data-ports";
|
|
15
|
-
import { NotFoundError } from "@remit/data-ports/errors";
|
|
16
|
-
import type { APIGatewayProxyEvent } from "aws-lambda";
|
|
17
|
-
import { getAccountConfigIdFromEvent } from "../auth.js";
|
|
18
|
-
import { type RawApiResponse, rawApiResponse } from "../response.js";
|
|
19
|
-
import { getClient } from "../service/data-client.js";
|
|
20
|
-
import type {
|
|
21
|
-
CalendarDetailOperationIds,
|
|
22
|
-
CalendarFeedDetailOperationIds,
|
|
23
|
-
CalendarFeedOperationIds,
|
|
24
|
-
OperationHandler,
|
|
25
|
-
} from "../types.js";
|
|
26
|
-
import {
|
|
27
|
-
type CalendarDeps,
|
|
28
|
-
type CalendarOutcome,
|
|
29
|
-
calendarDepsOf,
|
|
30
|
-
findCalendarFor,
|
|
31
|
-
notFound,
|
|
32
|
-
refuseCalendar,
|
|
33
|
-
} from "./calendar.js";
|
|
34
|
-
|
|
35
|
-
const toFeedState = (
|
|
36
|
-
token: CalendarFeedTokenItem,
|
|
37
|
-
): CalendarFeedStateResponse => ({
|
|
38
|
-
calendarId: token.calendarId,
|
|
39
|
-
createdAt: token.createdAt,
|
|
40
|
-
rotatedAt: token.rotatedAt,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Mints the calendar's feed address, or replaces the one it has.
|
|
45
|
-
*
|
|
46
|
-
* The plaintext exists here and nowhere else: the store keeps a digest, so this
|
|
47
|
-
* return value is the only chance anybody has to read the token. Ownership is
|
|
48
|
-
* settled before the mint — a calendar the caller does not hold is absent, not
|
|
49
|
-
* forbidden, which is the same answer `getCalendar` gives it.
|
|
50
|
-
*/
|
|
51
|
-
export const putCalendarFeedFor = async (
|
|
52
|
-
deps: CalendarDeps,
|
|
53
|
-
accountConfigId: string,
|
|
54
|
-
calendarId: string,
|
|
55
|
-
): Promise<CalendarOutcome<CalendarFeedResponse>> => {
|
|
56
|
-
const calendar = await findCalendarFor(deps, accountConfigId, calendarId);
|
|
57
|
-
if (!calendar.ok) return calendar;
|
|
58
|
-
|
|
59
|
-
const secret = mintCalendarFeedToken();
|
|
60
|
-
const stored = await deps.calendarFeedToken.put({
|
|
61
|
-
accountConfigId,
|
|
62
|
-
calendarId,
|
|
63
|
-
tokenHash: secret.tokenHash,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
ok: true,
|
|
68
|
-
value: {
|
|
69
|
-
calendarId: stored.calendarId,
|
|
70
|
-
feedToken: secret.token,
|
|
71
|
-
createdAt: stored.createdAt,
|
|
72
|
-
rotatedAt: stored.rotatedAt,
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/** Whether the calendar has a feed address, and how old it is. */
|
|
78
|
-
export const findCalendarFeedFor = async (
|
|
79
|
-
deps: CalendarDeps,
|
|
80
|
-
accountConfigId: string,
|
|
81
|
-
calendarId: string,
|
|
82
|
-
): Promise<CalendarOutcome<CalendarFeedStateResponse>> => {
|
|
83
|
-
const calendar = await findCalendarFor(deps, accountConfigId, calendarId);
|
|
84
|
-
if (!calendar.ok) return calendar;
|
|
85
|
-
|
|
86
|
-
const stored = await deps.calendarFeedToken.findByCalendar(
|
|
87
|
-
accountConfigId,
|
|
88
|
-
calendarId,
|
|
89
|
-
);
|
|
90
|
-
if (!stored) {
|
|
91
|
-
return refuseCalendar("NotFound", `no feed on calendar ${calendarId}`);
|
|
92
|
-
}
|
|
93
|
-
return { ok: true, value: toFeedState(stored) };
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Revokes the calendar's feed address.
|
|
98
|
-
*
|
|
99
|
-
* A calendar with no feed is refused rather than answered 204: the caller asked
|
|
100
|
-
* for a subscription to stop working, and reporting success for one that was
|
|
101
|
-
* never there reads as confirmation that it has.
|
|
102
|
-
*/
|
|
103
|
-
export const revokeCalendarFeedFor = async (
|
|
104
|
-
deps: CalendarDeps,
|
|
105
|
-
accountConfigId: string,
|
|
106
|
-
calendarId: string,
|
|
107
|
-
): Promise<CalendarOutcome<null>> => {
|
|
108
|
-
const calendar = await findCalendarFor(deps, accountConfigId, calendarId);
|
|
109
|
-
if (!calendar.ok) return calendar;
|
|
110
|
-
|
|
111
|
-
const stored = await deps.calendarFeedToken.findByCalendar(
|
|
112
|
-
accountConfigId,
|
|
113
|
-
calendarId,
|
|
114
|
-
);
|
|
115
|
-
if (!stored) {
|
|
116
|
-
return refuseCalendar("NotFound", `no feed on calendar ${calendarId}`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
await deps.calendarFeedToken.delete(accountConfigId, calendarId);
|
|
120
|
-
return { ok: true, value: null };
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* No feed answers to this address.
|
|
125
|
-
*
|
|
126
|
-
* One answer for an unknown token, a revoked one and a malformed one, with a
|
|
127
|
-
* body that says the same thing to all three: a caller probing addresses learns
|
|
128
|
-
* only whether the one it sent works, which is what it was going to find out
|
|
129
|
-
* anyway.
|
|
130
|
-
*/
|
|
131
|
-
const feedNotFound = (): RawApiResponse =>
|
|
132
|
-
rawApiResponse({
|
|
133
|
-
statusCode: 404,
|
|
134
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
|
135
|
-
body: "no calendar feed at this address\n",
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Serves a calendar to whoever holds its secret address.
|
|
140
|
-
*
|
|
141
|
-
* The token is the whole credential, so a value that cannot be one is refused
|
|
142
|
-
* before anything is hashed, and the digest of what arrived is what the store is
|
|
143
|
-
* asked about — the plaintext is never compared against a stored one because
|
|
144
|
-
* none is stored.
|
|
145
|
-
*
|
|
146
|
-
* `Last-Modified` is the collection's own timestamp, not the newest event in
|
|
147
|
-
* it: an event deleted from a calendar leaves every survivor older than the
|
|
148
|
-
* change, and a validator that moves backwards tells a subscriber its cached
|
|
149
|
-
* copy is still good. The collection is stamped by the same sequence bump every
|
|
150
|
-
* write and every delete goes through, so it only ever moves forward.
|
|
151
|
-
*
|
|
152
|
-
* A row whose collection is gone is the same 404. It should not exist — a
|
|
153
|
-
* calendar's delete takes its token with it, in one transaction — and serving a
|
|
154
|
-
* blank calendar for one would be worse than saying nothing.
|
|
155
|
-
*/
|
|
156
|
-
export const serveCalendarFeed = async (
|
|
157
|
-
deps: CalendarDeps,
|
|
158
|
-
feedToken: string,
|
|
159
|
-
conditions: {
|
|
160
|
-
ifNoneMatch: string | undefined;
|
|
161
|
-
ifModifiedSince: string | undefined;
|
|
162
|
-
},
|
|
163
|
-
): Promise<RawApiResponse> => {
|
|
164
|
-
if (!isCalendarFeedToken(feedToken)) return feedNotFound();
|
|
165
|
-
|
|
166
|
-
const stored = await deps.calendarFeedToken.findByTokenHash(
|
|
167
|
-
hashCalendarFeedToken(feedToken),
|
|
168
|
-
);
|
|
169
|
-
if (!stored) return feedNotFound();
|
|
170
|
-
|
|
171
|
-
const collection = await deps.calendarCollection
|
|
172
|
-
.get(stored.accountConfigId, stored.calendarId)
|
|
173
|
-
.catch((error: unknown) => {
|
|
174
|
-
if (error instanceof NotFoundError) return null;
|
|
175
|
-
throw error;
|
|
176
|
-
});
|
|
177
|
-
if (!collection) return feedNotFound();
|
|
178
|
-
|
|
179
|
-
const objects = await deps.calendarObject.listByCalendar(stored.calendarId);
|
|
180
|
-
const feed = buildCalendarFeed(collection, objects);
|
|
181
|
-
const etag = `"${feed.etag}"`;
|
|
182
|
-
const lastModified = new Date(collection.updatedAt).toUTCString();
|
|
183
|
-
|
|
184
|
-
// `If-None-Match` wins outright when both arrive (RFC 9110 13.2.2): the tag
|
|
185
|
-
// is exact where the date is truncated to the second, so honouring the date
|
|
186
|
-
// as well could only turn a 200 the tag asked for into a 304.
|
|
187
|
-
const unchanged =
|
|
188
|
-
conditions.ifNoneMatch === undefined
|
|
189
|
-
? calendarFeedIsUnmodifiedSince(
|
|
190
|
-
conditions.ifModifiedSince,
|
|
191
|
-
collection.updatedAt,
|
|
192
|
-
)
|
|
193
|
-
: calendarFeedIsUnchanged(conditions.ifNoneMatch, feed.etag);
|
|
194
|
-
|
|
195
|
-
if (unchanged) {
|
|
196
|
-
return rawApiResponse({
|
|
197
|
-
statusCode: 304,
|
|
198
|
-
headers: { ETag: etag, "Last-Modified": lastModified },
|
|
199
|
-
body: "",
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return rawApiResponse({
|
|
204
|
-
statusCode: 200,
|
|
205
|
-
headers: {
|
|
206
|
-
"Content-Type": "text/calendar; charset=utf-8",
|
|
207
|
-
ETag: etag,
|
|
208
|
-
"Last-Modified": lastModified,
|
|
209
|
-
},
|
|
210
|
-
body: feed.icalData,
|
|
211
|
-
});
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
export const CalendarFeedDetailOperations: Record<
|
|
215
|
-
CalendarFeedDetailOperationIds,
|
|
216
|
-
OperationHandler<CalendarDetailOperationIds>
|
|
217
|
-
> = {
|
|
218
|
-
CalendarDetailOperations_getCalendarFeed: async (
|
|
219
|
-
context,
|
|
220
|
-
...args: unknown[]
|
|
221
|
-
) => {
|
|
222
|
-
const event = args[0] as APIGatewayProxyEvent;
|
|
223
|
-
const accountConfigId = getAccountConfigIdFromEvent(event);
|
|
224
|
-
const { calendarId } = context.request.params as { calendarId: string };
|
|
225
|
-
const deps = calendarDepsOf(await getClient());
|
|
226
|
-
|
|
227
|
-
const found = await findCalendarFeedFor(deps, accountConfigId, calendarId);
|
|
228
|
-
if (!found.ok) return notFound(found.error.message);
|
|
229
|
-
return found.value;
|
|
230
|
-
},
|
|
231
|
-
|
|
232
|
-
CalendarDetailOperations_putCalendarFeed: async (
|
|
233
|
-
context,
|
|
234
|
-
...args: unknown[]
|
|
235
|
-
) => {
|
|
236
|
-
const event = args[0] as APIGatewayProxyEvent;
|
|
237
|
-
const accountConfigId = getAccountConfigIdFromEvent(event);
|
|
238
|
-
const { calendarId } = context.request.params as { calendarId: string };
|
|
239
|
-
const deps = calendarDepsOf(await getClient());
|
|
240
|
-
|
|
241
|
-
const minted = await putCalendarFeedFor(deps, accountConfigId, calendarId);
|
|
242
|
-
if (!minted.ok) return notFound(minted.error.message);
|
|
243
|
-
return minted.value;
|
|
244
|
-
},
|
|
245
|
-
|
|
246
|
-
CalendarDetailOperations_revokeCalendarFeed: async (
|
|
247
|
-
context,
|
|
248
|
-
...args: unknown[]
|
|
249
|
-
) => {
|
|
250
|
-
const event = args[0] as APIGatewayProxyEvent;
|
|
251
|
-
const accountConfigId = getAccountConfigIdFromEvent(event);
|
|
252
|
-
const { calendarId } = context.request.params as { calendarId: string };
|
|
253
|
-
const deps = calendarDepsOf(await getClient());
|
|
254
|
-
|
|
255
|
-
const revoked = await revokeCalendarFeedFor(
|
|
256
|
-
deps,
|
|
257
|
-
accountConfigId,
|
|
258
|
-
calendarId,
|
|
259
|
-
);
|
|
260
|
-
if (!revoked.ok) return notFound(revoked.error.message);
|
|
261
|
-
return { statusCode: 204 };
|
|
262
|
-
},
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
export const CalendarFeedOperations: Record<
|
|
266
|
-
CalendarFeedOperationIds,
|
|
267
|
-
OperationHandler<CalendarFeedOperationIds>
|
|
268
|
-
> = {
|
|
269
|
-
CalendarFeedOperations_getCalendarFeedIcal: async (
|
|
270
|
-
context,
|
|
271
|
-
...args: unknown[]
|
|
272
|
-
) => {
|
|
273
|
-
// From the raw path, not from the router's captured parameter: the matcher
|
|
274
|
-
// substitutes the parameter into the literal path and leaves the dot of
|
|
275
|
-
// ".ics" as a regex dot, so /feeds/calendar/<token>Xics routes here too —
|
|
276
|
-
// and answering it would serve the feed at an address nobody was handed.
|
|
277
|
-
const event = args[0] as APIGatewayProxyEvent;
|
|
278
|
-
const feedToken = readCalendarFeedToken(event.path);
|
|
279
|
-
if (feedToken === null) return feedNotFound();
|
|
280
|
-
|
|
281
|
-
const ifNoneMatch = context.request.headers["if-none-match"];
|
|
282
|
-
const ifModifiedSince = context.request.headers["if-modified-since"];
|
|
283
|
-
const deps = calendarDepsOf(await getClient());
|
|
284
|
-
|
|
285
|
-
return serveCalendarFeed(deps, feedToken, {
|
|
286
|
-
ifNoneMatch: typeof ifNoneMatch === "string" ? ifNoneMatch : undefined,
|
|
287
|
-
ifModifiedSince:
|
|
288
|
-
typeof ifModifiedSince === "string" ? ifModifiedSince : undefined,
|
|
289
|
-
});
|
|
290
|
-
},
|
|
291
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { applyShippedMigrations } from "@remit/drizzle-service/test-sqlite";
|
|
5
|
-
import Database from "better-sqlite3";
|
|
6
|
-
import { buildSqliteClient } from "../service/compose-sqlite.js";
|
|
7
|
-
import type { RemitClient } from "../service/data-client.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A handler test's store: the backend's own SQLite composition, over the DDL a
|
|
11
|
-
* self-host deployment actually runs.
|
|
12
|
-
*
|
|
13
|
-
* The migrations are applied rather than pushed from the drizzle table objects,
|
|
14
|
-
* so a handler test exercises the shipped column shapes. The client is built by
|
|
15
|
-
* `compose-sqlite.ts`, the composition root a self-host process boots, so
|
|
16
|
-
* nothing here is a second wiring that could drift from the one that ships.
|
|
17
|
-
*
|
|
18
|
-
* One per test file: every row is scoped by account config, so a test that
|
|
19
|
-
* mints its own account config sees only what it wrote.
|
|
20
|
-
*/
|
|
21
|
-
export const createCalendarSqliteClient = async (): Promise<{
|
|
22
|
-
client: RemitClient;
|
|
23
|
-
cleanup: () => void;
|
|
24
|
-
}> => {
|
|
25
|
-
const directory = mkdtempSync(join(tmpdir(), "remit-calendar-handlers-"));
|
|
26
|
-
const path = join(directory, "remit.db");
|
|
27
|
-
const sqlite = new Database(path);
|
|
28
|
-
applyShippedMigrations(sqlite);
|
|
29
|
-
sqlite.close();
|
|
30
|
-
|
|
31
|
-
process.env.SQLITE_DB_PATH = path;
|
|
32
|
-
return {
|
|
33
|
-
client: await buildSqliteClient(),
|
|
34
|
-
cleanup: () => rmSync(directory, { recursive: true, force: true }),
|
|
35
|
-
};
|
|
36
|
-
};
|