easy-ping 0.2.0 → 0.4.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/README.md +15 -4
- package/dist/{adapter-f0OR2DhY.d.cts → adapter-BfLe2J0t.d.cts} +10 -0
- package/dist/{adapter-f0OR2DhY.d.ts → adapter-BfLe2J0t.d.ts} +10 -0
- package/dist/adapters/drizzle.cjs +9 -4
- package/dist/adapters/drizzle.cjs.map +1 -1
- package/dist/adapters/drizzle.d.cts +35 -1
- package/dist/adapters/drizzle.d.ts +35 -1
- package/dist/adapters/drizzle.js +10 -5
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/mongodb.cjs +9 -4
- package/dist/adapters/mongodb.cjs.map +1 -1
- package/dist/adapters/mongodb.d.cts +2 -2
- package/dist/adapters/mongodb.d.ts +2 -2
- package/dist/adapters/mongodb.js +8 -4
- package/dist/adapters/mongodb.js.map +1 -1
- package/dist/adapters/postgres.cjs +136 -3
- package/dist/adapters/postgres.cjs.map +1 -1
- package/dist/adapters/postgres.d.cts +45 -2
- package/dist/adapters/postgres.d.ts +45 -2
- package/dist/adapters/postgres.js +38 -5
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/{chunk-OZSOIX23.js → chunk-3Y2MBUAW.js} +53 -12
- package/dist/chunk-3Y2MBUAW.js.map +1 -0
- package/dist/chunk-CYKAM7LE.js +226 -0
- package/dist/chunk-CYKAM7LE.js.map +1 -0
- package/dist/chunk-DG3ZL5NP.js +315 -0
- package/dist/chunk-DG3ZL5NP.js.map +1 -0
- package/dist/{chunk-NYDVNMKG.js → chunk-PSJHXZPR.js} +4 -3
- package/dist/chunk-PSJHXZPR.js.map +1 -0
- package/dist/{chunk-BV3U542P.js → chunk-W6I3B2CI.js} +2 -2
- package/dist/chunk-W6I3B2CI.js.map +1 -0
- package/dist/chunk-YEMRRMJQ.js +199 -0
- package/dist/chunk-YEMRRMJQ.js.map +1 -0
- package/dist/client.cjs +3 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +3 -5
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +377 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -22
- package/dist/index.d.ts +88 -22
- package/dist/index.js +119 -351
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +27 -6
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +8 -2
- package/dist/node.d.ts +8 -2
- package/dist/node.js +26 -6
- package/dist/node.js.map +1 -1
- package/dist/{plugin-Bqj9xAOS.d.cts → plugin-C9Hoxus2.d.ts} +38 -10
- package/dist/{plugin-bTJKmnlq.d.ts → plugin-CiMsGlQe.d.cts} +38 -10
- package/dist/plugins/digests.d.cts +2 -2
- package/dist/plugins/digests.d.ts +2 -2
- package/dist/plugins/preferences-client.cjs.map +1 -1
- package/dist/plugins/preferences-client.d.cts +2 -2
- package/dist/plugins/preferences-client.d.ts +2 -2
- package/dist/plugins/preferences-client.js +1 -1
- package/dist/plugins/preferences.cjs +100 -15
- package/dist/plugins/preferences.cjs.map +1 -1
- package/dist/plugins/preferences.d.cts +4 -2
- package/dist/plugins/preferences.d.ts +4 -2
- package/dist/plugins/preferences.js +35 -7
- package/dist/plugins/preferences.js.map +1 -1
- package/dist/plugins/push.cjs +222 -61
- package/dist/plugins/push.cjs.map +1 -1
- package/dist/plugins/push.d.cts +81 -3
- package/dist/plugins/push.d.ts +81 -3
- package/dist/plugins/push.js +164 -62
- package/dist/plugins/push.js.map +1 -1
- package/dist/providers/web-push.cjs +37 -11
- package/dist/providers/web-push.cjs.map +1 -1
- package/dist/providers/web-push.d.cts +9 -3
- package/dist/providers/web-push.d.ts +9 -3
- package/dist/providers/web-push.js +37 -12
- package/dist/providers/web-push.js.map +1 -1
- package/dist/react.cjs +3 -5
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +3 -5
- package/dist/react.js.map +1 -1
- package/dist/schema.cjs +2 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +7 -2
- package/dist/schema.d.ts +7 -2
- package/dist/schema.js +2 -198
- package/dist/schema.js.map +1 -1
- package/dist/testing.cjs +29 -0
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +29 -0
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BV3U542P.js.map +0 -1
- package/dist/chunk-NYDVNMKG.js.map +0 -1
- package/dist/chunk-OZSOIX23.js.map +0 -1
- package/dist/chunk-W3BMEPPQ.js +0 -50
- package/dist/chunk-W3BMEPPQ.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as Channel, b as DeliveryMode, S as SkipReason, c as DeliveryRecord, D as DatabaseAdapter, R as Recipient } from './adapter-
|
|
2
|
-
export { d as ClaimArgs, e as ClaimedDelivery, f as DeliveryOutcome, g as DeliveryRelease, a as DeliveryStatus, h as FeedPage, i as FeedQuery, F as Frequency, I as InsertDelivery, j as InsertNotification, N as NotificationRecord, P as PreferenceRecord } from './adapter-
|
|
1
|
+
import { C as Channel, b as DeliveryMode, S as SkipReason, c as DeliveryRecord, D as DatabaseAdapter, R as Recipient } from './adapter-BfLe2J0t.cjs';
|
|
2
|
+
export { d as ClaimArgs, e as ClaimedDelivery, f as DeliveryOutcome, g as DeliveryRelease, a as DeliveryStatus, h as FeedPage, i as FeedQuery, F as Frequency, I as InsertDelivery, j as InsertNotification, N as NotificationRecord, P as PreferenceRecord } from './adapter-BfLe2J0t.cjs';
|
|
3
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
4
|
-
import { A as AnyPlugin, L as Logger } from './plugin-
|
|
5
|
-
export { a as ActionsOf, b as AfterDeliverContext, c as AnyClientPlugin, B as BeforeSendContext, d as BeforeSendResult, C as ChannelDecision, e as ClientFetch, f as ClientPlugin, g as ConfigError, E as EasyPingError, h as EasyPingPlugin, F as FieldDeclaration, i as FieldType,
|
|
4
|
+
import { R as RouteScope, A as AnyPlugin, P as Promisable, L as Logger } from './plugin-CiMsGlQe.cjs';
|
|
5
|
+
export { a as ActionsOf, b as AfterDeliverContext, c as AnyClientPlugin, B as BeforeSendContext, d as BeforeSendResult, C as ChannelDecision, e as ClientFetch, f as ClientPlugin, g as ConfigError, D as DEFAULT_TOKEN_TTL_SECONDS, E as EasyPingError, h as EasyPingPlugin, F as FieldDeclaration, i as FieldType, M as MAX_TOKEN_TTL_SECONDS, j as PluginHooks, k as PrepareContext, l as ResolveChannelsContext, m as RouteContext, n as RouteDefinition, S as SchemaDeclaration, o as SignRequest, T as TableDeclaration, p as TokenClaims, U as UnionToIntersection, V as ValidationError, q as consoleLogger, r as defineClientPlugin, s as definePlugin, t as expiresIn, u as signToken, v as verifyToken } from './plugin-CiMsGlQe.cjs';
|
|
6
6
|
import { E as EmailProvider } from './provider-CA45WVqt.cjs';
|
|
7
7
|
export { a as EmailMessage, P as ProviderSendResult } from './provider-CA45WVqt.cjs';
|
|
8
8
|
|
|
@@ -38,6 +38,25 @@ type PayloadOf<TDef> = TDef extends {
|
|
|
38
38
|
schema: infer TSchema extends StandardSchemaV1;
|
|
39
39
|
} ? StandardSchemaV1.InferOutput<TSchema> : Record<string, unknown>;
|
|
40
40
|
|
|
41
|
+
type RateLimitConfig = {
|
|
42
|
+
/** Requests allowed per key per window. */
|
|
43
|
+
max: number;
|
|
44
|
+
windowMs: number;
|
|
45
|
+
/**
|
|
46
|
+
* Which bucket a request lands in. Defaults to the client address as the
|
|
47
|
+
* usual proxy headers report it; returning null exempts the request. Behind
|
|
48
|
+
* no proxy those headers are absent, so supply your own key there.
|
|
49
|
+
*/
|
|
50
|
+
key?: (request: Request) => string | null;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Fixed-window counter held in process memory. Per isolate on edge runtimes
|
|
54
|
+
* and per replica anywhere else, so it bounds one client's cost to one
|
|
55
|
+
* process rather than enforcing a global quota. That is enough to blunt
|
|
56
|
+
* secret guessing and poll storms, which is what it is for.
|
|
57
|
+
*/
|
|
58
|
+
declare function createRateLimiter(config: RateLimitConfig): (request: Request) => Response | null;
|
|
59
|
+
|
|
41
60
|
type SessionConfig = {
|
|
42
61
|
/** null yields 401; throwing yields 500. Deliberately distinct. */
|
|
43
62
|
getUserId: (request: Request) => string | null | Promise<string | null>;
|
|
@@ -77,10 +96,33 @@ type EasyPingConfig<TDefs extends NotificationDefinitions> = {
|
|
|
77
96
|
/** Required by `cron` and `deferred` modes. See RFC 0002 §4. */
|
|
78
97
|
cron?: {
|
|
79
98
|
secret: string;
|
|
99
|
+
/** Sweeps one POST /cron may run before returning. Defaults to 50. */
|
|
100
|
+
maxSweeps?: number;
|
|
80
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Bearer secret for plugins' machine routes (`/push/prune`, `/digests/cron`).
|
|
104
|
+
* Falls back to `cron.secret`; set it when the scheduler that hits /cron
|
|
105
|
+
* should not also be able to prune devices or fire digests.
|
|
106
|
+
*/
|
|
107
|
+
machineSecret?: string;
|
|
108
|
+
/**
|
|
109
|
+
* In-process fixed-window limiter, applied before routing. Keyed by client
|
|
110
|
+
* address from the usual proxy headers unless `key` says otherwise.
|
|
111
|
+
*/
|
|
112
|
+
rateLimit?: RateLimitConfig;
|
|
81
113
|
plugins?: readonly AnyPlugin[];
|
|
82
114
|
/** Where the handler is mounted, used to strip the prefix off incoming URLs. */
|
|
83
115
|
basePath?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Origins allowed to POST besides the request's own host. Cross-origin
|
|
118
|
+
* POSTs are otherwise refused with 403, and every POST must be
|
|
119
|
+
* `application/json`. `"*.example.com"` matches subdomains.
|
|
120
|
+
*/
|
|
121
|
+
trustedOrigins?: readonly string[];
|
|
122
|
+
/** Runs before routing. Return a Response to short-circuit — a rate limiter's 429, say. */
|
|
123
|
+
onRequest?: (request: Request) => Promisable<Response | undefined | void>;
|
|
124
|
+
/** Defaults to 64 KiB. */
|
|
125
|
+
maxBodyBytes?: number;
|
|
84
126
|
/** Table-name prefix; must match the one given to the adapter. */
|
|
85
127
|
tablePrefix?: string;
|
|
86
128
|
logger?: Logger;
|
|
@@ -111,6 +153,13 @@ type SendResult = {
|
|
|
111
153
|
type Worker = {
|
|
112
154
|
stop: () => Promise<void>;
|
|
113
155
|
};
|
|
156
|
+
type MountedRoute = {
|
|
157
|
+
method: "GET" | "POST";
|
|
158
|
+
path: string;
|
|
159
|
+
scope: RouteScope;
|
|
160
|
+
/** "core" for the built-in routes, otherwise the plugin id. */
|
|
161
|
+
owner: string;
|
|
162
|
+
};
|
|
114
163
|
type HealthReport = {
|
|
115
164
|
mode: DeliveryMode;
|
|
116
165
|
cronMounted: boolean;
|
|
@@ -131,6 +180,8 @@ type EasyPing<TDefs extends NotificationDefinitions> = {
|
|
|
131
180
|
batchSize?: number;
|
|
132
181
|
}): Worker;
|
|
133
182
|
healthCheck(): Promise<HealthReport>;
|
|
183
|
+
/** Every mounted route with its auth scope, so `custom`-scoped ones stay visible. RFC 0002 §3. */
|
|
184
|
+
listRoutes(): readonly MountedRoute[];
|
|
134
185
|
/**
|
|
135
186
|
* Deliveries that exhausted their attempts, newest first.
|
|
136
187
|
*
|
|
@@ -146,8 +197,6 @@ type EasyPing<TDefs extends NotificationDefinitions> = {
|
|
|
146
197
|
}): Promise<readonly DeliveryRecord[]>;
|
|
147
198
|
};
|
|
148
199
|
|
|
149
|
-
declare function easyPing<TDefs extends NotificationDefinitions>(config: EasyPingConfig<TDefs>): EasyPing<TDefs>;
|
|
150
|
-
|
|
151
200
|
type Backoff = "exponential" | ((attempt: number) => number);
|
|
152
201
|
|
|
153
202
|
type RunnerDeps = {
|
|
@@ -165,7 +214,15 @@ type SweepResult = {
|
|
|
165
214
|
claimed: number;
|
|
166
215
|
sent: number;
|
|
167
216
|
failed: number;
|
|
217
|
+
/** Deliveries that had nothing to do. Not errors; see DeliveryOutcome. */
|
|
218
|
+
skipped: number;
|
|
168
219
|
};
|
|
220
|
+
/**
|
|
221
|
+
* What gets persisted to `last_error`. Provider responses quote the offending
|
|
222
|
+
* field, which for a bad recipient is the address itself; that column outlives
|
|
223
|
+
* the notification and is read by admin tooling, so addresses do not go in.
|
|
224
|
+
*/
|
|
225
|
+
declare const redactErrorMessage: (text: string) => string;
|
|
169
226
|
declare function createRunner(deps: RunnerDeps): {
|
|
170
227
|
runOnce: (options?: {
|
|
171
228
|
limit?: number;
|
|
@@ -184,20 +241,29 @@ declare function createRunner(deps: RunnerDeps): {
|
|
|
184
241
|
};
|
|
185
242
|
type Runner = ReturnType<typeof createRunner>;
|
|
186
243
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
declare
|
|
201
|
-
|
|
244
|
+
/** Every JSON body is capped here. Nothing legitimate the routes accept is bigger. */
|
|
245
|
+
declare const MAX_BODY_BYTES: number;
|
|
246
|
+
type JsonBody = {
|
|
247
|
+
body: Record<string, unknown>;
|
|
248
|
+
} | {
|
|
249
|
+
error: Response;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Reads a JSON object body with a byte cap enforced while streaming, so an
|
|
253
|
+
* oversized body is refused before it is buffered. Malformed JSON is 400; an
|
|
254
|
+
* empty body is `{}`. Plugin routes should use this rather than
|
|
255
|
+
* `request.json()`, which has no limit.
|
|
256
|
+
*/
|
|
257
|
+
declare function readJsonBody(request: Request, maxBytes?: number): Promise<JsonBody>;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* For email templates built with template literals. Anything in a payload
|
|
261
|
+
* that a user typed — a display name, a comment excerpt — goes through this
|
|
262
|
+
* or the recipient gets that user's HTML delivered from your sending domain.
|
|
263
|
+
*/
|
|
264
|
+
declare const escapeHtml: (value: unknown) => string;
|
|
265
|
+
|
|
266
|
+
declare const MIN_SECRET_LENGTH = 16;
|
|
267
|
+
declare function easyPing<TDefs extends NotificationDefinitions>(config: EasyPingConfig<TDefs>): EasyPing<TDefs>;
|
|
202
268
|
|
|
203
|
-
export { type AnyNotificationDefinition, AnyPlugin, Channel, type ChannelsConfig,
|
|
269
|
+
export { type AnyNotificationDefinition, AnyPlugin, Channel, type ChannelsConfig, DatabaseAdapter, type DeliveryConfig, DeliveryMode, DeliveryRecord, type EasyPing, type EasyPingConfig, EmailProvider, type EmailTemplate, type HealthReport, type JsonBody, Logger, MAX_BODY_BYTES, MIN_SECRET_LENGTH, type MountedRoute, type NotificationDefinition, type NotificationDefinitions, type PayloadFromSchema, type PayloadOf, Promisable, type RateLimitConfig, Recipient, RouteScope, type Runner, type RunnerDeps, type SendArgs, type SendResult, type SessionConfig, SkipReason, type SweepResult, type Worker, createRateLimiter, createRunner, decodeBase64Url, defineNotification, easyPing, encodeBase64Url, escapeHtml, readJsonBody, redactErrorMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as Channel, b as DeliveryMode, S as SkipReason, c as DeliveryRecord, D as DatabaseAdapter, R as Recipient } from './adapter-
|
|
2
|
-
export { d as ClaimArgs, e as ClaimedDelivery, f as DeliveryOutcome, g as DeliveryRelease, a as DeliveryStatus, h as FeedPage, i as FeedQuery, F as Frequency, I as InsertDelivery, j as InsertNotification, N as NotificationRecord, P as PreferenceRecord } from './adapter-
|
|
1
|
+
import { C as Channel, b as DeliveryMode, S as SkipReason, c as DeliveryRecord, D as DatabaseAdapter, R as Recipient } from './adapter-BfLe2J0t.js';
|
|
2
|
+
export { d as ClaimArgs, e as ClaimedDelivery, f as DeliveryOutcome, g as DeliveryRelease, a as DeliveryStatus, h as FeedPage, i as FeedQuery, F as Frequency, I as InsertDelivery, j as InsertNotification, N as NotificationRecord, P as PreferenceRecord } from './adapter-BfLe2J0t.js';
|
|
3
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
4
|
-
import { A as AnyPlugin, L as Logger } from './plugin-
|
|
5
|
-
export { a as ActionsOf, b as AfterDeliverContext, c as AnyClientPlugin, B as BeforeSendContext, d as BeforeSendResult, C as ChannelDecision, e as ClientFetch, f as ClientPlugin, g as ConfigError, E as EasyPingError, h as EasyPingPlugin, F as FieldDeclaration, i as FieldType,
|
|
4
|
+
import { R as RouteScope, A as AnyPlugin, P as Promisable, L as Logger } from './plugin-C9Hoxus2.js';
|
|
5
|
+
export { a as ActionsOf, b as AfterDeliverContext, c as AnyClientPlugin, B as BeforeSendContext, d as BeforeSendResult, C as ChannelDecision, e as ClientFetch, f as ClientPlugin, g as ConfigError, D as DEFAULT_TOKEN_TTL_SECONDS, E as EasyPingError, h as EasyPingPlugin, F as FieldDeclaration, i as FieldType, M as MAX_TOKEN_TTL_SECONDS, j as PluginHooks, k as PrepareContext, l as ResolveChannelsContext, m as RouteContext, n as RouteDefinition, S as SchemaDeclaration, o as SignRequest, T as TableDeclaration, p as TokenClaims, U as UnionToIntersection, V as ValidationError, q as consoleLogger, r as defineClientPlugin, s as definePlugin, t as expiresIn, u as signToken, v as verifyToken } from './plugin-C9Hoxus2.js';
|
|
6
6
|
import { E as EmailProvider } from './provider-CA45WVqt.js';
|
|
7
7
|
export { a as EmailMessage, P as ProviderSendResult } from './provider-CA45WVqt.js';
|
|
8
8
|
|
|
@@ -38,6 +38,25 @@ type PayloadOf<TDef> = TDef extends {
|
|
|
38
38
|
schema: infer TSchema extends StandardSchemaV1;
|
|
39
39
|
} ? StandardSchemaV1.InferOutput<TSchema> : Record<string, unknown>;
|
|
40
40
|
|
|
41
|
+
type RateLimitConfig = {
|
|
42
|
+
/** Requests allowed per key per window. */
|
|
43
|
+
max: number;
|
|
44
|
+
windowMs: number;
|
|
45
|
+
/**
|
|
46
|
+
* Which bucket a request lands in. Defaults to the client address as the
|
|
47
|
+
* usual proxy headers report it; returning null exempts the request. Behind
|
|
48
|
+
* no proxy those headers are absent, so supply your own key there.
|
|
49
|
+
*/
|
|
50
|
+
key?: (request: Request) => string | null;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Fixed-window counter held in process memory. Per isolate on edge runtimes
|
|
54
|
+
* and per replica anywhere else, so it bounds one client's cost to one
|
|
55
|
+
* process rather than enforcing a global quota. That is enough to blunt
|
|
56
|
+
* secret guessing and poll storms, which is what it is for.
|
|
57
|
+
*/
|
|
58
|
+
declare function createRateLimiter(config: RateLimitConfig): (request: Request) => Response | null;
|
|
59
|
+
|
|
41
60
|
type SessionConfig = {
|
|
42
61
|
/** null yields 401; throwing yields 500. Deliberately distinct. */
|
|
43
62
|
getUserId: (request: Request) => string | null | Promise<string | null>;
|
|
@@ -77,10 +96,33 @@ type EasyPingConfig<TDefs extends NotificationDefinitions> = {
|
|
|
77
96
|
/** Required by `cron` and `deferred` modes. See RFC 0002 §4. */
|
|
78
97
|
cron?: {
|
|
79
98
|
secret: string;
|
|
99
|
+
/** Sweeps one POST /cron may run before returning. Defaults to 50. */
|
|
100
|
+
maxSweeps?: number;
|
|
80
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Bearer secret for plugins' machine routes (`/push/prune`, `/digests/cron`).
|
|
104
|
+
* Falls back to `cron.secret`; set it when the scheduler that hits /cron
|
|
105
|
+
* should not also be able to prune devices or fire digests.
|
|
106
|
+
*/
|
|
107
|
+
machineSecret?: string;
|
|
108
|
+
/**
|
|
109
|
+
* In-process fixed-window limiter, applied before routing. Keyed by client
|
|
110
|
+
* address from the usual proxy headers unless `key` says otherwise.
|
|
111
|
+
*/
|
|
112
|
+
rateLimit?: RateLimitConfig;
|
|
81
113
|
plugins?: readonly AnyPlugin[];
|
|
82
114
|
/** Where the handler is mounted, used to strip the prefix off incoming URLs. */
|
|
83
115
|
basePath?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Origins allowed to POST besides the request's own host. Cross-origin
|
|
118
|
+
* POSTs are otherwise refused with 403, and every POST must be
|
|
119
|
+
* `application/json`. `"*.example.com"` matches subdomains.
|
|
120
|
+
*/
|
|
121
|
+
trustedOrigins?: readonly string[];
|
|
122
|
+
/** Runs before routing. Return a Response to short-circuit — a rate limiter's 429, say. */
|
|
123
|
+
onRequest?: (request: Request) => Promisable<Response | undefined | void>;
|
|
124
|
+
/** Defaults to 64 KiB. */
|
|
125
|
+
maxBodyBytes?: number;
|
|
84
126
|
/** Table-name prefix; must match the one given to the adapter. */
|
|
85
127
|
tablePrefix?: string;
|
|
86
128
|
logger?: Logger;
|
|
@@ -111,6 +153,13 @@ type SendResult = {
|
|
|
111
153
|
type Worker = {
|
|
112
154
|
stop: () => Promise<void>;
|
|
113
155
|
};
|
|
156
|
+
type MountedRoute = {
|
|
157
|
+
method: "GET" | "POST";
|
|
158
|
+
path: string;
|
|
159
|
+
scope: RouteScope;
|
|
160
|
+
/** "core" for the built-in routes, otherwise the plugin id. */
|
|
161
|
+
owner: string;
|
|
162
|
+
};
|
|
114
163
|
type HealthReport = {
|
|
115
164
|
mode: DeliveryMode;
|
|
116
165
|
cronMounted: boolean;
|
|
@@ -131,6 +180,8 @@ type EasyPing<TDefs extends NotificationDefinitions> = {
|
|
|
131
180
|
batchSize?: number;
|
|
132
181
|
}): Worker;
|
|
133
182
|
healthCheck(): Promise<HealthReport>;
|
|
183
|
+
/** Every mounted route with its auth scope, so `custom`-scoped ones stay visible. RFC 0002 §3. */
|
|
184
|
+
listRoutes(): readonly MountedRoute[];
|
|
134
185
|
/**
|
|
135
186
|
* Deliveries that exhausted their attempts, newest first.
|
|
136
187
|
*
|
|
@@ -146,8 +197,6 @@ type EasyPing<TDefs extends NotificationDefinitions> = {
|
|
|
146
197
|
}): Promise<readonly DeliveryRecord[]>;
|
|
147
198
|
};
|
|
148
199
|
|
|
149
|
-
declare function easyPing<TDefs extends NotificationDefinitions>(config: EasyPingConfig<TDefs>): EasyPing<TDefs>;
|
|
150
|
-
|
|
151
200
|
type Backoff = "exponential" | ((attempt: number) => number);
|
|
152
201
|
|
|
153
202
|
type RunnerDeps = {
|
|
@@ -165,7 +214,15 @@ type SweepResult = {
|
|
|
165
214
|
claimed: number;
|
|
166
215
|
sent: number;
|
|
167
216
|
failed: number;
|
|
217
|
+
/** Deliveries that had nothing to do. Not errors; see DeliveryOutcome. */
|
|
218
|
+
skipped: number;
|
|
168
219
|
};
|
|
220
|
+
/**
|
|
221
|
+
* What gets persisted to `last_error`. Provider responses quote the offending
|
|
222
|
+
* field, which for a bad recipient is the address itself; that column outlives
|
|
223
|
+
* the notification and is read by admin tooling, so addresses do not go in.
|
|
224
|
+
*/
|
|
225
|
+
declare const redactErrorMessage: (text: string) => string;
|
|
169
226
|
declare function createRunner(deps: RunnerDeps): {
|
|
170
227
|
runOnce: (options?: {
|
|
171
228
|
limit?: number;
|
|
@@ -184,20 +241,29 @@ declare function createRunner(deps: RunnerDeps): {
|
|
|
184
241
|
};
|
|
185
242
|
type Runner = ReturnType<typeof createRunner>;
|
|
186
243
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
declare
|
|
201
|
-
|
|
244
|
+
/** Every JSON body is capped here. Nothing legitimate the routes accept is bigger. */
|
|
245
|
+
declare const MAX_BODY_BYTES: number;
|
|
246
|
+
type JsonBody = {
|
|
247
|
+
body: Record<string, unknown>;
|
|
248
|
+
} | {
|
|
249
|
+
error: Response;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Reads a JSON object body with a byte cap enforced while streaming, so an
|
|
253
|
+
* oversized body is refused before it is buffered. Malformed JSON is 400; an
|
|
254
|
+
* empty body is `{}`. Plugin routes should use this rather than
|
|
255
|
+
* `request.json()`, which has no limit.
|
|
256
|
+
*/
|
|
257
|
+
declare function readJsonBody(request: Request, maxBytes?: number): Promise<JsonBody>;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* For email templates built with template literals. Anything in a payload
|
|
261
|
+
* that a user typed — a display name, a comment excerpt — goes through this
|
|
262
|
+
* or the recipient gets that user's HTML delivered from your sending domain.
|
|
263
|
+
*/
|
|
264
|
+
declare const escapeHtml: (value: unknown) => string;
|
|
265
|
+
|
|
266
|
+
declare const MIN_SECRET_LENGTH = 16;
|
|
267
|
+
declare function easyPing<TDefs extends NotificationDefinitions>(config: EasyPingConfig<TDefs>): EasyPing<TDefs>;
|
|
202
268
|
|
|
203
|
-
export { type AnyNotificationDefinition, AnyPlugin, Channel, type ChannelsConfig,
|
|
269
|
+
export { type AnyNotificationDefinition, AnyPlugin, Channel, type ChannelsConfig, DatabaseAdapter, type DeliveryConfig, DeliveryMode, DeliveryRecord, type EasyPing, type EasyPingConfig, EmailProvider, type EmailTemplate, type HealthReport, type JsonBody, Logger, MAX_BODY_BYTES, MIN_SECRET_LENGTH, type MountedRoute, type NotificationDefinition, type NotificationDefinitions, type PayloadFromSchema, type PayloadOf, Promisable, type RateLimitConfig, Recipient, RouteScope, type Runner, type RunnerDeps, type SendArgs, type SendResult, type SessionConfig, SkipReason, type SweepResult, type Worker, createRateLimiter, createRunner, decodeBase64Url, defineNotification, easyPing, encodeBase64Url, escapeHtml, readJsonBody, redactErrorMessage };
|