@orkestrel/middleware 0.0.17 → 0.0.19
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 +4 -4
- package/dist/src/core/index.cjs +357 -294
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +390 -290
- package/dist/src/core/index.d.ts +390 -290
- package/dist/src/core/index.js +355 -293
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +472 -410
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +290 -208
- package/dist/src/server/index.d.ts +290 -208
- package/dist/src/server/index.js +464 -405
- package/dist/src/server/index.js.map +1 -1
- package/package.json +25 -22
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Connection } from '@orkestrel/server';
|
|
2
2
|
import { CookieOptions } from '@orkestrel/server';
|
|
3
3
|
import { Encoding } from '@orkestrel/server';
|
|
4
4
|
import { Guard } from '@orkestrel/contract';
|
|
@@ -11,9 +11,8 @@ import { TableInterface } from '@orkestrel/database';
|
|
|
11
11
|
import { TokenSecret } from '@orkestrel/server';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Configures `createBearer` — bearer-token authentication.
|
|
15
15
|
*
|
|
16
|
-
* @param options - See fields below
|
|
17
16
|
* @remarks
|
|
18
17
|
* - `secret` — the {@link TokenSecret} `verifyToken` checks the extracted
|
|
19
18
|
* token against (rotation-aware).
|
|
@@ -30,7 +29,7 @@ export declare interface BearerOptions {
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
|
-
*
|
|
32
|
+
* Describes the bearer-authentication state slice `createBearer` stashes on
|
|
34
33
|
* `context.state` once a token verifies.
|
|
35
34
|
*
|
|
36
35
|
* @remarks
|
|
@@ -43,7 +42,7 @@ export declare interface BearerState {
|
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
/**
|
|
46
|
-
*
|
|
45
|
+
* Describes the body state slice `createBody` stashes.
|
|
47
46
|
*
|
|
48
47
|
* @remarks
|
|
49
48
|
* `body` holds the same defined value the cached `context.body()` resolved
|
|
@@ -55,9 +54,8 @@ export declare interface BodyState {
|
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
/**
|
|
58
|
-
*
|
|
57
|
+
* Configures `createBoundary` — the outermost error-rendering battery.
|
|
59
58
|
*
|
|
60
|
-
* @param options - See fields below
|
|
61
59
|
* @remarks
|
|
62
60
|
* - `expose` — when `true`, a non-`HTTPError` throw's `error.message` is
|
|
63
61
|
* surfaced in the 500 body instead of a generic message. Defaults to
|
|
@@ -71,22 +69,22 @@ export declare interface BoundaryOptions {
|
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
72
|
+
* Builds the {@link Client} slice `createForwarded` stashes, from the
|
|
73
|
+
* resolved client IP — a leaf shaping helper.
|
|
76
74
|
*
|
|
77
75
|
* @param ip - The resolved client IP, if any
|
|
78
|
-
* @returns The {@link
|
|
76
|
+
* @returns The {@link Client} slice value
|
|
79
77
|
*
|
|
80
78
|
* @example
|
|
81
79
|
* ```ts
|
|
82
|
-
*
|
|
80
|
+
* buildClient('203.0.113.7') // { ip: '203.0.113.7' }
|
|
83
81
|
* ```
|
|
84
82
|
*/
|
|
85
|
-
export declare function
|
|
83
|
+
export declare function buildClient(ip: string | undefined): Client_2;
|
|
86
84
|
|
|
87
85
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
86
|
+
* Builds the draft `RateLimit` structured header field — emitted only when
|
|
87
|
+
* `createLimiter`'s `policy` option is `true`.
|
|
90
88
|
*
|
|
91
89
|
* @param remaining - The requests still admitted this window
|
|
92
90
|
* @param resetAt - The window reset instant (same clock unit as `now`)
|
|
@@ -101,8 +99,8 @@ export declare function buildClientInfo(ip: string | undefined): ClientInfo;
|
|
|
101
99
|
export declare function buildRateLimitField(remaining: number, resetAt: number, now: number): string;
|
|
102
100
|
|
|
103
101
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
102
|
+
* Builds the draft `RateLimit-Policy` structured header field — emitted only
|
|
103
|
+
* when `createLimiter`'s `policy` option is `true`.
|
|
106
104
|
*
|
|
107
105
|
* @param max - The window's admitted request count
|
|
108
106
|
* @param window - The window length in milliseconds
|
|
@@ -116,8 +114,8 @@ export declare function buildRateLimitField(remaining: number, resetAt: number,
|
|
|
116
114
|
export declare function buildRateLimitPolicyField(max: number, window: number): string;
|
|
117
115
|
|
|
118
116
|
/**
|
|
119
|
-
*
|
|
120
|
-
* floored at a minimum of `1
|
|
117
|
+
* Builds the `Retry-After` header value — whole seconds until a window reset,
|
|
118
|
+
* floored at a minimum of `1`.
|
|
121
119
|
*
|
|
122
120
|
* @param resetAt - The window reset instant (same clock unit as `now`)
|
|
123
121
|
* @param now - The current instant
|
|
@@ -131,26 +129,27 @@ export declare function buildRateLimitPolicyField(max: number, window: number):
|
|
|
131
129
|
export declare function buildRetryAfter(resetAt: number, now: number): string;
|
|
132
130
|
|
|
133
131
|
/**
|
|
134
|
-
*
|
|
132
|
+
* Describes the resolved client connection facts `createForwarded` stashes.
|
|
135
133
|
*
|
|
136
134
|
* @remarks
|
|
137
135
|
* `ip` is the first untrusted address walking `X-Forwarded-For` /
|
|
138
136
|
* `Forwarded` right-to-left past the configured trusted hops, falling back
|
|
139
137
|
* to the socket peer when no proxy hop qualifies.
|
|
140
138
|
*/
|
|
141
|
-
|
|
139
|
+
declare interface Client_2 {
|
|
142
140
|
readonly ip?: string;
|
|
143
141
|
}
|
|
142
|
+
export { Client_2 as Client }
|
|
144
143
|
|
|
145
144
|
/**
|
|
146
|
-
*
|
|
145
|
+
* Describes the client-facts state slice `createForwarded` stashes.
|
|
147
146
|
*/
|
|
148
147
|
export declare interface ClientState {
|
|
149
|
-
readonly client?:
|
|
148
|
+
readonly client?: Client_2;
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
/**
|
|
153
|
-
*
|
|
152
|
+
* Compresses bytes with the host-independent `CompressionStream` primitive.
|
|
154
153
|
*
|
|
155
154
|
* @param bytes - The uncompressed response bytes
|
|
156
155
|
* @param encoding - The negotiated actionable coding
|
|
@@ -166,9 +165,8 @@ export declare interface ClientState {
|
|
|
166
165
|
export declare function compressBytes(bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>): Promise<Uint8Array<ArrayBuffer>>;
|
|
167
166
|
|
|
168
167
|
/**
|
|
169
|
-
*
|
|
168
|
+
* Configures `createCompression` — response-body compression.
|
|
170
169
|
*
|
|
171
|
-
* @param options - See fields below
|
|
172
170
|
* @remarks
|
|
173
171
|
* - `threshold` — the minimum buffered body size (bytes) worth compressing;
|
|
174
172
|
* defaults to {@link DEFAULT_COMPRESSION_THRESHOLD}.
|
|
@@ -186,7 +184,7 @@ export declare interface CompressionOptions {
|
|
|
186
184
|
}
|
|
187
185
|
|
|
188
186
|
/**
|
|
189
|
-
*
|
|
187
|
+
* Runs the shared negotiate → skip → threshold → compress → header-set skeleton
|
|
190
188
|
* both faces' `createCompression` batteries compose — response-body
|
|
191
189
|
* compression over a caller-supplied set of feature-detected codings.
|
|
192
190
|
*
|
|
@@ -197,16 +195,16 @@ export declare interface CompressionOptions {
|
|
|
197
195
|
* `options.encodings` → {@link isCompressionNegotiated} → `isCompressibleType`
|
|
198
196
|
* on `Content-Type` → a fast skip when the response already carries a
|
|
199
197
|
* numeric `Content-Length` BELOW `options.threshold` (avoids buffering a
|
|
200
|
-
* body known too small to be worth compressing) → buffer
|
|
198
|
+
* body known too small to be worth compressing) → buffer through
|
|
201
199
|
* `response.arrayBuffer()` → a threshold passthrough when the buffered size
|
|
202
200
|
* is still below `options.threshold` → `options.compress` → set
|
|
203
|
-
* `Content-Encoding` and a fresh `Content-Length`
|
|
201
|
+
* `Content-Encoding` and a fresh `Content-Length` through {@link rebuildResponse}.
|
|
204
202
|
* Returns `response` unchanged (aside from the `Vary` stamp) on any skip.
|
|
205
203
|
*
|
|
206
204
|
* @param request - The inbound `Request` (read for `Accept-Encoding`)
|
|
207
205
|
* @param context - The `MiddlewareContext` (read for `context.method`)
|
|
208
206
|
* @param response - The downstream `Response` to consider compressing
|
|
209
|
-
* @param options -
|
|
207
|
+
* @param options - See {@link CompressResponseOptions}
|
|
210
208
|
* @returns The original `response` when skipped, or a new compressed `Response`
|
|
211
209
|
*
|
|
212
210
|
* @example
|
|
@@ -218,27 +216,42 @@ export declare interface CompressionOptions {
|
|
|
218
216
|
* })
|
|
219
217
|
* ```
|
|
220
218
|
*/
|
|
221
|
-
export declare function compressResponse(request: Request, context: MiddlewareContext<unknown>, response: Response, options:
|
|
219
|
+
export declare function compressResponse(request: Request, context: MiddlewareContext<unknown>, response: Response, options: CompressResponseOptions): Promise<Response>;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Describes the already-resolved settings `compressResponse` runs its shared
|
|
223
|
+
* negotiate → skip → threshold → compress skeleton against — the shape each
|
|
224
|
+
* face's `createCompression` builds from its own option bag.
|
|
225
|
+
*
|
|
226
|
+
* @remarks
|
|
227
|
+
* - `threshold` — the minimum body size (bytes) worth compressing.
|
|
228
|
+
* - `filter` — the per-response opt-out predicate; absent allows every
|
|
229
|
+
* response.
|
|
230
|
+
* - `encodings` — the codings offered, in preference order, already narrowed
|
|
231
|
+
* to what this face can actually produce.
|
|
232
|
+
* - `compress` — the runtime's compression primitive for one negotiated
|
|
233
|
+
* coding.
|
|
234
|
+
*/
|
|
235
|
+
export declare interface CompressResponseOptions {
|
|
222
236
|
readonly threshold: number;
|
|
223
237
|
readonly filter?: (request: Request, response: Response) => boolean;
|
|
224
238
|
readonly encodings: readonly Encoding[];
|
|
225
239
|
readonly compress: (bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>) => Promise<Uint8Array<ArrayBuffer>>;
|
|
226
|
-
}
|
|
240
|
+
}
|
|
227
241
|
|
|
228
242
|
/**
|
|
229
|
-
*
|
|
243
|
+
* Describes the connection-facts state slice `createLimiter`'s default key derivation
|
|
230
244
|
* falls back to when neither {@link BearerState} nor {@link ClientState} is
|
|
231
245
|
* present — the raw socket peer surfaced on `context.state` by the server's
|
|
232
246
|
* `state` option.
|
|
233
247
|
*/
|
|
234
248
|
export declare interface ConnectionState {
|
|
235
|
-
readonly connection?:
|
|
249
|
+
readonly connection?: Connection;
|
|
236
250
|
}
|
|
237
251
|
|
|
238
252
|
/**
|
|
239
|
-
*
|
|
253
|
+
* Configures `createCookieTransport` — the signed-cookie {@link SessionTransportInterface}.
|
|
240
254
|
*
|
|
241
|
-
* @param options - See fields below
|
|
242
255
|
* @remarks
|
|
243
256
|
* - `name` — the cookie name; defaults to {@link DEFAULT_SESSION_COOKIE}.
|
|
244
257
|
* - `secret` — the {@link TokenSecret} the session id is signed with (`signToken`).
|
|
@@ -252,9 +265,8 @@ export declare interface CookieTransportOptions {
|
|
|
252
265
|
}
|
|
253
266
|
|
|
254
267
|
/**
|
|
255
|
-
*
|
|
268
|
+
* Configures `createCors` — Cross-Origin Resource Sharing.
|
|
256
269
|
*
|
|
257
|
-
* @param options - See fields below
|
|
258
270
|
* @remarks
|
|
259
271
|
* - `origin` — the allowed origin(s): `'*'` (default), a single origin
|
|
260
272
|
* string, or an allow-list `readonly string[]` (reflects the request
|
|
@@ -270,7 +282,7 @@ export declare interface CorsOptions {
|
|
|
270
282
|
}
|
|
271
283
|
|
|
272
284
|
/**
|
|
273
|
-
*
|
|
285
|
+
* Creates the bearer-token authentication battery.
|
|
274
286
|
*
|
|
275
287
|
* @typeParam TState - The consumer's opaque per-request state type, must carry {@link BearerState}
|
|
276
288
|
* @param options - See {@link BearerOptions}
|
|
@@ -286,7 +298,7 @@ export declare interface CorsOptions {
|
|
|
286
298
|
export declare function createBearer<TState extends BearerState>(options: BearerOptions): MiddlewareHandler<TState>;
|
|
287
299
|
|
|
288
300
|
/**
|
|
289
|
-
*
|
|
301
|
+
* Creates the body-driving battery — eagerly awaits the cached `context.body()` so
|
|
290
302
|
* its throws (or a malformed-JSON `undefined`) surface before the handler
|
|
291
303
|
* runs, and stashes the resolved value onto {@link BodyState.body}.
|
|
292
304
|
*
|
|
@@ -297,8 +309,7 @@ export declare function createBearer<TState extends BearerState>(options: Bearer
|
|
|
297
309
|
* @remarks
|
|
298
310
|
* The shipped `MiddlewareContext.body()` is a parameterless, server-owned
|
|
299
311
|
* cache (`ServerOptions.limit` governs its size cap) — this battery carries
|
|
300
|
-
* no `limit`/`decompression` options
|
|
301
|
-
* `createBodyParser` surface, which configured them itself). `state.body` is
|
|
312
|
+
* no `limit`/`decompression` options. `state.body` is
|
|
302
313
|
* stashed from the SAME awaited call the 400 check reads — `context.body()`
|
|
303
314
|
* is never invoked twice.
|
|
304
315
|
*
|
|
@@ -310,7 +321,7 @@ export declare function createBearer<TState extends BearerState>(options: Bearer
|
|
|
310
321
|
export declare function createBody<TState extends BodyState = BodyState>(): MiddlewareHandler<TState>;
|
|
311
322
|
|
|
312
323
|
/**
|
|
313
|
-
*
|
|
324
|
+
* Creates the outermost error-rendering battery — catches a downstream throw and
|
|
314
325
|
* renders it as a `Response`.
|
|
315
326
|
*
|
|
316
327
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
@@ -326,7 +337,7 @@ export declare function createBody<TState extends BodyState = BodyState>(): Midd
|
|
|
326
337
|
export declare function createBoundary<TState>(options?: BoundaryOptions): MiddlewareHandler<TState>;
|
|
327
338
|
|
|
328
339
|
/**
|
|
329
|
-
*
|
|
340
|
+
* Creates the response-body compression battery — negotiates and compresses a buffered response
|
|
330
341
|
* body over the runtime's feature-detected `CompressionStream` codings.
|
|
331
342
|
*
|
|
332
343
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
@@ -342,11 +353,11 @@ export declare function createBoundary<TState>(options?: BoundaryOptions): Middl
|
|
|
342
353
|
export declare function createCompression<TState>(options?: CompressionOptions): MiddlewareHandler<TState>;
|
|
343
354
|
|
|
344
355
|
/**
|
|
345
|
-
*
|
|
356
|
+
* Creates a signed-cookie {@link SessionTransportInterface} — the session id travels as
|
|
346
357
|
* a `signToken`-signed cookie value.
|
|
347
358
|
*
|
|
348
359
|
* @param options - See {@link CookieTransportOptions}
|
|
349
|
-
* @returns A {@link
|
|
360
|
+
* @returns A {@link SessionTransportInterface}
|
|
350
361
|
* @throws {TypeError} When `options.secret` or `options.name` is malformed
|
|
351
362
|
*
|
|
352
363
|
* @example
|
|
@@ -354,10 +365,10 @@ export declare function createCompression<TState>(options?: CompressionOptions):
|
|
|
354
365
|
* const transport = createCookieTransport({ secret: 'shh' })
|
|
355
366
|
* ```
|
|
356
367
|
*/
|
|
357
|
-
export declare function createCookieTransport(options: CookieTransportOptions):
|
|
368
|
+
export declare function createCookieTransport(options: CookieTransportOptions): SessionTransportInterface;
|
|
358
369
|
|
|
359
370
|
/**
|
|
360
|
-
* Cross-Origin Resource Sharing battery.
|
|
371
|
+
* Creates the Cross-Origin Resource Sharing battery.
|
|
361
372
|
*
|
|
362
373
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
363
374
|
* @param options - See {@link CorsOptions}
|
|
@@ -372,7 +383,7 @@ export declare function createCookieTransport(options: CookieTransportOptions):
|
|
|
372
383
|
export declare function createCors<TState>(options?: CorsOptions): MiddlewareHandler<TState>;
|
|
373
384
|
|
|
374
385
|
/**
|
|
375
|
-
*
|
|
386
|
+
* Creates the session-bound double-submit CSRF protection battery.
|
|
376
387
|
*
|
|
377
388
|
* @typeParam TState - The consumer's opaque per-request state type, must carry {@link CSRFState}, {@link SessionState}, and {@link ConnectionState}
|
|
378
389
|
* @param options - See {@link CSRFOptions}
|
|
@@ -388,33 +399,33 @@ export declare function createCors<TState>(options?: CorsOptions): MiddlewareHan
|
|
|
388
399
|
export declare function createCSRF<TState extends CSRFState & SessionState & ConnectionState>(options: CSRFOptions): MiddlewareHandler<TState>;
|
|
389
400
|
|
|
390
401
|
/**
|
|
391
|
-
*
|
|
402
|
+
* Creates a {@link DatabaseSessionStore} as a {@link SessionStoreInterface} —
|
|
392
403
|
* the durable counterpart to `createMemorySessionStore`, over a caller-opened
|
|
393
404
|
* `@orkestrel/database` table (declare it with {@link sessionColumns}).
|
|
394
405
|
*
|
|
395
|
-
* @typeParam S - The session
|
|
406
|
+
* @typeParam S - The session entity type
|
|
396
407
|
* @param table - The backing `TableInterface<SessionRow>`
|
|
397
|
-
* @param
|
|
398
|
-
* @param options -
|
|
408
|
+
* @param guard - A {@link Guard} narrowing a restored snapshot to `S`
|
|
409
|
+
* @param options - See {@link SessionLimits}
|
|
399
410
|
* @returns A {@link SessionStoreInterface}
|
|
411
|
+
* @throws {TypeError} When `options.ttl` or `options.lifetime` is malformed
|
|
400
412
|
*
|
|
401
413
|
* @remarks
|
|
402
414
|
* This factory only wraps `new DatabaseSessionStore(...)` — it never opens a
|
|
403
415
|
* database or driver itself; the caller owns that lifecycle and passes in an
|
|
404
|
-
* already-open table.
|
|
416
|
+
* already-open table. It supplies {@link createRestoredSession} as the store's
|
|
417
|
+
* snapshot rebuild step, which is why the store imports nothing from this
|
|
418
|
+
* file.
|
|
405
419
|
*
|
|
406
420
|
* @example
|
|
407
421
|
* ```ts
|
|
408
422
|
* const store = createDatabaseSessionStore(db.table('sessions'), isSession, { ttl: 60_000 })
|
|
409
423
|
* ```
|
|
410
424
|
*/
|
|
411
|
-
export declare function createDatabaseSessionStore<S extends SessionInterface = Session>(table: TableInterface<SessionRow>,
|
|
412
|
-
readonly ttl?: number;
|
|
413
|
-
readonly lifetime?: number;
|
|
414
|
-
}): SessionStoreInterface<S>;
|
|
425
|
+
export declare function createDatabaseSessionStore<S extends SessionInterface = Session>(table: TableInterface<SessionRow>, guard: Guard<S>, options?: SessionLimits): SessionStoreInterface<S>;
|
|
415
426
|
|
|
416
427
|
/**
|
|
417
|
-
*
|
|
428
|
+
* Creates the application-level per-request deadline battery.
|
|
418
429
|
*
|
|
419
430
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
420
431
|
* @param options - See {@link DeadlineOptions}
|
|
@@ -424,7 +435,7 @@ export declare function createDatabaseSessionStore<S extends SessionInterface =
|
|
|
424
435
|
* @remarks
|
|
425
436
|
* MUST sit OUTSIDE `createBody` in the chain — it reconstructs the inbound
|
|
426
437
|
* `Request` (to link its `signal` to the deadline `signal`), which throws if
|
|
427
|
-
* the body was already consumed upstream (
|
|
438
|
+
* the body was already consumed upstream (for example by `createBody`'s cached read).
|
|
428
439
|
*
|
|
429
440
|
* @example
|
|
430
441
|
* ```ts
|
|
@@ -434,7 +445,7 @@ export declare function createDatabaseSessionStore<S extends SessionInterface =
|
|
|
434
445
|
export declare function createDeadline<TState>(options: DeadlineOptions): MiddlewareHandler<TState>;
|
|
435
446
|
|
|
436
447
|
/**
|
|
437
|
-
*
|
|
448
|
+
* Creates the dynamic response `ETag` + conditional GET battery.
|
|
438
449
|
*
|
|
439
450
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
440
451
|
* @param options - See {@link ETagOptions}
|
|
@@ -449,7 +460,7 @@ export declare function createDeadline<TState>(options: DeadlineOptions): Middle
|
|
|
449
460
|
export declare function createETag<TState>(options?: ETagOptions): MiddlewareHandler<TState>;
|
|
450
461
|
|
|
451
462
|
/**
|
|
452
|
-
*
|
|
463
|
+
* Creates the trusted-proxy client-IP resolver battery.
|
|
453
464
|
*
|
|
454
465
|
* @typeParam TState - The consumer's opaque per-request state type, must carry {@link ClientState} and {@link ConnectionState}
|
|
455
466
|
* @param options - See {@link ForwardedOptions}
|
|
@@ -464,11 +475,11 @@ export declare function createETag<TState>(options?: ETagOptions): MiddlewareHan
|
|
|
464
475
|
export declare function createForwarded<TState extends ClientState & ConnectionState>(options: ForwardedOptions): MiddlewareHandler<TState>;
|
|
465
476
|
|
|
466
477
|
/**
|
|
467
|
-
*
|
|
478
|
+
* Creates a bare-header {@link SessionTransportInterface} — the session id travels
|
|
468
479
|
* verbatim in a request/response header.
|
|
469
480
|
*
|
|
470
481
|
* @param options - See {@link HeaderTransportOptions}
|
|
471
|
-
* @returns A {@link
|
|
482
|
+
* @returns A {@link SessionTransportInterface}
|
|
472
483
|
* @throws {TypeError} When `options.header` is malformed
|
|
473
484
|
*
|
|
474
485
|
* @example
|
|
@@ -476,10 +487,10 @@ export declare function createForwarded<TState extends ClientState & ConnectionS
|
|
|
476
487
|
* const transport = createHeaderTransport()
|
|
477
488
|
* ```
|
|
478
489
|
*/
|
|
479
|
-
export declare function createHeaderTransport(options?: HeaderTransportOptions):
|
|
490
|
+
export declare function createHeaderTransport(options?: HeaderTransportOptions): SessionTransportInterface;
|
|
480
491
|
|
|
481
492
|
/**
|
|
482
|
-
*
|
|
493
|
+
* Creates the fixed-window rate-limiting battery.
|
|
483
494
|
*
|
|
484
495
|
* @typeParam TState - The consumer's opaque per-request state type, must carry {@link BearerState}, {@link ClientState}, and {@link ConnectionState}
|
|
485
496
|
* @param options - See {@link LimiterOptions}
|
|
@@ -494,28 +505,42 @@ export declare function createHeaderTransport(options?: HeaderTransportOptions):
|
|
|
494
505
|
export declare function createLimiter<TState extends BearerState & ClientState & ConnectionState>(options: LimiterOptions<TState>): MiddlewareHandler<TState>;
|
|
495
506
|
|
|
496
507
|
/**
|
|
497
|
-
*
|
|
508
|
+
* Creates the default in-process {@link SessionStoreInterface} — a `Map`-backed
|
|
498
509
|
* store enforcing an idle timeout and an absolute lifetime.
|
|
499
510
|
*
|
|
500
|
-
* @typeParam S - The session
|
|
511
|
+
* @typeParam S - The session entity type
|
|
501
512
|
* @param options - See {@link MemorySessionStoreOptions}
|
|
502
513
|
* @returns A {@link SessionStoreInterface}
|
|
503
514
|
* @throws {TypeError} When `options.ttl` or `options.lifetime` is malformed
|
|
504
515
|
*
|
|
505
516
|
* @remarks
|
|
506
|
-
* The {@link
|
|
507
|
-
*
|
|
508
|
-
* factory — the name `createSession` belongs to the battery, not this class.
|
|
517
|
+
* The store holds whatever {@link SessionInterface} entity `createSession`'s
|
|
518
|
+
* `create` option produced, keyed by that entity's own `id`.
|
|
509
519
|
*
|
|
510
520
|
* @example
|
|
511
521
|
* ```ts
|
|
512
522
|
* const store = createMemorySessionStore({ ttl: 60_000 })
|
|
513
523
|
* ```
|
|
514
524
|
*/
|
|
515
|
-
export declare function createMemorySessionStore<S>(options?: MemorySessionStoreOptions): SessionStoreInterface<S>;
|
|
525
|
+
export declare function createMemorySessionStore<S extends SessionInterface>(options?: MemorySessionStoreOptions): SessionStoreInterface<S>;
|
|
516
526
|
|
|
517
527
|
/**
|
|
518
|
-
*
|
|
528
|
+
* Rebuilds a {@link Session} from an untrusted snapshot value — the inverse of
|
|
529
|
+
* `snapshotSession` and a durable store's `get` deserialization step.
|
|
530
|
+
*
|
|
531
|
+
* @param value - The candidate snapshot, of unknown shape
|
|
532
|
+
* @returns A rebuilt {@link Session}, or `undefined` when `value` is malformed
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```ts
|
|
536
|
+
* createRestoredSession({ id: 'abc', state: { userId: 'u_1' } }) // Session { id: 'abc' }
|
|
537
|
+
* createRestoredSession({ id: 1 }) // undefined
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
export declare function createRestoredSession(value: unknown): Session | undefined;
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Creates the security-headers + request-identifier battery.
|
|
519
544
|
*
|
|
520
545
|
* @typeParam TState - The consumer's opaque per-request state type, must carry {@link IdentifierState}
|
|
521
546
|
* @param options - See {@link SecurityOptions}
|
|
@@ -530,7 +555,7 @@ export declare function createMemorySessionStore<S>(options?: MemorySessionStore
|
|
|
530
555
|
export declare function createSecurity<TState extends IdentifierState>(options?: SecurityOptions): MiddlewareHandler<TState>;
|
|
531
556
|
|
|
532
557
|
/**
|
|
533
|
-
*
|
|
558
|
+
* Creates the generic session battery — resolves, mints, and persists a session
|
|
534
559
|
* across the request, with a mid-handler `regenerate`/`destroy` control handle.
|
|
535
560
|
*
|
|
536
561
|
* @typeParam S - The session entity type the store persists (must implement {@link SessionInterface})
|
|
@@ -538,7 +563,7 @@ export declare function createSecurity<TState extends IdentifierState>(options?:
|
|
|
538
563
|
* @param options - See {@link SessionOptions}
|
|
539
564
|
* @returns A `MiddlewareHandler<TState>`
|
|
540
565
|
* @throws {TypeError} When any option is malformed
|
|
541
|
-
* @throws {HTTPError} `404` when `
|
|
566
|
+
* @throws {HTTPError} `404` when `required` is set and no session resolves or mints
|
|
542
567
|
*
|
|
543
568
|
* @example
|
|
544
569
|
* ```ts
|
|
@@ -548,7 +573,7 @@ export declare function createSecurity<TState extends IdentifierState>(options?:
|
|
|
548
573
|
export declare function createSession<S extends SessionInterface = SessionInterface, TState extends SessionState & ConnectionState = SessionState & ConnectionState>(options: SessionOptions<S, TState>): MiddlewareHandler<TState>;
|
|
549
574
|
|
|
550
575
|
/**
|
|
551
|
-
*
|
|
576
|
+
* Creates the access-log/timing seam — records one {@link TelemetryEntry} per request
|
|
552
577
|
* after the response settles.
|
|
553
578
|
*
|
|
554
579
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
@@ -564,9 +589,8 @@ export declare function createSession<S extends SessionInterface = SessionInterf
|
|
|
564
589
|
export declare function createTelemetry<TState>(options: TelemetryOptions): MiddlewareHandler<TState>;
|
|
565
590
|
|
|
566
591
|
/**
|
|
567
|
-
*
|
|
592
|
+
* Configures `createCSRF` — session-bound double-submit CSRF protection.
|
|
568
593
|
*
|
|
569
|
-
* @param options - See fields below
|
|
570
594
|
* @remarks
|
|
571
595
|
* - `secret` — the {@link TokenSecret} the CSRF token is signed with.
|
|
572
596
|
* - `cookie` — the signed-cookie name; defaults to {@link DEFAULT_CSRF_COOKIE}.
|
|
@@ -587,7 +611,7 @@ export declare interface CSRFOptions {
|
|
|
587
611
|
}
|
|
588
612
|
|
|
589
613
|
/**
|
|
590
|
-
*
|
|
614
|
+
* Describes the CSRF state slice `createCSRF` stashes — the raw token a safe-method
|
|
591
615
|
* response exposes for a subsequent mutating request to submit back.
|
|
592
616
|
*/
|
|
593
617
|
export declare interface CSRFState {
|
|
@@ -595,26 +619,28 @@ export declare interface CSRFState {
|
|
|
595
619
|
}
|
|
596
620
|
|
|
597
621
|
/**
|
|
598
|
-
*
|
|
622
|
+
* Implements a durable {@link SessionStoreInterface} over an `@orkestrel/database`
|
|
599
623
|
* table — the same idle-timeout + absolute-lifetime contract as
|
|
600
624
|
* {@link MemorySessionStore}, backed by a caller-supplied `TableInterface`
|
|
601
625
|
* instead of an in-process `Map`.
|
|
602
626
|
*
|
|
603
|
-
* @typeParam S - The session
|
|
627
|
+
* @typeParam S - The stored session entity type
|
|
604
628
|
*
|
|
605
629
|
* @remarks
|
|
606
630
|
* `get` reads the row, evicts (removes the row) once `sessionExpired`
|
|
607
|
-
* reports either threshold elapsed, then rebuilds the session
|
|
608
|
-
*
|
|
609
|
-
* caller's
|
|
610
|
-
*
|
|
631
|
+
* reports either threshold elapsed, then rebuilds the session through the
|
|
632
|
+
* `restore` step it was constructed with — a malformed snapshot or one that
|
|
633
|
+
* fails the caller's guard resolves `undefined` rather than throwing.
|
|
634
|
+
* `createDatabaseSessionStore` supplies `createRestoredSession` as that step,
|
|
635
|
+
* so a caller reaching the factory never states it. A live read
|
|
636
|
+
* touches `seen`. `set` preserves an existing row's `created` across a
|
|
611
637
|
* re-`set` of the same id (stamped once at the first `set`), mirroring
|
|
612
638
|
* {@link MemorySessionStore}. `delete` of an absent id is a no-op (the
|
|
613
639
|
* table's `remove` contract).
|
|
614
640
|
*
|
|
615
641
|
* A malformed-snapshot or failed-guard `undefined` LEAVES the row in place —
|
|
616
642
|
* unlike the expired path, which removes it. This is deliberate: a
|
|
617
|
-
* caller-contextual
|
|
643
|
+
* caller-contextual guard may reject a session that is still perfectly
|
|
618
644
|
* valid for another flow reading the same table (a differently-shaped `S`,
|
|
619
645
|
* a stricter guard mid-rollout), so `get` never destroys data on a guard
|
|
620
646
|
* miss. A row that no caller's guard ever accepts again self-heals once its
|
|
@@ -622,28 +648,26 @@ export declare interface CSRFState {
|
|
|
622
648
|
*
|
|
623
649
|
* @example
|
|
624
650
|
* ```ts
|
|
625
|
-
* const store = new DatabaseSessionStore(table, isSession, {
|
|
626
|
-
*
|
|
651
|
+
* const store = new DatabaseSessionStore(table, isSession, createRestoredSession, {
|
|
652
|
+
* ttl: 60_000,
|
|
653
|
+
* })
|
|
654
|
+
* await store.set(new Session('abc'), Date.now())
|
|
627
655
|
* ```
|
|
628
656
|
*/
|
|
629
657
|
export declare class DatabaseSessionStore<S extends SessionInterface = Session> implements SessionStoreInterface<S> {
|
|
630
658
|
#private;
|
|
631
|
-
constructor(table: TableInterface<SessionRow>,
|
|
632
|
-
readonly ttl?: number;
|
|
633
|
-
readonly lifetime?: number;
|
|
634
|
-
});
|
|
659
|
+
constructor(table: TableInterface<SessionRow>, guard: Guard<S>, restore: SessionRestoreFunction, options?: SessionLimits);
|
|
635
660
|
get(id: string, now: number): Promise<S | undefined>;
|
|
636
|
-
set(
|
|
661
|
+
set(session: S, now: number): Promise<void>;
|
|
637
662
|
delete(id: string): Promise<void>;
|
|
638
663
|
}
|
|
639
664
|
|
|
640
665
|
/**
|
|
641
|
-
*
|
|
666
|
+
* Configures `createDeadline` — the application-level per-request deadline.
|
|
642
667
|
*
|
|
643
|
-
* @param options - See fields below
|
|
644
668
|
* @remarks
|
|
645
|
-
* - `ms` — the deadline in milliseconds, armed
|
|
646
|
-
* linked to the request's `signal`
|
|
669
|
+
* - `ms` — the deadline in milliseconds, armed through `@orkestrel/timeout` and
|
|
670
|
+
* linked to the request's `signal` through `@orkestrel/abort`'s `linkSignal`.
|
|
647
671
|
* - `status` — the response status returned when the deadline fires before
|
|
648
672
|
* the downstream chain settles; defaults to {@link DEFAULT_DEADLINE_STATUS}.
|
|
649
673
|
*/
|
|
@@ -652,20 +676,20 @@ export declare interface DeadlineOptions {
|
|
|
652
676
|
readonly status?: number;
|
|
653
677
|
}
|
|
654
678
|
|
|
655
|
-
/**
|
|
679
|
+
/** Names the default header `createBearer` reads the token from. */
|
|
656
680
|
export declare const DEFAULT_BEARER_HEADER = "authorization";
|
|
657
681
|
|
|
658
|
-
/**
|
|
682
|
+
/** Names the default scheme prefix `createBearer` strips before verification. */
|
|
659
683
|
export declare const DEFAULT_BEARER_SCHEME = "Bearer";
|
|
660
684
|
|
|
661
|
-
/**
|
|
685
|
+
/** Holds the default `Origin-Agent-Cluster` value `createSecurity` sets. */
|
|
662
686
|
export declare const DEFAULT_CLUSTER = "?1";
|
|
663
687
|
|
|
664
|
-
/**
|
|
688
|
+
/** Holds the value `createSecurity` sets for `Cross-Origin-Embedder-Policy` when `coep: true`. */
|
|
665
689
|
export declare const DEFAULT_COEP = "require-corp";
|
|
666
690
|
|
|
667
691
|
/**
|
|
668
|
-
*
|
|
692
|
+
* Lists the default content-codings `createCompression` offers, in preference order —
|
|
669
693
|
* intersected at construction with what the runtime's `CompressionStream`
|
|
670
694
|
* actually supports.
|
|
671
695
|
*
|
|
@@ -678,76 +702,75 @@ export declare const DEFAULT_COEP = "require-corp";
|
|
|
678
702
|
*/
|
|
679
703
|
export declare const DEFAULT_COMPRESSION_ENCODINGS: readonly Encoding[];
|
|
680
704
|
|
|
681
|
-
/**
|
|
705
|
+
/** Holds the default minimum buffered body size (bytes) `createCompression` will compress. */
|
|
682
706
|
export declare const DEFAULT_COMPRESSION_THRESHOLD = 1024;
|
|
683
707
|
|
|
684
|
-
/**
|
|
708
|
+
/** Holds the default `Cross-Origin-Opener-Policy` value `createSecurity` sets. */
|
|
685
709
|
export declare const DEFAULT_COOP = "same-origin";
|
|
686
710
|
|
|
687
|
-
/**
|
|
711
|
+
/** Holds the default `Cross-Origin-Resource-Policy` value `createSecurity` sets. */
|
|
688
712
|
export declare const DEFAULT_CORP = "same-origin";
|
|
689
713
|
|
|
690
|
-
/**
|
|
714
|
+
/** Lists the default headers `createCors` advertises on a preflight response. */
|
|
691
715
|
export declare const DEFAULT_CORS_HEADERS: readonly string[];
|
|
692
716
|
|
|
693
|
-
/**
|
|
717
|
+
/** Lists the default methods `createCors` advertises on a preflight response. */
|
|
694
718
|
export declare const DEFAULT_CORS_METHODS: readonly string[];
|
|
695
719
|
|
|
696
720
|
/**
|
|
697
|
-
*
|
|
721
|
+
* Holds the default `Content-Security-Policy` value `createSecurity` sets — a custom
|
|
698
722
|
* `csp` option REPLACES this wholesale, never merges.
|
|
699
723
|
*/
|
|
700
724
|
export declare const DEFAULT_CSP = "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; form-action 'self'";
|
|
701
725
|
|
|
702
|
-
/**
|
|
726
|
+
/** Names the default signed cookie `createCSRF` writes the CSRF token under. */
|
|
703
727
|
export declare const DEFAULT_CSRF_COOKIE = "csrf";
|
|
704
728
|
|
|
705
|
-
/**
|
|
729
|
+
/** Names the default body field `createCSRF` falls back to reading a mutating request's submitted token from. */
|
|
706
730
|
export declare const DEFAULT_CSRF_FIELD = "_csrf";
|
|
707
731
|
|
|
708
|
-
/**
|
|
732
|
+
/** Names the default header `createCSRF` reads a mutating request's submitted token from. */
|
|
709
733
|
export declare const DEFAULT_CSRF_HEADER = "x-csrf-token";
|
|
710
734
|
|
|
711
|
-
/**
|
|
735
|
+
/** Lists the default methods `createCSRF` treats as safe (mint instead of verify). */
|
|
712
736
|
export declare const DEFAULT_CSRF_SAFE_METHODS: readonly string[];
|
|
713
737
|
|
|
714
|
-
/**
|
|
738
|
+
/** Holds the default response status `createDeadline` returns when its deadline fires first. */
|
|
715
739
|
export declare const DEFAULT_DEADLINE_STATUS = 503;
|
|
716
740
|
|
|
717
|
-
/**
|
|
741
|
+
/** Holds the default `X-Frame-Options` value `createSecurity` sets. */
|
|
718
742
|
export declare const DEFAULT_FRAME_OPTIONS = "DENY";
|
|
719
743
|
|
|
720
|
-
/**
|
|
744
|
+
/** Holds the value `createSecurity` sets for `Strict-Transport-Security` when `hsts: true`. */
|
|
721
745
|
export declare const DEFAULT_HSTS = "max-age=31536000; includeSubDomains";
|
|
722
746
|
|
|
723
|
-
/**
|
|
747
|
+
/** Names the default header `createSecurity` mints/echoes a request identifier into. */
|
|
724
748
|
export declare const DEFAULT_IDENTIFIER_HEADER = "x-request-id";
|
|
725
749
|
|
|
726
|
-
/**
|
|
750
|
+
/** Holds the default maximum number of distinct rate-limit keys `createLimiter` tracks before LRU eviction. */
|
|
727
751
|
export declare const DEFAULT_LIMITER_CAPACITY = 10000;
|
|
728
752
|
|
|
729
|
-
/**
|
|
753
|
+
/** Holds the default 429 body message `createLimiter` sends when a key is over budget. */
|
|
730
754
|
export declare const DEFAULT_LIMITER_MESSAGE = "rate limit exceeded";
|
|
731
755
|
|
|
732
|
-
/**
|
|
756
|
+
/** Holds the default `Permissions-Policy` value `createSecurity` sets. */
|
|
733
757
|
export declare const DEFAULT_PERMISSIONS_POLICY = "camera=(), microphone=(), geolocation=()";
|
|
734
758
|
|
|
735
|
-
/**
|
|
759
|
+
/** Holds the default `Referrer-Policy` value `createSecurity` sets. */
|
|
736
760
|
export declare const DEFAULT_REFERRER_POLICY = "strict-origin-when-cross-origin";
|
|
737
761
|
|
|
738
|
-
/**
|
|
762
|
+
/** Holds the default maximum number of distinct session ids `createMemorySessionStore` tracks before LRU (by last write) eviction. */
|
|
739
763
|
export declare const DEFAULT_SESSION_CAPACITY = 10000;
|
|
740
764
|
|
|
741
|
-
/**
|
|
765
|
+
/** Names the default cookie `createCookieTransport` writes the signed session id under. */
|
|
742
766
|
export declare const DEFAULT_SESSION_COOKIE = "session";
|
|
743
767
|
|
|
744
|
-
/**
|
|
768
|
+
/** Names the default header `createHeaderTransport` carries the session id in. */
|
|
745
769
|
export declare const DEFAULT_SESSION_HEADER = "session-id";
|
|
746
770
|
|
|
747
771
|
/**
|
|
748
|
-
* Feature-
|
|
749
|
-
* actually supports — `createCompression`'s construction-time intersection
|
|
750
|
-
* (ruling J).
|
|
772
|
+
* Feature-detects which of `candidates` the runtime's `CompressionStream`
|
|
773
|
+
* actually supports — `createCompression`'s construction-time intersection.
|
|
751
774
|
*
|
|
752
775
|
* @remarks
|
|
753
776
|
* Probes each candidate with `new CompressionStream(candidate)` inside a
|
|
@@ -766,7 +789,7 @@ export declare const DEFAULT_SESSION_HEADER = "session-id";
|
|
|
766
789
|
export declare function detectEncodings(candidates: readonly Encoding[]): readonly Encoding[];
|
|
767
790
|
|
|
768
791
|
/**
|
|
769
|
-
*
|
|
792
|
+
* Compares two strings in constant time — `createCSRF`'s double-submit token
|
|
770
793
|
* comparison, avoiding a timing oracle on the submitted-vs-cookie match.
|
|
771
794
|
*
|
|
772
795
|
* @remarks
|
|
@@ -778,7 +801,7 @@ export declare function detectEncodings(candidates: readonly Encoding[]): readon
|
|
|
778
801
|
*
|
|
779
802
|
* @param a - The first string
|
|
780
803
|
* @param b - The second string
|
|
781
|
-
* @returns
|
|
804
|
+
* @returns True if `a` and `b` are exactly equal; false otherwise
|
|
782
805
|
*
|
|
783
806
|
* @example
|
|
784
807
|
* ```ts
|
|
@@ -789,9 +812,8 @@ export declare function detectEncodings(candidates: readonly Encoding[]): readon
|
|
|
789
812
|
export declare function equalsConstantTime(a: string, b: string): boolean;
|
|
790
813
|
|
|
791
814
|
/**
|
|
792
|
-
*
|
|
815
|
+
* Configures `createETag` — dynamic response ETag + conditional GET.
|
|
793
816
|
*
|
|
794
|
-
* @param options - See fields below
|
|
795
817
|
* @remarks
|
|
796
818
|
* - `weak` — mint a weak `W/"…"` ETag (default `true`) or a strong `"…"` one
|
|
797
819
|
* (`false`).
|
|
@@ -801,8 +823,8 @@ export declare interface ETagOptions {
|
|
|
801
823
|
}
|
|
802
824
|
|
|
803
825
|
/**
|
|
804
|
-
*
|
|
805
|
-
* it steps aside
|
|
826
|
+
* Scopes a battery to run everywhere EXCEPT a set of exact pathnames — there
|
|
827
|
+
* it steps aside through `next()`.
|
|
806
828
|
*
|
|
807
829
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
808
830
|
* @param paths - One pathname, or a set of pathnames, matched exactly against `context.url.pathname`
|
|
@@ -817,9 +839,8 @@ export declare interface ETagOptions {
|
|
|
817
839
|
export declare function except<TState>(paths: string | readonly string[], handler: MiddlewareHandler<TState>): MiddlewareHandler<TState>;
|
|
818
840
|
|
|
819
841
|
/**
|
|
820
|
-
*
|
|
842
|
+
* Configures `createForwarded` — the trusted-proxy client-IP resolver.
|
|
821
843
|
*
|
|
822
|
-
* @param options - See fields below
|
|
823
844
|
* @remarks
|
|
824
845
|
* Construction requires EXACTLY ONE of the two forms (a `TypeError` guards
|
|
825
846
|
* both-set and neither-set):
|
|
@@ -834,9 +855,8 @@ export declare type ForwardedOptions = {
|
|
|
834
855
|
};
|
|
835
856
|
|
|
836
857
|
/**
|
|
837
|
-
*
|
|
858
|
+
* Configures `createHeaderTransport` — the bare-header {@link SessionTransportInterface}.
|
|
838
859
|
*
|
|
839
|
-
* @param options - See fields below
|
|
840
860
|
* @remarks
|
|
841
861
|
* - `header` — the header carrying the session id; defaults to
|
|
842
862
|
* {@link DEFAULT_SESSION_HEADER}.
|
|
@@ -846,7 +866,7 @@ export declare interface HeaderTransportOptions {
|
|
|
846
866
|
}
|
|
847
867
|
|
|
848
868
|
/**
|
|
849
|
-
*
|
|
869
|
+
* Describes the request-identifier state slice `createSecurity` stashes when its
|
|
850
870
|
* `identifier` option is enabled.
|
|
851
871
|
*/
|
|
852
872
|
export declare interface IdentifierState {
|
|
@@ -854,21 +874,21 @@ export declare interface IdentifierState {
|
|
|
854
874
|
}
|
|
855
875
|
|
|
856
876
|
/**
|
|
857
|
-
*
|
|
858
|
-
*
|
|
859
|
-
*
|
|
877
|
+
* Checks whether a response is eligible for the compression/ETag buffering pipeline
|
|
878
|
+
* — the shared cheap-skip predicate both batteries apply before ever touching
|
|
879
|
+
* `response.arrayBuffer()`.
|
|
860
880
|
*
|
|
861
881
|
* @remarks
|
|
862
882
|
* Skips a `HEAD` request, a `204`/`304` or otherwise bodyless response, an
|
|
863
883
|
* `event-stream` response (SSE — buffering would hang the connection), and a
|
|
864
884
|
* response that already carries the header the caller is about to set
|
|
865
|
-
* (`skipHeader`,
|
|
885
|
+
* (`skipHeader`, for example `Content-Encoding` for compression, `ETag` for the
|
|
866
886
|
* ETag battery).
|
|
867
887
|
*
|
|
868
888
|
* @param method - The request's HTTP method
|
|
869
889
|
* @param response - The candidate response
|
|
870
890
|
* @param skipHeader - The response header whose presence means "already handled"
|
|
871
|
-
* @returns
|
|
891
|
+
* @returns True if the response must be left untouched; false otherwise
|
|
872
892
|
*
|
|
873
893
|
* @example
|
|
874
894
|
* ```ts
|
|
@@ -878,11 +898,11 @@ export declare interface IdentifierState {
|
|
|
878
898
|
export declare function isBufferingIneligible(method: string, response: Response, skipHeader: string): boolean;
|
|
879
899
|
|
|
880
900
|
/**
|
|
881
|
-
*
|
|
882
|
-
* `createCompression`'s negotiation-eligibility half of
|
|
901
|
+
* Checks whether a negotiated `Accept-Encoding` outcome is worth acting on —
|
|
902
|
+
* `createCompression`'s negotiation-eligibility half of the skip list.
|
|
883
903
|
*
|
|
884
904
|
* @param encoding - The negotiated coding, or `undefined` when negotiation failed
|
|
885
|
-
* @returns
|
|
905
|
+
* @returns True if `encoding` names an actionable, non-`identity` coding; false otherwise
|
|
886
906
|
*
|
|
887
907
|
* @example
|
|
888
908
|
* ```ts
|
|
@@ -893,12 +913,12 @@ export declare function isBufferingIneligible(method: string, response: Response
|
|
|
893
913
|
export declare function isCompressionNegotiated(encoding: Encoding | undefined): encoding is Exclude<Encoding, 'identity'>;
|
|
894
914
|
|
|
895
915
|
/**
|
|
896
|
-
*
|
|
897
|
-
* structural guard
|
|
916
|
+
* Determines whether a value implements {@link MultipartBody} — a total
|
|
917
|
+
* structural guard: `files` keyed by field name to arrays of
|
|
898
918
|
* {@link MultipartFile}, and a `fields` string record.
|
|
899
919
|
*
|
|
900
920
|
* @param value - The candidate value
|
|
901
|
-
* @returns
|
|
921
|
+
* @returns True if `value` is shaped like a {@link MultipartBody}; false otherwise
|
|
902
922
|
*
|
|
903
923
|
* @example
|
|
904
924
|
* ```ts
|
|
@@ -908,21 +928,34 @@ export declare function isCompressionNegotiated(encoding: Encoding | undefined):
|
|
|
908
928
|
export declare function isMultipartBody(value: unknown): value is MultipartBody;
|
|
909
929
|
|
|
910
930
|
/**
|
|
911
|
-
*
|
|
912
|
-
* total structural guard
|
|
931
|
+
* Determines whether a value is one staged {@link MultipartFile} record — a
|
|
932
|
+
* total structural guard checking every required field's shape.
|
|
913
933
|
*
|
|
914
934
|
* @param value - The candidate value
|
|
915
|
-
* @returns
|
|
935
|
+
* @returns True if `value` is shaped like a {@link MultipartFile}; false otherwise
|
|
936
|
+
*
|
|
937
|
+
* @example
|
|
938
|
+
* ```ts
|
|
939
|
+
* isMultipartFile({
|
|
940
|
+
* field: 'avatar',
|
|
941
|
+
* name: 'a.png',
|
|
942
|
+
* size: 3,
|
|
943
|
+
* mime: 'image/png',
|
|
944
|
+
* validated: true,
|
|
945
|
+
* status: 'staged',
|
|
946
|
+
* path: '/tmp/a',
|
|
947
|
+
* }) // true
|
|
948
|
+
* ```
|
|
916
949
|
*/
|
|
917
950
|
export declare function isMultipartFile(value: unknown): value is MultipartFile;
|
|
918
951
|
|
|
919
952
|
/**
|
|
920
|
-
*
|
|
953
|
+
* Determines whether a request is a CORS PREFLIGHT — an `OPTIONS` request
|
|
921
954
|
* carrying an `Access-Control-Request-Method` header.
|
|
922
955
|
*
|
|
923
956
|
* @param method - The request's HTTP method
|
|
924
957
|
* @param headers - The request's `Headers`
|
|
925
|
-
* @returns
|
|
958
|
+
* @returns True if the request is a CORS preflight `createCors` must answer; false otherwise
|
|
926
959
|
*
|
|
927
960
|
* @example
|
|
928
961
|
* ```ts
|
|
@@ -932,29 +965,29 @@ export declare function isMultipartFile(value: unknown): value is MultipartFile;
|
|
|
932
965
|
export declare function isPreflight(method: string, headers: Headers): boolean;
|
|
933
966
|
|
|
934
967
|
/**
|
|
935
|
-
*
|
|
936
|
-
* structural guard
|
|
937
|
-
* — accepts a plain object, a
|
|
938
|
-
* (a real `Session`), since a
|
|
939
|
-
* instance, not a literal.
|
|
968
|
+
* Determines whether a value implements {@link SessionInterface} — a total
|
|
969
|
+
* structural guard: an `id` string, a `state` `Map`, and the `set`, `delete`,
|
|
970
|
+
* and `clear` mutators. Prototype-agnostic — accepts a plain object, a
|
|
971
|
+
* null-prototype object, AND a class instance (a real `Session`), since a
|
|
972
|
+
* restored/stored session is routinely a class instance, not a literal.
|
|
940
973
|
*
|
|
941
974
|
* @param value - The candidate value
|
|
942
|
-
* @returns
|
|
975
|
+
* @returns True if `value` is shaped like a {@link SessionInterface}; false otherwise
|
|
943
976
|
*
|
|
944
977
|
* @example
|
|
945
978
|
* ```ts
|
|
946
|
-
* isSession({ id: 'a', data: new Map() }) // true
|
|
947
979
|
* isSession(new Session('a')) // true
|
|
980
|
+
* isSession({ id: 'a', state: new Map() }) // false — the mutators are missing
|
|
948
981
|
* ```
|
|
949
982
|
*/
|
|
950
983
|
export declare function isSession(value: unknown): value is SessionInterface;
|
|
951
984
|
|
|
952
985
|
/**
|
|
953
|
-
*
|
|
954
|
-
* total structural guard
|
|
986
|
+
* Determines whether a value implements {@link SessionControlInterface} — a
|
|
987
|
+
* total structural guard: callable `regenerate` and `destroy`.
|
|
955
988
|
*
|
|
956
989
|
* @param value - The candidate value
|
|
957
|
-
* @returns
|
|
990
|
+
* @returns True if `value` is shaped like a {@link SessionControlInterface}; false otherwise
|
|
958
991
|
*
|
|
959
992
|
* @example
|
|
960
993
|
* ```ts
|
|
@@ -964,15 +997,14 @@ export declare function isSession(value: unknown): value is SessionInterface;
|
|
|
964
997
|
export declare function isSessionControl(value: unknown): value is SessionControlInterface;
|
|
965
998
|
|
|
966
999
|
/**
|
|
967
|
-
*
|
|
1000
|
+
* Configures `createLimiter` — fixed-window rate limiting.
|
|
968
1001
|
*
|
|
969
1002
|
* @typeParam TState - The consumer's opaque per-request state type `key` reads
|
|
970
|
-
* @param options - See fields below
|
|
971
1003
|
* @remarks
|
|
972
1004
|
* - `max` — the number of requests admitted per key per `window`.
|
|
973
1005
|
* - `window` — the window length in milliseconds.
|
|
974
1006
|
* - `capacity` — the maximum number of distinct keys tracked before the
|
|
975
|
-
* least-recently-used key is evicted (true LRU — every access, not
|
|
1007
|
+
* least-recently-used key is evicted (true LRU — every access, not only
|
|
976
1008
|
* insertion, refreshes recency); defaults to {@link DEFAULT_LIMITER_CAPACITY}.
|
|
977
1009
|
* - `key` — derives the bucket key from the request; defaults to the
|
|
978
1010
|
* bearer-token-then-client-IP idiom (see the battery's guide).
|
|
@@ -997,7 +1029,7 @@ export declare interface LimiterOptions<TState = unknown> {
|
|
|
997
1029
|
}
|
|
998
1030
|
|
|
999
1031
|
/**
|
|
1000
|
-
*
|
|
1032
|
+
* Checks whether a candidate address is a bare (non-CIDR) trusted-hop match — an
|
|
1001
1033
|
* exact string match, or a simple prefix-CIDR match for IPv4 (`/8`–`/32`).
|
|
1002
1034
|
* An IPv6 entry matches by exact string only — there is no IPv6 CIDR
|
|
1003
1035
|
* support.
|
|
@@ -1016,7 +1048,7 @@ export declare interface LimiterOptions<TState = unknown> {
|
|
|
1016
1048
|
*
|
|
1017
1049
|
* @param address - The candidate hop address
|
|
1018
1050
|
* @param entry - One `trusted` roster entry — an exact address or an IPv4 CIDR
|
|
1019
|
-
* @returns
|
|
1051
|
+
* @returns True if `address` is covered by `entry`; false otherwise
|
|
1020
1052
|
*
|
|
1021
1053
|
* @example
|
|
1022
1054
|
* ```ts
|
|
@@ -1027,18 +1059,18 @@ export declare interface LimiterOptions<TState = unknown> {
|
|
|
1027
1059
|
export declare function matchesTrustedEntry(address: string, entry: string): boolean;
|
|
1028
1060
|
|
|
1029
1061
|
/**
|
|
1030
|
-
*
|
|
1062
|
+
* Implements the default in-process {@link SessionStoreInterface} — a `Map`-backed store
|
|
1031
1063
|
* enforcing both an idle timeout and an absolute lifetime, with lazy
|
|
1032
1064
|
* (read-time) eviction, a bounded capacity, and no background timers.
|
|
1033
1065
|
*
|
|
1034
|
-
* @typeParam S - The session
|
|
1066
|
+
* @typeParam S - The stored session entity type
|
|
1035
1067
|
*
|
|
1036
1068
|
* @remarks
|
|
1037
|
-
* `get` evicts a session whose idle time (`now -
|
|
1038
|
-
* absolute lifetime (`now -
|
|
1069
|
+
* `get` evicts a session whose idle time (`now - seen >= ttl`) or
|
|
1070
|
+
* absolute lifetime (`now - created >= lifetime`) has elapsed — the
|
|
1039
1071
|
* lifetime check fires EVEN IF the session was continuously touched, since
|
|
1040
|
-
* `
|
|
1041
|
-
* later re-`set` of the same id. A live read touches `
|
|
1072
|
+
* `created` is stamped once at the first `set` and preserved across every
|
|
1073
|
+
* later re-`set` of the same id. A live read touches `seen`. `delete` of
|
|
1042
1074
|
* an absent id is a no-op.
|
|
1043
1075
|
*
|
|
1044
1076
|
* Capacity is enforced as least-recently-used **by last write**: `set`
|
|
@@ -1053,21 +1085,20 @@ export declare function matchesTrustedEntry(address: string, entry: string): boo
|
|
|
1053
1085
|
* @example
|
|
1054
1086
|
* ```ts
|
|
1055
1087
|
* const store = new MemorySessionStore({ ttl: 60_000, lifetime: 3_600_000 })
|
|
1056
|
-
* await store.set('abc',
|
|
1088
|
+
* await store.set(new Session('abc'), Date.now())
|
|
1057
1089
|
* ```
|
|
1058
1090
|
*/
|
|
1059
|
-
export declare class MemorySessionStore<S> implements SessionStoreInterface<S> {
|
|
1091
|
+
export declare class MemorySessionStore<S extends SessionInterface> implements SessionStoreInterface<S> {
|
|
1060
1092
|
#private;
|
|
1061
1093
|
constructor(options?: MemorySessionStoreOptions);
|
|
1062
1094
|
get(id: string, now: number): Promise<S | undefined>;
|
|
1063
|
-
set(
|
|
1095
|
+
set(session: S, now: number): Promise<void>;
|
|
1064
1096
|
delete(id: string): Promise<void>;
|
|
1065
1097
|
}
|
|
1066
1098
|
|
|
1067
1099
|
/**
|
|
1068
|
-
*
|
|
1100
|
+
* Configures `createMemorySessionStore` — the default in-process {@link SessionStoreInterface}.
|
|
1069
1101
|
*
|
|
1070
|
-
* @param options - See fields below
|
|
1071
1102
|
* @remarks
|
|
1072
1103
|
* - `ttl` — the idle timeout in milliseconds (lazy eviction on `get`).
|
|
1073
1104
|
* - `lifetime` — the absolute lifetime in milliseconds from first `set`
|
|
@@ -1081,15 +1112,13 @@ export declare class MemorySessionStore<S> implements SessionStoreInterface<S> {
|
|
|
1081
1112
|
* sink only — it must never call back into the store (no re-entrant
|
|
1082
1113
|
* `get`/`set`); mutations during eviction are unsupported.
|
|
1083
1114
|
*/
|
|
1084
|
-
export declare interface MemorySessionStoreOptions {
|
|
1085
|
-
readonly ttl?: number;
|
|
1086
|
-
readonly lifetime?: number;
|
|
1115
|
+
export declare interface MemorySessionStoreOptions extends SessionLimits {
|
|
1087
1116
|
readonly capacity?: number;
|
|
1088
1117
|
readonly evict?: (id: string) => void;
|
|
1089
1118
|
}
|
|
1090
1119
|
|
|
1091
1120
|
/**
|
|
1092
|
-
*
|
|
1121
|
+
* Describes the parsed multipart request body `createMultipart` stashes — files keyed
|
|
1093
1122
|
* by their field name, plus every plain text field.
|
|
1094
1123
|
*/
|
|
1095
1124
|
export declare interface MultipartBody {
|
|
@@ -1098,7 +1127,7 @@ export declare interface MultipartBody {
|
|
|
1098
1127
|
}
|
|
1099
1128
|
|
|
1100
1129
|
/**
|
|
1101
|
-
*
|
|
1130
|
+
* Represents one staged multipart upload's public record — the shape the node-face
|
|
1102
1131
|
* `createMultipart` battery (`@orkestrel/middleware/server`) produces per
|
|
1103
1132
|
* uploaded file.
|
|
1104
1133
|
*
|
|
@@ -1106,7 +1135,7 @@ export declare interface MultipartBody {
|
|
|
1106
1135
|
* Declared here rather than in the node-bound server surface so the
|
|
1107
1136
|
* fetch/string-pure {@link MultipartState} slice — referenced by any
|
|
1108
1137
|
* environment narrowing `context.state` — never depends on the node face.
|
|
1109
|
-
* The server's concrete `
|
|
1138
|
+
* The server's concrete `UploadedFile` is structurally compatible
|
|
1110
1139
|
* with this shape.
|
|
1111
1140
|
*/
|
|
1112
1141
|
export declare interface MultipartFile {
|
|
@@ -1120,7 +1149,7 @@ export declare interface MultipartFile {
|
|
|
1120
1149
|
}
|
|
1121
1150
|
|
|
1122
1151
|
/**
|
|
1123
|
-
*
|
|
1152
|
+
* Describes the multipart state slice `createMultipart` stashes.
|
|
1124
1153
|
*
|
|
1125
1154
|
* @remarks
|
|
1126
1155
|
* Present only once `createMultipart` has fully parsed a multipart request.
|
|
@@ -1133,8 +1162,8 @@ export declare interface MultipartState {
|
|
|
1133
1162
|
}
|
|
1134
1163
|
|
|
1135
1164
|
/**
|
|
1136
|
-
*
|
|
1137
|
-
* steps aside
|
|
1165
|
+
* Scopes a battery to run ONLY on a set of exact pathnames — elsewhere it
|
|
1166
|
+
* steps aside through `next()`.
|
|
1138
1167
|
*
|
|
1139
1168
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
1140
1169
|
* @param paths - One pathname, or a set of pathnames, matched exactly against `context.url.pathname`
|
|
@@ -1149,7 +1178,7 @@ export declare interface MultipartState {
|
|
|
1149
1178
|
export declare function only<TState>(paths: string | readonly string[], handler: MiddlewareHandler<TState>): MiddlewareHandler<TState>;
|
|
1150
1179
|
|
|
1151
1180
|
/**
|
|
1152
|
-
*
|
|
1181
|
+
* Rebuilds a `Response` around a replacement body while preserving its
|
|
1153
1182
|
* status/statusText — the buffered-response reconstruction shared by the
|
|
1154
1183
|
* compression and ETag batteries after they have consumed
|
|
1155
1184
|
* `response.arrayBuffer()`.
|
|
@@ -1168,7 +1197,7 @@ export declare function only<TState>(paths: string | readonly string[], handler:
|
|
|
1168
1197
|
export declare function rebuildResponse(body: ConstructorParameters<typeof Response>[0], response: Response, headers?: ConstructorParameters<typeof Headers>[0]): Response;
|
|
1169
1198
|
|
|
1170
1199
|
/**
|
|
1171
|
-
*
|
|
1200
|
+
* Walks `X-Forwarded-For` right-to-left and resolves the first UNTRUSTED hop
|
|
1172
1201
|
* address — `createForwarded`'s core algorithm.
|
|
1173
1202
|
*
|
|
1174
1203
|
* @remarks
|
|
@@ -1184,7 +1213,7 @@ export declare function rebuildResponse(body: ConstructorParameters<typeof Respo
|
|
|
1184
1213
|
* socket peer).
|
|
1185
1214
|
*
|
|
1186
1215
|
* @param header - The raw `X-Forwarded-For` header value (comma-separated hops), if present
|
|
1187
|
-
* @param trust -
|
|
1216
|
+
* @param trust - The {@link ForwardedOptions} form in force — a trusted hop COUNT or a `trusted` CIDR/exact roster
|
|
1188
1217
|
* @returns The first untrusted hop address, or `undefined` when none qualifies
|
|
1189
1218
|
*
|
|
1190
1219
|
* @example
|
|
@@ -1192,21 +1221,17 @@ export declare function rebuildResponse(body: ConstructorParameters<typeof Respo
|
|
|
1192
1221
|
* resolveForwardedFor('203.0.113.7, 10.0.0.1', { proxies: 1 }) // '203.0.113.7'
|
|
1193
1222
|
* ```
|
|
1194
1223
|
*/
|
|
1195
|
-
export declare function resolveForwardedFor(header: string | undefined, trust:
|
|
1196
|
-
readonly proxies: number;
|
|
1197
|
-
} | {
|
|
1198
|
-
readonly trusted: readonly string[];
|
|
1199
|
-
}): string | undefined;
|
|
1224
|
+
export declare function resolveForwardedFor(header: string | undefined, trust: ForwardedOptions): string | undefined;
|
|
1200
1225
|
|
|
1201
1226
|
/**
|
|
1202
|
-
*
|
|
1227
|
+
* Derives `createLimiter`'s default rate-limit bucket key from a request's
|
|
1203
1228
|
* resolved identity facts.
|
|
1204
1229
|
*
|
|
1205
1230
|
* @remarks
|
|
1206
1231
|
* Prefers a verified bearer token ({@link BearerState.token}) as
|
|
1207
1232
|
* `token:<value>`; else a resolved client IP ({@link ClientState.client.ip},
|
|
1208
1233
|
* set when `createForwarded` is mounted) or the raw socket peer
|
|
1209
|
-
* ({@link ConnectionState.connection.ip}) collapsed
|
|
1234
|
+
* ({@link ConnectionState.connection.ip}) collapsed through `computeClientKey`
|
|
1210
1235
|
* (IPv6 to its `/64` network) as `ip:<key>`; else the literal `ip:unknown`.
|
|
1211
1236
|
* Never reads `X-Forwarded-For` itself — that trust decision belongs solely
|
|
1212
1237
|
* to `createForwarded`.
|
|
@@ -1223,7 +1248,7 @@ export declare function resolveForwardedFor(header: string | undefined, trust: {
|
|
|
1223
1248
|
export declare function resolveKey(state: BearerState & ClientState & ConnectionState): string;
|
|
1224
1249
|
|
|
1225
1250
|
/**
|
|
1226
|
-
*
|
|
1251
|
+
* Resolves an opt-in, value-bearing security header — `string | boolean`
|
|
1227
1252
|
* (default OFF, `true` uses the secure default), the shape `createSecurity`'s
|
|
1228
1253
|
* `coep`/`hsts` options use, distinct from the plain value-or-`false` shape
|
|
1229
1254
|
* `resolveSecurityHeader` (the peer substrate) handles.
|
|
@@ -1241,22 +1266,7 @@ export declare function resolveKey(state: BearerState & ClientState & Connection
|
|
|
1241
1266
|
export declare function resolveOptInHeader(value: string | boolean | undefined, fallback: string): string | undefined;
|
|
1242
1267
|
|
|
1243
1268
|
/**
|
|
1244
|
-
*
|
|
1245
|
-
* {@link snapshotSession}) — a durable store's `get` deserialization step.
|
|
1246
|
-
*
|
|
1247
|
-
* @param value - The candidate snapshot, of unknown shape
|
|
1248
|
-
* @returns A rebuilt `Session`, or `undefined` when `value` is malformed
|
|
1249
|
-
*
|
|
1250
|
-
* @example
|
|
1251
|
-
* ```ts
|
|
1252
|
-
* restoreSession({ id: 'abc', data: { userId: 'u_1' } }) // Session { id: 'abc', data: Map }
|
|
1253
|
-
* restoreSession({ id: 1 }) // undefined
|
|
1254
|
-
* ```
|
|
1255
|
-
*/
|
|
1256
|
-
export declare function restoreSession(value: unknown): Session | undefined;
|
|
1257
|
-
|
|
1258
|
-
/**
|
|
1259
|
-
* `createSecurity`'s `identifier` sub-option — request-id minting/echo
|
|
1269
|
+
* Describes `createSecurity`'s `identifier` sub-option — request-id minting/echo
|
|
1260
1270
|
* policy, or `false` to disable the feature entirely.
|
|
1261
1271
|
*
|
|
1262
1272
|
* @remarks
|
|
@@ -1269,9 +1279,8 @@ export declare type SecurityIdentifierOptions = {
|
|
|
1269
1279
|
} | false;
|
|
1270
1280
|
|
|
1271
1281
|
/**
|
|
1272
|
-
*
|
|
1282
|
+
* Configures `createSecurity` — the security-headers + request-id battery.
|
|
1273
1283
|
*
|
|
1274
|
-
* @param options - See fields below
|
|
1275
1284
|
* @remarks
|
|
1276
1285
|
* Every header option is `string | false` (a custom value replaces the
|
|
1277
1286
|
* default wholesale, `false` omits the header) unless noted; unset uses the
|
|
@@ -1305,35 +1314,41 @@ export declare interface SecurityOptions {
|
|
|
1305
1314
|
}
|
|
1306
1315
|
|
|
1307
1316
|
/**
|
|
1308
|
-
*
|
|
1309
|
-
* value
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1317
|
+
* Represents a server-managed session's default entity — the `create` option's default
|
|
1318
|
+
* value for `createSession`. It ships without a bare `create*` factory of its
|
|
1319
|
+
* own, because the name `createSession` belongs to the battery;
|
|
1320
|
+
* `createRestoredSession` rebuilds one from a stored snapshot.
|
|
1312
1321
|
*
|
|
1313
1322
|
* @remarks
|
|
1314
|
-
* `
|
|
1315
|
-
*
|
|
1323
|
+
* `state` is a `ReadonlyMap` view over the entity's own `Map`: TypeScript
|
|
1324
|
+
* refuses a write through it, and `set`, `delete`, and `clear` are the write
|
|
1325
|
+
* path. `createSession` persists the state to the configured store on the way
|
|
1326
|
+
* out.
|
|
1316
1327
|
*
|
|
1317
1328
|
* @example
|
|
1318
1329
|
* ```ts
|
|
1319
1330
|
* const session = new Session('abc123')
|
|
1320
|
-
* session.
|
|
1331
|
+
* session.set('userId', 'u_1')
|
|
1321
1332
|
* ```
|
|
1322
1333
|
*/
|
|
1323
1334
|
export declare class Session implements SessionInterface {
|
|
1324
|
-
|
|
1325
|
-
readonly data: Map<string, unknown>;
|
|
1335
|
+
#private;
|
|
1326
1336
|
constructor(id: string);
|
|
1337
|
+
get id(): string;
|
|
1338
|
+
get state(): ReadonlyMap<string, unknown>;
|
|
1339
|
+
set(key: string, value: unknown): void;
|
|
1340
|
+
delete(key: string): boolean;
|
|
1341
|
+
clear(): void;
|
|
1327
1342
|
}
|
|
1328
1343
|
|
|
1329
1344
|
/**
|
|
1330
|
-
*
|
|
1345
|
+
* Holds the `@orkestrel/database` column shape for a
|
|
1331
1346
|
* {@link import('./types.js').SessionRow} table — pass as-is to
|
|
1332
1347
|
* `createDatabase({ tables: { sessions: sessionColumns } })` so an app
|
|
1333
1348
|
* declaring a durable session table never hand-writes the shape.
|
|
1334
1349
|
*
|
|
1335
1350
|
* @remarks
|
|
1336
|
-
* `
|
|
1351
|
+
* `seen`/`created` are `integerShape({ min: 0 })` — the table validates
|
|
1337
1352
|
* them as integers, so
|
|
1338
1353
|
* {@link import('./stores/DatabaseSessionStore.js').DatabaseSessionStore}'s
|
|
1339
1354
|
* `now` clock must yield integer milliseconds (`Date.now()`, the implicit
|
|
@@ -1349,19 +1364,19 @@ export declare class Session implements SessionInterface {
|
|
|
1349
1364
|
export declare const sessionColumns: {
|
|
1350
1365
|
id: StringShape;
|
|
1351
1366
|
session: JSONShape;
|
|
1352
|
-
|
|
1353
|
-
|
|
1367
|
+
seen: NumberShape;
|
|
1368
|
+
created: NumberShape;
|
|
1354
1369
|
};
|
|
1355
1370
|
|
|
1356
1371
|
/**
|
|
1357
|
-
*
|
|
1372
|
+
* Describes the mid-handler control handle `createSession` stashes alongside the
|
|
1358
1373
|
* session itself — the OWASP anti-fixation / logout primitives.
|
|
1359
1374
|
*
|
|
1360
1375
|
* @remarks
|
|
1361
1376
|
* `regenerate` and `destroy` record intent SYNCHRONOUSLY when called; the
|
|
1362
1377
|
* store I/O and transport write happen after the handler's `next()` returns
|
|
1363
1378
|
* (`destroy` supersedes a prior `regenerate`). `regenerate` mints a new id,
|
|
1364
|
-
* carries the session's `
|
|
1379
|
+
* carries the session's `state` over, and invalidates the old id.
|
|
1365
1380
|
*/
|
|
1366
1381
|
export declare interface SessionControlInterface {
|
|
1367
1382
|
regenerate(): void;
|
|
@@ -1369,47 +1384,86 @@ export declare interface SessionControlInterface {
|
|
|
1369
1384
|
}
|
|
1370
1385
|
|
|
1371
1386
|
/**
|
|
1372
|
-
*
|
|
1387
|
+
* Describes the per-session instants a store stamps and `sessionExpired` measures
|
|
1388
|
+
* against.
|
|
1389
|
+
*
|
|
1390
|
+
* @remarks
|
|
1391
|
+
* - `seen` — the instant of the most recent live read or write.
|
|
1392
|
+
* - `created` — the instant of the first `set`, preserved across every
|
|
1393
|
+
* later re-`set` of the same id.
|
|
1394
|
+
*/
|
|
1395
|
+
export declare interface SessionCursors {
|
|
1396
|
+
readonly seen: number;
|
|
1397
|
+
readonly created: number;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
/**
|
|
1401
|
+
* Represents one in-process session entry — the payload {@link MemorySessionStore} holds
|
|
1402
|
+
* against an id, alongside the same cursors a persisted row carries.
|
|
1403
|
+
*
|
|
1404
|
+
* @typeParam S - The stored session entity type
|
|
1405
|
+
*/
|
|
1406
|
+
export declare interface SessionEntry<S extends SessionInterface> extends SessionCursors {
|
|
1407
|
+
readonly session: S;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/**
|
|
1411
|
+
* Checks whether a session has aged past its idle timeout or absolute lifetime as
|
|
1373
1412
|
* of `now` — the pure expiry predicate `MemorySessionStore` delegates to.
|
|
1374
1413
|
*
|
|
1375
|
-
* @param cursors -
|
|
1414
|
+
* @param cursors - See {@link SessionCursors}
|
|
1376
1415
|
* @param now - The current instant (same clock unit as `cursors`)
|
|
1377
|
-
* @param limits -
|
|
1378
|
-
* @returns
|
|
1416
|
+
* @param limits - See {@link SessionLimits}
|
|
1417
|
+
* @returns True if either configured threshold has elapsed; false otherwise
|
|
1379
1418
|
*
|
|
1380
1419
|
* @example
|
|
1381
1420
|
* ```ts
|
|
1382
|
-
* sessionExpired({
|
|
1421
|
+
* sessionExpired({ seen: 0, created: 0 }, 1_000, { ttl: 500 }) // true
|
|
1383
1422
|
* ```
|
|
1384
1423
|
*/
|
|
1385
|
-
export declare function sessionExpired(cursors:
|
|
1386
|
-
readonly lastSeen: number;
|
|
1387
|
-
readonly createdAt: number;
|
|
1388
|
-
}, now: number, limits: {
|
|
1389
|
-
readonly ttl?: number;
|
|
1390
|
-
readonly lifetime?: number;
|
|
1391
|
-
}): boolean;
|
|
1424
|
+
export declare function sessionExpired(cursors: SessionCursors, now: number, limits: SessionLimits): boolean;
|
|
1392
1425
|
|
|
1393
1426
|
/**
|
|
1394
|
-
*
|
|
1427
|
+
* Represents a server-managed session's public surface — an id, its live state, and the
|
|
1428
|
+
* mutators that write it.
|
|
1395
1429
|
*
|
|
1396
1430
|
* @remarks
|
|
1397
|
-
* `
|
|
1398
|
-
*
|
|
1431
|
+
* `state` is a `ReadonlyMap` view a handler reads directly: TypeScript
|
|
1432
|
+
* refuses a write through it, and `set`, `delete`, and `clear` are the write
|
|
1433
|
+
* path. `createSession` persists the state to the configured
|
|
1434
|
+
* {@link SessionStoreInterface} on the way out. `clear` empties the state
|
|
1435
|
+
* without ending the session — `SessionControlInterface.destroy` does that.
|
|
1399
1436
|
*/
|
|
1400
1437
|
export declare interface SessionInterface {
|
|
1401
1438
|
readonly id: string;
|
|
1402
|
-
readonly
|
|
1439
|
+
readonly state: ReadonlyMap<string, unknown>;
|
|
1440
|
+
set(key: string, value: unknown): void;
|
|
1441
|
+
delete(key: string): boolean;
|
|
1442
|
+
clear(): void;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* Describes the idle and absolute-lifetime thresholds a session store enforces —
|
|
1447
|
+
* `sessionExpired`'s limits argument and both shipped stores' construction
|
|
1448
|
+
* options.
|
|
1449
|
+
*
|
|
1450
|
+
* @remarks
|
|
1451
|
+
* - `ttl` — the idle timeout in milliseconds; absent means no idle expiry.
|
|
1452
|
+
* - `lifetime` — the absolute lifetime in milliseconds from the first `set`;
|
|
1453
|
+
* absent means no absolute expiry.
|
|
1454
|
+
*/
|
|
1455
|
+
export declare interface SessionLimits {
|
|
1456
|
+
readonly ttl?: number | undefined;
|
|
1457
|
+
readonly lifetime?: number | undefined;
|
|
1403
1458
|
}
|
|
1404
1459
|
|
|
1405
1460
|
/**
|
|
1406
|
-
*
|
|
1461
|
+
* Configures `createSession` — the generic session battery.
|
|
1407
1462
|
*
|
|
1408
|
-
* @typeParam S - The session
|
|
1463
|
+
* @typeParam S - The session entity type `create` produces
|
|
1409
1464
|
* @typeParam TState - The consumer's opaque per-request state type `mint` reads
|
|
1410
|
-
* @param options - See fields below
|
|
1411
1465
|
* @remarks
|
|
1412
|
-
* - `transport` — the {@link
|
|
1466
|
+
* - `transport` — the {@link SessionTransportInterface} (`createCookieTransport(...)`,
|
|
1413
1467
|
* `createHeaderTransport(...)`, or a custom one).
|
|
1414
1468
|
* - `store` — the {@link SessionStoreInterface}; defaults to
|
|
1415
1469
|
* `createMemorySessionStore({ ttl, lifetime, capacity, evict })`.
|
|
@@ -1426,14 +1480,12 @@ export declare interface SessionInterface {
|
|
|
1426
1480
|
* defaults to `new Session(id)`.
|
|
1427
1481
|
* - `mint` — decides whether to auto-mint a session when none resolves;
|
|
1428
1482
|
* defaults to always minting (auto-session).
|
|
1429
|
-
* - `
|
|
1483
|
+
* - `required` — when `true`, a request that resolves no session and does not
|
|
1430
1484
|
* mint one renders a 404 instead of proceeding sessionless. Defaults to `false`.
|
|
1431
|
-
* - `ends` — when `true`, a `DELETE` request carrying a valid session id
|
|
1432
|
-
* deletes the session and short-circuits with `204`. Defaults to `false`.
|
|
1433
1485
|
* - `clock` — the injected time source fed to the store; defaults to `Date.now`.
|
|
1434
1486
|
*/
|
|
1435
|
-
export declare interface SessionOptions<S, TState = unknown> {
|
|
1436
|
-
readonly transport:
|
|
1487
|
+
export declare interface SessionOptions<S extends SessionInterface, TState = unknown> {
|
|
1488
|
+
readonly transport: SessionTransportInterface;
|
|
1437
1489
|
readonly store?: SessionStoreInterface<S>;
|
|
1438
1490
|
readonly ttl?: number;
|
|
1439
1491
|
readonly lifetime?: number;
|
|
@@ -1441,25 +1493,47 @@ export declare interface SessionOptions<S, TState = unknown> {
|
|
|
1441
1493
|
readonly evict?: (id: string) => void;
|
|
1442
1494
|
readonly create?: (id: string) => S;
|
|
1443
1495
|
readonly mint?: (context: MiddlewareContext<TState>) => boolean | Promise<boolean>;
|
|
1444
|
-
readonly
|
|
1445
|
-
readonly ends?: boolean;
|
|
1496
|
+
readonly required?: boolean;
|
|
1446
1497
|
readonly clock?: () => number;
|
|
1447
1498
|
}
|
|
1448
1499
|
|
|
1449
1500
|
/**
|
|
1450
|
-
*
|
|
1501
|
+
* Rebuilds a session entity from an untrusted stored snapshot, or resolves `undefined` when the value is malformed.
|
|
1502
|
+
*
|
|
1503
|
+
* @remarks
|
|
1504
|
+
* The step {@link DatabaseSessionStore} is constructed with, and the seam a
|
|
1505
|
+
* consumer implements to restore its own session entity from a persisted row.
|
|
1506
|
+
* `createDatabaseSessionStore` supplies `createRestoredSession` as that step.
|
|
1507
|
+
*/
|
|
1508
|
+
export declare type SessionRestoreFunction = (value: unknown) => SessionInterface | undefined;
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Represents one persisted session row — an opaque snapshot column plus the store-owned
|
|
1451
1512
|
* idle/absolute-lifetime cursors, the shape a {@link DatabaseSessionStore}'s
|
|
1452
1513
|
* backing table holds.
|
|
1453
1514
|
*/
|
|
1454
|
-
export declare interface SessionRow {
|
|
1515
|
+
export declare interface SessionRow extends SessionCursors {
|
|
1455
1516
|
readonly id: string;
|
|
1456
1517
|
readonly session: unknown;
|
|
1457
|
-
readonly lastSeen: number;
|
|
1458
|
-
readonly createdAt: number;
|
|
1459
1518
|
}
|
|
1460
1519
|
|
|
1461
1520
|
/**
|
|
1462
|
-
*
|
|
1521
|
+
* Represents a session's serializable projection — the value `snapshotSession` produces
|
|
1522
|
+
* and a durable store's `set` writes.
|
|
1523
|
+
*
|
|
1524
|
+
* @remarks
|
|
1525
|
+
* `state` is the wire member a persisted row carries, built on a
|
|
1526
|
+
* null-prototype record so a session key literally named `__proto__`
|
|
1527
|
+
* round-trips as an own enumerable property. It holds the same entries the
|
|
1528
|
+
* entity's own `state` view publishes.
|
|
1529
|
+
*/
|
|
1530
|
+
export declare interface SessionSnapshot {
|
|
1531
|
+
readonly id: string;
|
|
1532
|
+
readonly state: Readonly<Record<string, unknown>>;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
/**
|
|
1536
|
+
* Describes the session state slice `createSession` stashes.
|
|
1463
1537
|
*
|
|
1464
1538
|
* @remarks
|
|
1465
1539
|
* `session` is present whenever a request resolves or mints a session;
|
|
@@ -1471,24 +1545,34 @@ export declare interface SessionState {
|
|
|
1471
1545
|
}
|
|
1472
1546
|
|
|
1473
1547
|
/**
|
|
1474
|
-
*
|
|
1475
|
-
* implements — a point-access store
|
|
1548
|
+
* Describes the pluggable session persistence seam `createSession`'s `store` option
|
|
1549
|
+
* implements — a point-access store keyed by session id.
|
|
1476
1550
|
*
|
|
1477
|
-
* @typeParam S - The session
|
|
1551
|
+
* @typeParam S - The stored session entity type
|
|
1478
1552
|
* @remarks
|
|
1479
1553
|
* Every primitive is async and takes a trailing `now` clock reading (the
|
|
1480
1554
|
* same seam `createSession`'s `clock` option feeds) so a store can apply its
|
|
1481
1555
|
* own idle/absolute expiry against the caller's injected time rather than
|
|
1482
|
-
* its own wall clock. `
|
|
1483
|
-
|
|
1484
|
-
|
|
1556
|
+
* its own wall clock. `set` reads the id from the session it is handed —
|
|
1557
|
+
* a stored value carries its own id, so no separate id is passed. `delete` of
|
|
1558
|
+
* an absent id is a no-op, never throws.
|
|
1559
|
+
*
|
|
1560
|
+
* `get` must resolve a value satisfying {@link isSession} — an `id` string,
|
|
1561
|
+
* a `state` `Map` view, and the mutators — or `undefined`. `createSession`
|
|
1562
|
+
* dereferences the resolved value's `id` and `state` without re-checking
|
|
1563
|
+
* them, so a store that resolves an off-shape value corrupts the battery's
|
|
1564
|
+
* own state rather than being refused at the seam. The shipped
|
|
1565
|
+
* `DatabaseSessionStore` enforces this with the caller-supplied guard it is
|
|
1566
|
+
* constructed with.
|
|
1567
|
+
*/
|
|
1568
|
+
export declare interface SessionStoreInterface<S extends SessionInterface> {
|
|
1485
1569
|
get(id: string, now: number): Promise<S | undefined>;
|
|
1486
|
-
set(
|
|
1570
|
+
set(session: S, now: number): Promise<void>;
|
|
1487
1571
|
delete(id: string): Promise<void>;
|
|
1488
1572
|
}
|
|
1489
1573
|
|
|
1490
1574
|
/**
|
|
1491
|
-
*
|
|
1575
|
+
* Describes the transport seam `createSession`'s `transport` option implements — how a
|
|
1492
1576
|
* session id travels to and from the client (a signed cookie, a header, …).
|
|
1493
1577
|
*
|
|
1494
1578
|
* @remarks
|
|
@@ -1498,24 +1582,25 @@ export declare interface SessionStoreInterface<S> {
|
|
|
1498
1582
|
* called only when a session is freshly minted or regenerated; `clear` is
|
|
1499
1583
|
* called on `destroy()`. `write`'s `encrypted` flag is the request's resolved
|
|
1500
1584
|
* transport security (derived from `context.url.protocol`) so a cookie
|
|
1501
|
-
* transport can resolve its own `Secure` attribute
|
|
1585
|
+
* transport can resolve its own `Secure` attribute through `resolveSecure`
|
|
1502
1586
|
* without re-deriving connection facts itself.
|
|
1503
1587
|
*/
|
|
1504
|
-
export declare interface
|
|
1588
|
+
export declare interface SessionTransportInterface {
|
|
1505
1589
|
read(request: Request): string | undefined | Promise<string | undefined>;
|
|
1506
1590
|
write(response: Response, id: string, encrypted: boolean): void | Promise<void>;
|
|
1507
1591
|
clear(response: Response): void;
|
|
1508
1592
|
}
|
|
1509
1593
|
|
|
1510
1594
|
/**
|
|
1511
|
-
*
|
|
1595
|
+
* Snapshots a session's `state` into a plain, serializable record — the
|
|
1512
1596
|
* projection a durable store's `set` writes to disk.
|
|
1513
1597
|
*
|
|
1514
1598
|
* @param session - The session to snapshot
|
|
1515
|
-
* @returns A plain-object copy of
|
|
1599
|
+
* @returns A {@link SessionSnapshot} whose `state` is a plain-object copy of
|
|
1600
|
+
* `session.state`, keyed alongside `session.id`
|
|
1516
1601
|
*
|
|
1517
1602
|
* @remarks
|
|
1518
|
-
* `
|
|
1603
|
+
* `state` is built on a null-prototype object (`Object.create(null)`), never
|
|
1519
1604
|
* a `{}` literal — a session key literally named `__proto__` must round-trip
|
|
1520
1605
|
* as an OWN enumerable property instead of hitting `Object.prototype`'s
|
|
1521
1606
|
* `__proto__` accessor (which would silently drop the entry and risk
|
|
@@ -1523,16 +1608,13 @@ export declare interface SessionTransport {
|
|
|
1523
1608
|
*
|
|
1524
1609
|
* @example
|
|
1525
1610
|
* ```ts
|
|
1526
|
-
* snapshotSession(session) // { id: 'abc',
|
|
1611
|
+
* snapshotSession(session) // { id: 'abc', state: { userId: 'u_1' } }
|
|
1527
1612
|
* ```
|
|
1528
1613
|
*/
|
|
1529
|
-
export declare function snapshotSession(session: SessionInterface):
|
|
1530
|
-
readonly id: string;
|
|
1531
|
-
readonly data: Record<string, unknown>;
|
|
1532
|
-
};
|
|
1614
|
+
export declare function snapshotSession(session: SessionInterface): SessionSnapshot;
|
|
1533
1615
|
|
|
1534
1616
|
/**
|
|
1535
|
-
*
|
|
1617
|
+
* Represents one access-log-style entry `createTelemetry` records after a response
|
|
1536
1618
|
* settles — the access-log/timing seam's payload shape.
|
|
1537
1619
|
*
|
|
1538
1620
|
* @remarks
|
|
@@ -1551,9 +1633,8 @@ export declare interface TelemetryEntry {
|
|
|
1551
1633
|
}
|
|
1552
1634
|
|
|
1553
1635
|
/**
|
|
1554
|
-
*
|
|
1636
|
+
* Configures `createTelemetry` — the request timing/access-log seam.
|
|
1555
1637
|
*
|
|
1556
|
-
* @param options - See fields below
|
|
1557
1638
|
* @remarks
|
|
1558
1639
|
* - `record` — invoked once per request with the settled {@link
|
|
1559
1640
|
* TelemetryEntry}; its own throw is swallowed so a broken sink can never
|
|
@@ -1564,17 +1645,36 @@ export declare interface TelemetryOptions {
|
|
|
1564
1645
|
}
|
|
1565
1646
|
|
|
1566
1647
|
/**
|
|
1567
|
-
*
|
|
1568
|
-
*
|
|
1648
|
+
* Copies every entry of one session's `state` into another — the regenerate
|
|
1649
|
+
* state-carry `createSession`'s `control.regenerate()` applies.
|
|
1650
|
+
*
|
|
1651
|
+
* @param from - The source session whose `state` is copied
|
|
1652
|
+
* @param to - The destination session the entries are written into, through
|
|
1653
|
+
* its own `set` mutator
|
|
1654
|
+
*
|
|
1655
|
+
* @example
|
|
1656
|
+
* ```ts
|
|
1657
|
+
* transferSessionState(oldSession, newSession)
|
|
1658
|
+
* ```
|
|
1659
|
+
*/
|
|
1660
|
+
export declare function transferSessionState(from: SessionInterface, to: SessionInterface): void;
|
|
1661
|
+
|
|
1662
|
+
/**
|
|
1663
|
+
* Validates a store's idle and absolute-lifetime thresholds, throwing when
|
|
1664
|
+
* either is present and malformed — the shared construction gate
|
|
1665
|
+
* {@link MemorySessionStore} and {@link DatabaseSessionStore} both apply, so
|
|
1666
|
+
* one malformed `ttl` is refused identically by whichever store receives it.
|
|
1569
1667
|
*
|
|
1570
|
-
* @param
|
|
1571
|
-
* @
|
|
1668
|
+
* @param limits - See {@link SessionLimits}
|
|
1669
|
+
* @returns Nothing; a successful return means both thresholds are usable
|
|
1670
|
+
* @throws {TypeError} Thrown when `ttl` or `lifetime` is present and is not a
|
|
1671
|
+
* positive finite number
|
|
1572
1672
|
*
|
|
1573
1673
|
* @example
|
|
1574
1674
|
* ```ts
|
|
1575
|
-
*
|
|
1675
|
+
* validateSessionLimits({ ttl: 60_000 }) // returns; the thresholds are usable
|
|
1576
1676
|
* ```
|
|
1577
1677
|
*/
|
|
1578
|
-
export declare function
|
|
1678
|
+
export declare function validateSessionLimits(limits: SessionLimits | undefined): void;
|
|
1579
1679
|
|
|
1580
1680
|
export { }
|