@dereekb/firebase 13.30.0 → 13.32.0
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/eslint/package.json +3 -3
- package/index.cjs.js +1066 -312
- package/index.esm.js +1034 -315
- package/package.json +5 -5
- package/src/lib/common/auth/oidc/oidc.profile.d.ts +106 -0
- package/src/lib/model/notification/index.d.ts +2 -0
- package/src/lib/model/notification/notification.api.d.ts +102 -0
- package/src/lib/model/notification/notification.api.error.d.ts +15 -0
- package/src/lib/model/notification/notification.d.ts +11 -0
- package/src/lib/model/notification/notification.healthcheck.d.ts +616 -0
- package/src/lib/model/notification/notification.healthcheck.mailgun.d.ts +57 -0
- package/test/package.json +6 -6
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.healthcheck
|
|
3
|
+
*
|
|
4
|
+
* Types describing the outcome of a notification delivery health check — a self-serve
|
|
5
|
+
* diagnosis of why a given user is or is not receiving notifications on each delivery method.
|
|
6
|
+
*
|
|
7
|
+
* A health check produces one {@link NotificationDeliveryHealthCheckResult} per delivery method
|
|
8
|
+
* ({@link NotificationDeliveryMethod}), each carrying zero or more {@link NotificationHealthCheckIssue}
|
|
9
|
+
* findings and, optionally, a {@link NotificationHealthCheckProbe} describing a real test message
|
|
10
|
+
* that was dispatched through that method.
|
|
11
|
+
*
|
|
12
|
+
* Issue codes are intentionally open-ended: {@link KnownNotificationHealthCheckIssueCode} covers the
|
|
13
|
+
* checks the library performs itself, while apps and delivery providers are free to emit their own
|
|
14
|
+
* codes for provider-specific findings (e.g. an address on a Mailgun suppression list).
|
|
15
|
+
*/
|
|
16
|
+
import { type Maybe, type Minutes, type Seconds } from '@dereekb/util';
|
|
17
|
+
import { type NotificationTemplateType } from './notification.id';
|
|
18
|
+
/**
|
|
19
|
+
* A delivery method (channel) that notifications can be sent through.
|
|
20
|
+
*
|
|
21
|
+
* The values mirror the per-method flags on {@link NotificationBoxRecipientTemplateConfig}
|
|
22
|
+
* (`se`/`st`/`sp`/`sn`), so a method maps directly onto the config field that gates it.
|
|
23
|
+
*/
|
|
24
|
+
export declare enum NotificationDeliveryMethod {
|
|
25
|
+
/**
|
|
26
|
+
* Email delivery. Gated by `se`.
|
|
27
|
+
*/
|
|
28
|
+
EMAIL = "e",
|
|
29
|
+
/**
|
|
30
|
+
* Text/SMS delivery. Gated by `st`.
|
|
31
|
+
*/
|
|
32
|
+
TEXT = "t",
|
|
33
|
+
/**
|
|
34
|
+
* Push notification delivery. Gated by `sp`.
|
|
35
|
+
*/
|
|
36
|
+
PUSH = "p",
|
|
37
|
+
/**
|
|
38
|
+
* In-app delivery to a NotificationSummary. Gated by `sn`.
|
|
39
|
+
*/
|
|
40
|
+
NOTIFICATION_SUMMARY = "n"
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* All delivery methods, in the order a report should present them.
|
|
44
|
+
*/
|
|
45
|
+
export declare const ALL_NOTIFICATION_DELIVERY_METHODS: NotificationDeliveryMethod[];
|
|
46
|
+
/**
|
|
47
|
+
* A value held per delivery method, for the methods it is known for.
|
|
48
|
+
*
|
|
49
|
+
* Partial because a health check only covers the methods it was asked about, so anything derived
|
|
50
|
+
* from one covers those methods only.
|
|
51
|
+
*
|
|
52
|
+
* @template T - The per-method value.
|
|
53
|
+
*/
|
|
54
|
+
export type NotificationDeliveryMethodMap<T> = Partial<Record<NotificationDeliveryMethod, T>>;
|
|
55
|
+
/**
|
|
56
|
+
* The outcome of a health check, or of one individual finding within it.
|
|
57
|
+
*/
|
|
58
|
+
export declare enum NotificationHealthCheckStatus {
|
|
59
|
+
/**
|
|
60
|
+
* Everything that was checked looks healthy.
|
|
61
|
+
*/
|
|
62
|
+
OK = "ok",
|
|
63
|
+
/**
|
|
64
|
+
* Something looks off, but delivery is probably still working.
|
|
65
|
+
*/
|
|
66
|
+
WARNING = "warn",
|
|
67
|
+
/**
|
|
68
|
+
* Delivery is blocked or broken.
|
|
69
|
+
*/
|
|
70
|
+
ERROR = "error",
|
|
71
|
+
/**
|
|
72
|
+
* Waiting on an asynchronous result, such as an in-flight delivery probe.
|
|
73
|
+
*/
|
|
74
|
+
PENDING = "pending",
|
|
75
|
+
/**
|
|
76
|
+
* Not checked. Either the method is not configured for this app, or no check was available.
|
|
77
|
+
*/
|
|
78
|
+
SKIPPED = "skipped",
|
|
79
|
+
/**
|
|
80
|
+
* The check ran but could not reach a conclusion, such as when a provider API was unreachable.
|
|
81
|
+
*/
|
|
82
|
+
UNKNOWN = "unknown"
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Severity ranking used to roll several statuses up into one.
|
|
86
|
+
*
|
|
87
|
+
* Higher wins. `ERROR` outranks `PENDING` so that a method with a known problem is not masked by an
|
|
88
|
+
* unrelated in-flight probe, and `SKIPPED` ranks lowest so an unconfigured method never drags a
|
|
89
|
+
* report down.
|
|
90
|
+
*/
|
|
91
|
+
export declare const NOTIFICATION_HEALTH_CHECK_STATUS_SEVERITY: Record<NotificationHealthCheckStatus, number>;
|
|
92
|
+
/**
|
|
93
|
+
* Rolls a set of statuses up into the single most severe one.
|
|
94
|
+
*
|
|
95
|
+
* @param statuses - The statuses to roll up.
|
|
96
|
+
* @returns The most severe status, or {@link NotificationHealthCheckStatus.SKIPPED} if none were given.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* rollupNotificationHealthCheckStatus([NotificationHealthCheckStatus.OK, NotificationHealthCheckStatus.ERROR]);
|
|
101
|
+
* // NotificationHealthCheckStatus.ERROR
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function rollupNotificationHealthCheckStatus(statuses: NotificationHealthCheckStatus[]): NotificationHealthCheckStatus;
|
|
105
|
+
/**
|
|
106
|
+
* True if the status represents a problem the user should act on.
|
|
107
|
+
*
|
|
108
|
+
* @param status - The status to test.
|
|
109
|
+
* @returns True for errors and warnings; false for statuses that need no action.
|
|
110
|
+
*/
|
|
111
|
+
export declare function isProblemNotificationHealthCheckStatus(status: NotificationHealthCheckStatus): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Issue codes emitted by the health checks the library performs itself.
|
|
114
|
+
*
|
|
115
|
+
* Apps and delivery providers may emit additional codes of their own — see
|
|
116
|
+
* {@link NotificationHealthCheckIssueCode}.
|
|
117
|
+
*/
|
|
118
|
+
export declare enum KnownNotificationHealthCheckIssueCode {
|
|
119
|
+
/**
|
|
120
|
+
* The server has no send service configured for this delivery method, so nothing will ever be sent through it.
|
|
121
|
+
*/
|
|
122
|
+
SEND_SERVICE_NOT_CONFIGURED = "sendServiceNotConfigured",
|
|
123
|
+
/**
|
|
124
|
+
* No send service health check is available for this delivery method, so only configuration was inspected.
|
|
125
|
+
*/
|
|
126
|
+
SEND_SERVICE_HEALTH_CHECK_UNAVAILABLE = "sendServiceHealthCheckUnavailable",
|
|
127
|
+
/**
|
|
128
|
+
* No delivery target could be resolved for this method — e.g. no email address on the auth record and no override.
|
|
129
|
+
*/
|
|
130
|
+
NO_DELIVERY_TARGET = "noDeliveryTarget",
|
|
131
|
+
/**
|
|
132
|
+
* The recipient has opted out of all notifications.
|
|
133
|
+
*/
|
|
134
|
+
RECIPIENT_OPTED_OUT = "recipientOptedOut",
|
|
135
|
+
/**
|
|
136
|
+
* The recipient's notifications are disabled.
|
|
137
|
+
*/
|
|
138
|
+
RECIPIENT_DISABLED = "recipientDisabled",
|
|
139
|
+
/**
|
|
140
|
+
* This delivery method is switched off by the user's global or default configuration.
|
|
141
|
+
*/
|
|
142
|
+
METHOD_DISABLED_GLOBALLY = "methodDisabledGlobally",
|
|
143
|
+
/**
|
|
144
|
+
* This delivery method is switched off for the notification template type that was checked.
|
|
145
|
+
*/
|
|
146
|
+
METHOD_DISABLED_FOR_TEMPLATE = "methodDisabledForTemplate",
|
|
147
|
+
/**
|
|
148
|
+
* This delivery method is switched off for one or more of the user's individual notification boxes.
|
|
149
|
+
*/
|
|
150
|
+
METHOD_DISABLED_FOR_BOX = "methodDisabledForBox",
|
|
151
|
+
/**
|
|
152
|
+
* The user is not subscribed to any notification boxes, so no model-driven notifications will reach them.
|
|
153
|
+
*/
|
|
154
|
+
NO_NOTIFICATION_BOXES = "noNotificationBoxes",
|
|
155
|
+
/**
|
|
156
|
+
* The user has notification box exclusions that suppress notifications from matching boxes.
|
|
157
|
+
*/
|
|
158
|
+
NOTIFICATION_BOX_EXCLUSIONS = "notificationBoxExclusions",
|
|
159
|
+
/**
|
|
160
|
+
* The user's configuration has not finished syncing to their notification boxes.
|
|
161
|
+
*/
|
|
162
|
+
NEEDS_CONFIG_SYNC = "needsConfigSync",
|
|
163
|
+
/**
|
|
164
|
+
* One or more of the user's subscriptions is broken and will never send.
|
|
165
|
+
*/
|
|
166
|
+
SUBSCRIPTION_BROKEN = "subscriptionBroken",
|
|
167
|
+
/**
|
|
168
|
+
* One or more of the user's subscriptions has not finished being set up, so its notifications are delayed.
|
|
169
|
+
*/
|
|
170
|
+
SUBSCRIPTION_NOT_READY = "subscriptionNotReady",
|
|
171
|
+
/**
|
|
172
|
+
* A test message was dispatched and its outcome is not known yet.
|
|
173
|
+
*/
|
|
174
|
+
PROBE_PENDING = "probePending",
|
|
175
|
+
/**
|
|
176
|
+
* A test message was confirmed delivered.
|
|
177
|
+
*/
|
|
178
|
+
PROBE_DELIVERED = "probeDelivered",
|
|
179
|
+
/**
|
|
180
|
+
* A test message failed to deliver.
|
|
181
|
+
*/
|
|
182
|
+
PROBE_FAILED = "probeFailed",
|
|
183
|
+
/**
|
|
184
|
+
* A test message could not be dispatched at all.
|
|
185
|
+
*/
|
|
186
|
+
PROBE_DISPATCH_FAILED = "probeDispatchFailed"
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The code identifying what a {@link NotificationHealthCheckIssue} describes.
|
|
190
|
+
*
|
|
191
|
+
* Library checks use {@link KnownNotificationHealthCheckIssueCode}; apps and delivery providers may
|
|
192
|
+
* use any other string to describe provider-specific findings.
|
|
193
|
+
*/
|
|
194
|
+
export type NotificationHealthCheckIssueCode = KnownNotificationHealthCheckIssueCode | string;
|
|
195
|
+
/**
|
|
196
|
+
* Structured detail attached to a {@link NotificationHealthCheckIssue}.
|
|
197
|
+
*
|
|
198
|
+
* Stored directly in Firestore, so values must be Firestore-compatible and should be kept small.
|
|
199
|
+
*/
|
|
200
|
+
export type NotificationHealthCheckIssueData = Readonly<Record<string, any>>;
|
|
201
|
+
/**
|
|
202
|
+
* A single finding produced by a health check.
|
|
203
|
+
*
|
|
204
|
+
* Field abbreviations:
|
|
205
|
+
* - `c` — issue code
|
|
206
|
+
* - `s` — status/severity
|
|
207
|
+
* - `m` — human-readable message
|
|
208
|
+
* - `f` — suggested fix
|
|
209
|
+
* - `d` — structured detail
|
|
210
|
+
*/
|
|
211
|
+
export interface NotificationHealthCheckIssue {
|
|
212
|
+
/**
|
|
213
|
+
* Identifies what was found. See {@link KnownNotificationHealthCheckIssueCode}.
|
|
214
|
+
*/
|
|
215
|
+
c: NotificationHealthCheckIssueCode;
|
|
216
|
+
/**
|
|
217
|
+
* How severe the finding is.
|
|
218
|
+
*/
|
|
219
|
+
s: NotificationHealthCheckStatus;
|
|
220
|
+
/**
|
|
221
|
+
* Human-readable statement of what was found, suitable for showing to the affected user.
|
|
222
|
+
*/
|
|
223
|
+
m: string;
|
|
224
|
+
/**
|
|
225
|
+
* What the user (or an admin) can do about it, when there is a known remedy.
|
|
226
|
+
*/
|
|
227
|
+
f?: Maybe<string>;
|
|
228
|
+
/**
|
|
229
|
+
* Structured detail backing the finding, for display or debugging.
|
|
230
|
+
*/
|
|
231
|
+
d?: Maybe<NotificationHealthCheckIssueData>;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The human-facing content of a {@link NotificationHealthCheckIssue}.
|
|
235
|
+
*/
|
|
236
|
+
export interface NotificationHealthCheckIssueContent {
|
|
237
|
+
/**
|
|
238
|
+
* Human-readable statement of what was found, suitable for showing to the affected user.
|
|
239
|
+
*/
|
|
240
|
+
readonly message: string;
|
|
241
|
+
/**
|
|
242
|
+
* What the user (or an admin) can do about it, when there is a known remedy.
|
|
243
|
+
*/
|
|
244
|
+
readonly fix?: Maybe<string>;
|
|
245
|
+
/**
|
|
246
|
+
* Structured detail backing the finding, for display or debugging.
|
|
247
|
+
*/
|
|
248
|
+
readonly data?: Maybe<NotificationHealthCheckIssueData>;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Creates a {@link NotificationHealthCheckIssue}.
|
|
252
|
+
*
|
|
253
|
+
* @param code - The issue code.
|
|
254
|
+
* @param status - The severity.
|
|
255
|
+
* @param content - The message, plus an optional suggested fix and structured detail.
|
|
256
|
+
* @returns The issue.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* notificationHealthCheckIssue(KnownNotificationHealthCheckIssueCode.NO_DELIVERY_TARGET, NotificationHealthCheckStatus.ERROR, {
|
|
261
|
+
* message: 'There is no email address on your account.',
|
|
262
|
+
* fix: 'Add an email address to your account.'
|
|
263
|
+
* });
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export declare function notificationHealthCheckIssue(code: NotificationHealthCheckIssueCode, status: NotificationHealthCheckStatus, content: NotificationHealthCheckIssueContent): NotificationHealthCheckIssue;
|
|
267
|
+
/**
|
|
268
|
+
* A real test message dispatched through a delivery method in order to observe whether it arrives.
|
|
269
|
+
*
|
|
270
|
+
* Delivery confirmation is asynchronous for most providers, so a probe is recorded when it is
|
|
271
|
+
* dispatched and resolved on a later health check run.
|
|
272
|
+
*
|
|
273
|
+
* Field abbreviations:
|
|
274
|
+
* - `id` — provider correlation id
|
|
275
|
+
* - `at` — dispatch time
|
|
276
|
+
* - `s` — current status
|
|
277
|
+
* - `tg` — delivery target
|
|
278
|
+
* - `d` — provider detail
|
|
279
|
+
*/
|
|
280
|
+
export interface NotificationHealthCheckProbe {
|
|
281
|
+
/**
|
|
282
|
+
* Provider-specific id used to correlate the dispatched message with its delivery outcome.
|
|
283
|
+
* For email this is the provider's message id.
|
|
284
|
+
*/
|
|
285
|
+
id: string;
|
|
286
|
+
/**
|
|
287
|
+
* When the probe was dispatched.
|
|
288
|
+
*/
|
|
289
|
+
at: Date;
|
|
290
|
+
/**
|
|
291
|
+
* The probe's current status. {@link NotificationHealthCheckStatus.PENDING} until the provider
|
|
292
|
+
* reports an outcome.
|
|
293
|
+
*/
|
|
294
|
+
s: NotificationHealthCheckStatus;
|
|
295
|
+
/**
|
|
296
|
+
* The delivery target the probe was sent to.
|
|
297
|
+
*/
|
|
298
|
+
tg: string;
|
|
299
|
+
/**
|
|
300
|
+
* Provider detail about the outcome, once known — typically the failure reason.
|
|
301
|
+
*/
|
|
302
|
+
d?: Maybe<string>;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* True if the probe is still awaiting an outcome and should be re-checked.
|
|
306
|
+
*
|
|
307
|
+
* @param probe - The probe to test, if one exists.
|
|
308
|
+
* @returns True if the probe is pending.
|
|
309
|
+
*/
|
|
310
|
+
export declare function isPendingNotificationHealthCheckProbe(probe: Maybe<NotificationHealthCheckProbe>): boolean;
|
|
311
|
+
/**
|
|
312
|
+
* The correlation id of a probe the provider gave nothing to track it by.
|
|
313
|
+
*
|
|
314
|
+
* Empty rather than absent because the field is what a provider looks the outcome up with, and there is
|
|
315
|
+
* nothing to look up — such a probe is always recorded already settled, so it is never queried.
|
|
316
|
+
*/
|
|
317
|
+
export declare const UNTRACKABLE_NOTIFICATION_HEALTH_CHECK_PROBE_ID = "";
|
|
318
|
+
/**
|
|
319
|
+
* Records a dispatch attempt the provider gave no way to track.
|
|
320
|
+
*
|
|
321
|
+
* A send that produced no correlation id still happened, and the test message window is derived from the
|
|
322
|
+
* recorded probe — so an attempt recorded as nothing at all would leave the server's throttle and the
|
|
323
|
+
* client's countdown with nothing to key on, making the action look successful and be immediately
|
|
324
|
+
* repeatable. Always settled ({@link NotificationHealthCheckStatus.UNKNOWN} when the provider accepted it,
|
|
325
|
+
* `ERROR` when it did not), never pending: there is no outcome coming for it.
|
|
326
|
+
*
|
|
327
|
+
* @param probe - The attempt's time, settled status, target, and provider detail.
|
|
328
|
+
* @returns The probe recording the attempt.
|
|
329
|
+
*/
|
|
330
|
+
export declare function untrackableNotificationHealthCheckProbe(probe: Omit<NotificationHealthCheckProbe, 'id'>): NotificationHealthCheckProbe;
|
|
331
|
+
/**
|
|
332
|
+
* The result of checking a single delivery method.
|
|
333
|
+
*
|
|
334
|
+
* Field abbreviations:
|
|
335
|
+
* - `me` — delivery method
|
|
336
|
+
* - `s` — rolled-up status
|
|
337
|
+
* - `tg` — resolved delivery target
|
|
338
|
+
* - `is` — findings
|
|
339
|
+
* - `pr` — delivery probe
|
|
340
|
+
* - `pb` — whether a test message can be dispatched through this method
|
|
341
|
+
*/
|
|
342
|
+
export interface NotificationDeliveryHealthCheckResult {
|
|
343
|
+
/**
|
|
344
|
+
* The delivery method that was checked.
|
|
345
|
+
*/
|
|
346
|
+
me: NotificationDeliveryMethod;
|
|
347
|
+
/**
|
|
348
|
+
* The most severe status across this method's findings and probe.
|
|
349
|
+
*/
|
|
350
|
+
s: NotificationHealthCheckStatus;
|
|
351
|
+
/**
|
|
352
|
+
* The delivery target that was resolved for this method — an email address, phone number, or
|
|
353
|
+
* NotificationSummary id. Absent when none could be resolved.
|
|
354
|
+
*/
|
|
355
|
+
tg?: Maybe<string>;
|
|
356
|
+
/**
|
|
357
|
+
* Everything the check found for this method.
|
|
358
|
+
*/
|
|
359
|
+
is: NotificationHealthCheckIssue[];
|
|
360
|
+
/**
|
|
361
|
+
* The probe dispatched through this method, if any. May still be pending.
|
|
362
|
+
*/
|
|
363
|
+
pr?: Maybe<NotificationHealthCheckProbe>;
|
|
364
|
+
/**
|
|
365
|
+
* Whether a test message can actually be dispatched through this method — the provider exposes a
|
|
366
|
+
* probe and a delivery target was resolved to send it to.
|
|
367
|
+
*
|
|
368
|
+
* Whether probing is supported is only knowable on the server, so it is reported here for a client
|
|
369
|
+
* that offers a "send a test message" action: absent means no, and the action should not be offered.
|
|
370
|
+
*/
|
|
371
|
+
pb?: Maybe<boolean>;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* A complete health check result, covering every delivery method that was checked.
|
|
375
|
+
*
|
|
376
|
+
* Field abbreviations:
|
|
377
|
+
* - `at` — when the check ran
|
|
378
|
+
* - `vat` — when its pending probes were last verified
|
|
379
|
+
* - `s` — rolled-up status across the whole check
|
|
380
|
+
* - `t` — notification template type the configuration was evaluated against
|
|
381
|
+
* - `is` — account-wide findings
|
|
382
|
+
* - `m` — per-method results
|
|
383
|
+
*/
|
|
384
|
+
export interface NotificationHealthCheck {
|
|
385
|
+
/**
|
|
386
|
+
* When the check was run.
|
|
387
|
+
*/
|
|
388
|
+
at: Date;
|
|
389
|
+
/**
|
|
390
|
+
* When the check's pending probes were last verified.
|
|
391
|
+
*
|
|
392
|
+
* A verify-only run refreshes the probe findings without re-running the check, so it advances this
|
|
393
|
+
* rather than `at` — otherwise polling an in-flight test message would keep pushing the user's own
|
|
394
|
+
* run window out. Absent until a verify-only run has happened.
|
|
395
|
+
*/
|
|
396
|
+
vat?: Maybe<Date>;
|
|
397
|
+
/**
|
|
398
|
+
* The most severe status across the account-wide findings and every checked method.
|
|
399
|
+
*/
|
|
400
|
+
s: NotificationHealthCheckStatus;
|
|
401
|
+
/**
|
|
402
|
+
* The notification template type the per-template configuration was evaluated against.
|
|
403
|
+
*/
|
|
404
|
+
t?: Maybe<NotificationTemplateType>;
|
|
405
|
+
/**
|
|
406
|
+
* Findings that apply to the account as a whole rather than to one delivery method — a disabled
|
|
407
|
+
* account, a subscription that failed to sync, an opt-out that suppresses every method.
|
|
408
|
+
*/
|
|
409
|
+
is: NotificationHealthCheckIssue[];
|
|
410
|
+
/**
|
|
411
|
+
* The result for each delivery method that was checked.
|
|
412
|
+
*/
|
|
413
|
+
m: NotificationDeliveryHealthCheckResult[];
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Rolls a delivery method's findings and probe up into a single status.
|
|
417
|
+
*
|
|
418
|
+
* @param result - The per-method result, without its rolled-up status.
|
|
419
|
+
* @returns The most severe status across the method's findings and probe.
|
|
420
|
+
*/
|
|
421
|
+
export declare function rollupNotificationDeliveryHealthCheckResultStatus(result: Pick<NotificationDeliveryHealthCheckResult, 'is' | 'pr'>): NotificationHealthCheckStatus;
|
|
422
|
+
/**
|
|
423
|
+
* The delivery methods whose test message is still awaiting an outcome.
|
|
424
|
+
*
|
|
425
|
+
* A pending probe is the whole reason to keep watching a check: it is the one part of a report that
|
|
426
|
+
* changes on its own, as the provider records what happened to the message. Both the client (which
|
|
427
|
+
* polls until they settle) and the server (which only consults a provider it has something to ask
|
|
428
|
+
* about) scope their work to exactly these methods.
|
|
429
|
+
*
|
|
430
|
+
* @param healthCheck - The health check to read.
|
|
431
|
+
* @returns The methods carrying a pending probe, in report order. Empty when nothing is in flight.
|
|
432
|
+
*/
|
|
433
|
+
export declare function notificationHealthCheckPendingProbeMethods(healthCheck: Maybe<Pick<NotificationHealthCheck, 'm'>>): NotificationDeliveryMethod[];
|
|
434
|
+
/**
|
|
435
|
+
* Finds the result for a specific delivery method.
|
|
436
|
+
*
|
|
437
|
+
* @param healthCheck - The health check to read.
|
|
438
|
+
* @param method - The delivery method to look for.
|
|
439
|
+
* @returns The method's result, or undefined if the method was not checked.
|
|
440
|
+
*/
|
|
441
|
+
export declare function notificationDeliveryHealthCheckResultForMethod(healthCheck: Maybe<NotificationHealthCheck>, method: NotificationDeliveryMethod): Maybe<NotificationDeliveryHealthCheckResult>;
|
|
442
|
+
/**
|
|
443
|
+
* Every issue in a health check, account-wide findings first.
|
|
444
|
+
*
|
|
445
|
+
* @param healthCheck - The health check to read.
|
|
446
|
+
* @returns All issues, account-wide first and then in method order.
|
|
447
|
+
*/
|
|
448
|
+
export declare function allNotificationHealthCheckIssues(healthCheck: Maybe<NotificationHealthCheck>): NotificationHealthCheckIssue[];
|
|
449
|
+
/**
|
|
450
|
+
* Rolls a whole health check up into a single status.
|
|
451
|
+
*
|
|
452
|
+
* @param healthCheck - The check's account-wide findings and per-method results.
|
|
453
|
+
* @returns The most severe status across everything the check found.
|
|
454
|
+
*/
|
|
455
|
+
export declare function rollupNotificationHealthCheckResultStatus(healthCheck: Pick<NotificationHealthCheck, 'is' | 'm'>): NotificationHealthCheckStatus;
|
|
456
|
+
/**
|
|
457
|
+
* How long a user must wait between health check runs.
|
|
458
|
+
*
|
|
459
|
+
* A run calls out to each delivery provider and can dispatch real messages, so it is throttled against
|
|
460
|
+
* the check stored on the NotificationUser rather than being runnable on demand.
|
|
461
|
+
*/
|
|
462
|
+
export declare const DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_THROTTLE_MINUTES: Minutes;
|
|
463
|
+
/**
|
|
464
|
+
* Input for {@link notificationUserHealthCheckNextRunAt}.
|
|
465
|
+
*/
|
|
466
|
+
export interface NotificationUserHealthCheckNextRunAtInput {
|
|
467
|
+
/**
|
|
468
|
+
* The check currently stored on the NotificationUser, if any.
|
|
469
|
+
*/
|
|
470
|
+
readonly healthCheck?: Maybe<Pick<NotificationHealthCheck, 'at'>>;
|
|
471
|
+
/**
|
|
472
|
+
* Overrides {@link DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_THROTTLE_MINUTES}.
|
|
473
|
+
*/
|
|
474
|
+
readonly throttleMinutes?: Maybe<Minutes>;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* The earliest time another health check may be run for a NotificationUser.
|
|
478
|
+
*
|
|
479
|
+
* Both the server (which enforces the throttle) and the client (which disables the action until then)
|
|
480
|
+
* derive the window from the same stored check, so the UI cannot offer a run the server would reject.
|
|
481
|
+
*
|
|
482
|
+
* @param input - The stored check, and optionally a throttle window to use instead of the default.
|
|
483
|
+
* @returns The time the next run is allowed, or undefined when no check has been run yet.
|
|
484
|
+
*/
|
|
485
|
+
export declare function notificationUserHealthCheckNextRunAt(input: NotificationUserHealthCheckNextRunAtInput): Maybe<Date>;
|
|
486
|
+
/**
|
|
487
|
+
* How long a user must wait between test messages on a single delivery method.
|
|
488
|
+
*
|
|
489
|
+
* Throttled separately from — and more strictly than — a plain run: a probe delivers a real message to
|
|
490
|
+
* the user, while a run only reads configuration and provider state. Running the check must therefore
|
|
491
|
+
* not consume the test message allowance, and vice versa.
|
|
492
|
+
*
|
|
493
|
+
* Only the default. An app that wants a different cadence declares its own value and passes it to both
|
|
494
|
+
* the server (which enforces the window) and the client (which counts down to it) — see
|
|
495
|
+
* {@link NotificationUserHealthCheckNextProbeAtInput.throttleMinutes}. Both sides must use the same
|
|
496
|
+
* value, or the UI will offer a test message the server rejects.
|
|
497
|
+
*/
|
|
498
|
+
export declare const DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_PROBE_THROTTLE_MINUTES: Minutes;
|
|
499
|
+
/**
|
|
500
|
+
* Input for {@link notificationUserHealthCheckNextProbeAt}.
|
|
501
|
+
*/
|
|
502
|
+
export interface NotificationUserHealthCheckNextProbeAtInput {
|
|
503
|
+
/**
|
|
504
|
+
* The check currently stored on the NotificationUser, if any.
|
|
505
|
+
*/
|
|
506
|
+
readonly healthCheck?: Maybe<Pick<NotificationHealthCheck, 'm'>>;
|
|
507
|
+
/**
|
|
508
|
+
* The delivery methods the window is being computed for.
|
|
509
|
+
*
|
|
510
|
+
* Absent or empty considers every method that was checked, which is the window an unscoped test
|
|
511
|
+
* message run answers to.
|
|
512
|
+
*/
|
|
513
|
+
readonly methods?: Maybe<NotificationDeliveryMethod[]>;
|
|
514
|
+
/**
|
|
515
|
+
* Overrides {@link DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_PROBE_THROTTLE_MINUTES}.
|
|
516
|
+
*/
|
|
517
|
+
readonly throttleMinutes?: Maybe<Minutes>;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* The earliest time another test message may be dispatched for a NotificationUser.
|
|
521
|
+
*
|
|
522
|
+
* The window is per delivery method: each method has its own test message action, so a test email must
|
|
523
|
+
* not hold the test text message off. Pass the methods being probed to get their window — the most
|
|
524
|
+
* recent probe among just those methods — and pass none for the window across every checked method.
|
|
525
|
+
*
|
|
526
|
+
* Both the server (which enforces the window) and the client (which disables the action until then)
|
|
527
|
+
* derive it from the same stored check, so the UI cannot offer a test message the server would reject.
|
|
528
|
+
*
|
|
529
|
+
* @param input - The stored check, the methods being probed, and optionally a throttle window to use
|
|
530
|
+
* instead of the default.
|
|
531
|
+
* @returns The time the next probe is allowed, or undefined when none of those methods has ever
|
|
532
|
+
* dispatched one.
|
|
533
|
+
*/
|
|
534
|
+
export declare function notificationUserHealthCheckNextProbeAt(input: NotificationUserHealthCheckNextProbeAtInput): Maybe<Date>;
|
|
535
|
+
/**
|
|
536
|
+
* How long a caller must wait between verifications of a check's pending probes.
|
|
537
|
+
*
|
|
538
|
+
* A verify-only run exists to be polled: a dispatched test message settles on the provider's schedule,
|
|
539
|
+
* so something has to keep asking until it does. It is throttled far more loosely than a run or a probe
|
|
540
|
+
* because it is far cheaper — it consults a provider only for a method with a probe actually in flight,
|
|
541
|
+
* and touches nothing else — but it is throttled all the same, so a client cannot poll a provider's API
|
|
542
|
+
* in a tight loop.
|
|
543
|
+
*
|
|
544
|
+
* Seconds rather than minutes: the point of the verification is that the outcome appears while the user
|
|
545
|
+
* is still looking at the report.
|
|
546
|
+
*/
|
|
547
|
+
export declare const DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_VERIFY_THROTTLE_SECONDS: Seconds;
|
|
548
|
+
/**
|
|
549
|
+
* Input for {@link notificationUserHealthCheckNextVerifyAt}.
|
|
550
|
+
*/
|
|
551
|
+
export interface NotificationUserHealthCheckNextVerifyAtInput {
|
|
552
|
+
/**
|
|
553
|
+
* The check currently stored on the NotificationUser, if any.
|
|
554
|
+
*/
|
|
555
|
+
readonly healthCheck?: Maybe<Pick<NotificationHealthCheck, 'vat'>>;
|
|
556
|
+
/**
|
|
557
|
+
* Overrides {@link DEFAULT_NOTIFICATION_USER_HEALTH_CHECK_VERIFY_THROTTLE_SECONDS}.
|
|
558
|
+
*/
|
|
559
|
+
readonly throttleSeconds?: Maybe<Seconds>;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* The earliest time a check's pending probes may be verified again.
|
|
563
|
+
*
|
|
564
|
+
* Derived from `vat` rather than `at`, so verifying an in-flight test message neither answers to nor
|
|
565
|
+
* consumes the user's run window. Both the server (which enforces the window) and the client (which
|
|
566
|
+
* paces its polling to it) derive it the same way.
|
|
567
|
+
*
|
|
568
|
+
* @param input - The stored check, and optionally a window to use instead of the default.
|
|
569
|
+
* @returns The time the next verification is allowed, or undefined when none has happened yet.
|
|
570
|
+
*/
|
|
571
|
+
export declare function notificationUserHealthCheckNextVerifyAt(input: NotificationUserHealthCheckNextVerifyAtInput): Maybe<Date>;
|
|
572
|
+
/**
|
|
573
|
+
* The earliest time another test message may be dispatched through each of a check's delivery methods.
|
|
574
|
+
*
|
|
575
|
+
* The per-method form of {@link notificationUserHealthCheckNextProbeAt}, for a UI that renders one test
|
|
576
|
+
* message action per method and needs every method's window at once.
|
|
577
|
+
*
|
|
578
|
+
* @param input - The stored check, and optionally a throttle window to use instead of the default.
|
|
579
|
+
* @returns The time the next probe is allowed on each checked method. A method that has never
|
|
580
|
+
* dispatched a probe maps to undefined.
|
|
581
|
+
*/
|
|
582
|
+
export declare function notificationUserHealthCheckNextProbeAtByMethod(input: Omit<NotificationUserHealthCheckNextProbeAtInput, 'methods'>): NotificationDeliveryMethodMap<Maybe<Date>>;
|
|
583
|
+
/**
|
|
584
|
+
* Firestore sub-object converter for {@link NotificationHealthCheckIssue}.
|
|
585
|
+
*/
|
|
586
|
+
export declare const firestoreNotificationHealthCheckIssue: import("../..").FirestoreSubObjectFieldMapFunctionsConfig<NotificationHealthCheckIssue, Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheckIssue, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
587
|
+
/**
|
|
588
|
+
* Firestore sub-object converter for {@link NotificationHealthCheckProbe}.
|
|
589
|
+
*/
|
|
590
|
+
export declare const firestoreNotificationHealthCheckProbe: import("../..").FirestoreSubObjectFieldMapFunctionsConfig<NotificationHealthCheckProbe, Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheckProbe, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
591
|
+
declare const notificationHealthCheckProbeMapFunctions: import("@dereekb/util").ModelMapFunctions<NotificationHealthCheckProbe, Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheckProbe, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
592
|
+
/**
|
|
593
|
+
* The Firestore data form of a {@link NotificationHealthCheckProbe}.
|
|
594
|
+
*/
|
|
595
|
+
export type NotificationHealthCheckProbeData = ReturnType<typeof notificationHealthCheckProbeMapFunctions.to>;
|
|
596
|
+
/**
|
|
597
|
+
* Firestore sub-object converter for {@link NotificationDeliveryHealthCheckResult}.
|
|
598
|
+
*/
|
|
599
|
+
export declare const firestoreNotificationDeliveryHealthCheckResult: import("../..").FirestoreSubObjectFieldMapFunctionsConfig<NotificationDeliveryHealthCheckResult, Partial<import("@dereekb/util").ReplaceType<NotificationDeliveryHealthCheckResult, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
600
|
+
/**
|
|
601
|
+
* Firestore sub-object converter for {@link NotificationHealthCheck}.
|
|
602
|
+
*/
|
|
603
|
+
export declare const firestoreNotificationHealthCheck: import("../..").FirestoreSubObjectFieldMapFunctionsConfig<NotificationHealthCheck, Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheck, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
604
|
+
declare const notificationHealthCheckMapFunctions: import("@dereekb/util").ModelMapFunctions<NotificationHealthCheck, Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheck, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
605
|
+
/**
|
|
606
|
+
* The Firestore data form of a {@link NotificationHealthCheck}.
|
|
607
|
+
*/
|
|
608
|
+
export type NotificationHealthCheckData = ReturnType<typeof notificationHealthCheckMapFunctions.to>;
|
|
609
|
+
/**
|
|
610
|
+
* Field config for the optional {@link NotificationHealthCheck} stored on a NotificationUser.
|
|
611
|
+
*
|
|
612
|
+
* Unlike {@link firestoreNotificationHealthCheck}, this leaves the field absent instead of defaulting
|
|
613
|
+
* to an empty check, so "never run" stays distinguishable from "ran and found nothing".
|
|
614
|
+
*/
|
|
615
|
+
export declare const optionalFirestoreNotificationHealthCheck: import("../..").FirestoreModelFieldMapFunctionsConfig<Maybe<NotificationHealthCheck>, Maybe<Partial<import("@dereekb/util").ReplaceType<NotificationHealthCheck, import("@dereekb/util").MaybeMap<object>, any>>>>;
|
|
616
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.healthcheck.mailgun
|
|
3
|
+
*
|
|
4
|
+
* Issue codes emitted by the Mailgun-backed email health check.
|
|
5
|
+
*
|
|
6
|
+
* These live here, rather than next to the server-side check that emits them, so a browser can ship a
|
|
7
|
+
* first-class presentation for each code without re-declaring the strings. The check itself stays in
|
|
8
|
+
* `@dereekb/firebase-server/model` and imports these codes from here.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Issue codes emitted by the Mailgun email health check.
|
|
12
|
+
*
|
|
13
|
+
* These are Mailgun-specific and sit alongside the library's own
|
|
14
|
+
* {@link KnownNotificationHealthCheckIssueCode} values.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum MailgunNotificationHealthCheckIssueCode {
|
|
17
|
+
/**
|
|
18
|
+
* The address is on the domain's bounce suppression list, so Mailgun drops every message to it.
|
|
19
|
+
*/
|
|
20
|
+
SUPPRESSED_BOUNCE = "mailgunSuppressedBounce",
|
|
21
|
+
/**
|
|
22
|
+
* The address is on the domain's spam complaint list, so Mailgun drops every message to it.
|
|
23
|
+
*/
|
|
24
|
+
SUPPRESSED_COMPLAINT = "mailgunSuppressedComplaint",
|
|
25
|
+
/**
|
|
26
|
+
* The address is on the domain's unsubscribe list.
|
|
27
|
+
*/
|
|
28
|
+
SUPPRESSED_UNSUBSCRIBE = "mailgunSuppressedUnsubscribe",
|
|
29
|
+
/**
|
|
30
|
+
* A recent message to the address failed or was rejected.
|
|
31
|
+
*/
|
|
32
|
+
RECENT_DELIVERY_FAILURE = "mailgunRecentDeliveryFailure",
|
|
33
|
+
/**
|
|
34
|
+
* A recent message to the address was delivered successfully.
|
|
35
|
+
*/
|
|
36
|
+
RECENT_DELIVERY_SUCCESS = "mailgunRecentDeliverySuccess",
|
|
37
|
+
/**
|
|
38
|
+
* No email activity was recorded for the address in the window that was inspected.
|
|
39
|
+
*/
|
|
40
|
+
NO_RECENT_ACTIVITY = "mailgunNoRecentActivity",
|
|
41
|
+
/**
|
|
42
|
+
* The sending domain is not active, which blocks delivery for everyone.
|
|
43
|
+
*/
|
|
44
|
+
DOMAIN_NOT_ACTIVE = "mailgunDomainNotActive",
|
|
45
|
+
/**
|
|
46
|
+
* Address validation says the address cannot receive mail.
|
|
47
|
+
*/
|
|
48
|
+
ADDRESS_UNDELIVERABLE = "mailgunAddressUndeliverable",
|
|
49
|
+
/**
|
|
50
|
+
* The address belongs to a disposable email provider.
|
|
51
|
+
*/
|
|
52
|
+
ADDRESS_DISPOSABLE = "mailgunAddressDisposable",
|
|
53
|
+
/**
|
|
54
|
+
* A probe was requested but no probe message builder is configured.
|
|
55
|
+
*/
|
|
56
|
+
PROBE_NOT_CONFIGURED = "mailgunProbeNotConfigured"
|
|
57
|
+
}
|