@nifrajs/core 5.5.0 → 5.6.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/CHANGELOG.md +159 -0
- package/dist/assurance.d.ts.map +1 -1
- package/dist/assurance.js.map +1 -1
- package/dist/evidence.d.ts +2 -0
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +2 -0
- package/dist/evidence.js.map +1 -1
- package/dist/file-type.d.ts +30 -0
- package/dist/file-type.d.ts.map +1 -0
- package/dist/file-type.js +118 -0
- package/dist/file-type.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/route-program.d.ts +11 -0
- package/dist/internal/route-program.d.ts.map +1 -1
- package/dist/internal/route-program.js +133 -85
- package/dist/internal/route-program.js.map +1 -1
- package/dist/reflection.d.ts +14 -1
- package/dist/reflection.d.ts.map +1 -1
- package/dist/reflection.js +34 -7
- package/dist/reflection.js.map +1 -1
- package/dist/response-observer.d.ts +1 -0
- package/dist/response-observer.d.ts.map +1 -1
- package/dist/response-observer.js +1 -0
- package/dist/response-observer.js.map +1 -1
- package/dist/server/bare-error-lane.d.ts +4 -1
- package/dist/server/bare-error-lane.d.ts.map +1 -1
- package/dist/server/bare-error-lane.js +9 -3
- package/dist/server/bare-error-lane.js.map +1 -1
- package/dist/server/before-handler.d.ts +10 -0
- package/dist/server/before-handler.d.ts.map +1 -0
- package/dist/server/before-handler.js +12 -0
- package/dist/server/before-handler.js.map +1 -0
- package/dist/server/body-lane.d.ts.map +1 -1
- package/dist/server/body-lane.js +8 -2
- package/dist/server/body-lane.js.map +1 -1
- package/dist/server/body-parser.d.ts.map +1 -1
- package/dist/server/body-parser.js +2 -5
- package/dist/server/body-parser.js.map +1 -1
- package/dist/server/body.d.ts +24 -8
- package/dist/server/body.d.ts.map +1 -1
- package/dist/server/body.js +86 -33
- package/dist/server/body.js.map +1 -1
- package/dist/server/core-copies.js +1 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +6 -17
- package/dist/server/http.js.map +1 -1
- package/dist/server/multipart.d.ts +3 -0
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/multipart.js +226 -97
- package/dist/server/multipart.js.map +1 -1
- package/dist/server/proto-guard.d.ts.map +1 -1
- package/dist/server/proto-guard.js +39 -4
- package/dist/server/proto-guard.js.map +1 -1
- package/dist/server/query.d.ts.map +1 -1
- package/dist/server/query.js +8 -14
- package/dist/server/query.js.map +1 -1
- package/dist/server/repeated-prefix.d.ts +17 -0
- package/dist/server/repeated-prefix.d.ts.map +1 -0
- package/dist/server/repeated-prefix.js +17 -0
- package/dist/server/repeated-prefix.js.map +1 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +1 -3
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/respond.d.ts +1 -3
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +21 -16
- package/dist/server/respond.js.map +1 -1
- package/dist/server/response-contract-lane.d.ts +12 -2
- package/dist/server/response-contract-lane.d.ts.map +1 -1
- package/dist/server/response-contract-lane.js +135 -8
- package/dist/server/response-contract-lane.js.map +1 -1
- package/dist/server/runtime-core.d.ts +7 -0
- package/dist/server/runtime-core.d.ts.map +1 -1
- package/dist/server/runtime-core.js +8 -1
- package/dist/server/runtime-core.js.map +1 -1
- package/dist/server/server-types.d.ts +6 -3
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +6 -2
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +239 -78
- package/dist/server/server.js.map +1 -1
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +5 -4
- package/dist/server/sse.js.map +1 -1
- package/dist/server/webhook.d.ts +1 -1
- package/dist/server/webhook.d.ts.map +1 -1
- package/dist/server/webhook.js +24 -19
- package/dist/server/webhook.js.map +1 -1
- package/dist/server/websocket.d.ts +18 -3
- package/dist/server/websocket.d.ts.map +1 -1
- package/dist/server/websocket.js +45 -5
- package/dist/server/websocket.js.map +1 -1
- package/dist/server/ws-bun.d.ts.map +1 -1
- package/dist/server/ws-bun.js +12 -3
- package/dist/server/ws-bun.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/tool-cli.d.ts +64 -0
- package/dist/tool-cli.d.ts.map +1 -0
- package/dist/tool-cli.js +495 -0
- package/dist/tool-cli.js.map +1 -0
- package/package.json +11 -1
- package/src/assurance.ts +1 -0
- package/src/evidence.ts +4 -0
- package/src/file-type.ts +130 -0
- package/src/index.ts +2 -1
- package/src/internal/route-program.ts +261 -93
- package/src/reflection.ts +53 -7
- package/src/response-observer.ts +6 -0
- package/src/server/bare-error-lane.ts +9 -4
- package/src/server/before-handler.ts +14 -0
- package/src/server/body-lane.ts +19 -9
- package/src/server/body-parser.ts +1 -5
- package/src/server/body.ts +96 -36
- package/src/server/core-copies.ts +1 -1
- package/src/server/http.ts +6 -15
- package/src/server/multipart.ts +232 -100
- package/src/server/proto-guard.ts +39 -4
- package/src/server/query.ts +7 -13
- package/src/server/repeated-prefix.ts +25 -0
- package/src/server/request-context.ts +1 -3
- package/src/server/respond.ts +23 -15
- package/src/server/response-contract-lane.ts +130 -8
- package/src/server/runtime-core.ts +10 -1
- package/src/server/server-types.ts +6 -3
- package/src/server/server.ts +265 -76
- package/src/server/sse.ts +6 -5
- package/src/server/webhook.ts +29 -24
- package/src/server/websocket.ts +57 -8
- package/src/server/ws-bun.ts +17 -2
- package/src/server.ts +1 -0
- package/src/tool-cli.ts +584 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Magic-byte file-type detection - trust the bytes, not the `Content-Type` header (which a client
|
|
3
|
+
* sets freely). Reads only the leading bytes; imports nothing, so it is edge-safe. Covers the common
|
|
4
|
+
* upload types; returns `null` for anything unrecognized (incl. text formats like SVG/CSV that have no
|
|
5
|
+
* magic number - handle those explicitly if you accept them).
|
|
6
|
+
*
|
|
7
|
+
* The shared owner for every type-by-bytes check: `@nifrajs/schema/form`'s `t.file({ accept })` and
|
|
8
|
+
* `@nifrajs/uploads`'s `validateUpload` must give one file one verdict, so both read this module.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* How many leading bytes {@link detectFileType} looks at. Reading this many from the start of a file
|
|
12
|
+
* (`file.slice(0, FILE_TYPE_PREFIX_BYTES)`) is enough for every type it knows: it reaches the first four
|
|
13
|
+
* compatible brands of an ISO-BMFF `ftyp` box, where an AVIF with the generic `mif1` brand says `avif`.
|
|
14
|
+
*/
|
|
15
|
+
export const FILE_TYPE_PREFIX_BYTES = 32;
|
|
16
|
+
/**
|
|
17
|
+
* Every MIME type {@link detectFileType} can return. An allow-list entry outside this set (and
|
|
18
|
+
* outside a `type/*` wildcard that covers one of them) can never match, so check a configured
|
|
19
|
+
* allow-list against it up front instead of rejecting every upload at request time.
|
|
20
|
+
*/
|
|
21
|
+
export const DETECTABLE_MIME_TYPES = [
|
|
22
|
+
"image/jpeg",
|
|
23
|
+
"image/png",
|
|
24
|
+
"image/gif",
|
|
25
|
+
"image/webp",
|
|
26
|
+
"audio/wav",
|
|
27
|
+
"video/x-msvideo",
|
|
28
|
+
"image/avif",
|
|
29
|
+
"image/heic",
|
|
30
|
+
"audio/mp4",
|
|
31
|
+
"video/mp4",
|
|
32
|
+
"video/webm",
|
|
33
|
+
"audio/ogg",
|
|
34
|
+
"audio/mpeg",
|
|
35
|
+
"application/pdf",
|
|
36
|
+
"application/zip",
|
|
37
|
+
"application/gzip",
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* An MPEG audio frame header: an 11-bit frame sync, then a version, layer, bitrate and sample rate that
|
|
41
|
+
* are not reserved values. An MP3 needs no ID3 tag, so this is how an untagged one starts. AAC's ADTS
|
|
42
|
+
* sync shares the first 12 bits, but its layer is always the reserved `00`.
|
|
43
|
+
*/
|
|
44
|
+
function mpegAudioFrame(bytes) {
|
|
45
|
+
const [b0 = 0, b1 = 0, b2 = 0] = bytes;
|
|
46
|
+
if (bytes.length < 4 || b0 !== 0xff || (b1 & 0xe0) !== 0xe0)
|
|
47
|
+
return false;
|
|
48
|
+
const version = (b1 >> 3) & 0b11;
|
|
49
|
+
const layer = (b1 >> 1) & 0b11;
|
|
50
|
+
const bitrate = b2 >> 4;
|
|
51
|
+
const sampleRate = (b2 >> 2) & 0b11;
|
|
52
|
+
return version !== 0b01 && layer !== 0b00 && bitrate !== 0b1111 && sampleRate !== 0b11;
|
|
53
|
+
}
|
|
54
|
+
/** Detect a file's type from its magic bytes, or `null` if unrecognized. */
|
|
55
|
+
export function detectFileType(bytes) {
|
|
56
|
+
const at = (offset, ...sig) => sig.every((byte, i) => bytes[offset + i] === byte);
|
|
57
|
+
// Images
|
|
58
|
+
if (at(0, 0xff, 0xd8, 0xff))
|
|
59
|
+
return { mime: "image/jpeg", ext: "jpg" };
|
|
60
|
+
if (at(0, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a))
|
|
61
|
+
return { mime: "image/png", ext: "png" };
|
|
62
|
+
if (at(0, 0x47, 0x49, 0x46, 0x38))
|
|
63
|
+
return { mime: "image/gif", ext: "gif" };
|
|
64
|
+
// RIFF container (bytes 0-3 "RIFF", 8-11 the form type)
|
|
65
|
+
if (at(0, 0x52, 0x49, 0x46, 0x46)) {
|
|
66
|
+
if (at(8, 0x57, 0x45, 0x42, 0x50))
|
|
67
|
+
return { mime: "image/webp", ext: "webp" };
|
|
68
|
+
if (at(8, 0x57, 0x41, 0x56, 0x45))
|
|
69
|
+
return { mime: "audio/wav", ext: "wav" };
|
|
70
|
+
if (at(8, 0x41, 0x56, 0x49, 0x20))
|
|
71
|
+
return { mime: "video/x-msvideo", ext: "avi" };
|
|
72
|
+
}
|
|
73
|
+
// ISO-BMFF (`ftyp` box at offset 4) - mp4 / avif / heic / m4a, disambiguated by the major brand.
|
|
74
|
+
if (at(4, 0x66, 0x74, 0x79, 0x70)) {
|
|
75
|
+
const brandAt = (offset) => String.fromCharCode(bytes[offset] ?? 0, bytes[offset + 1] ?? 0, bytes[offset + 2] ?? 0, bytes[offset + 3] ?? 0);
|
|
76
|
+
const brand = brandAt(8);
|
|
77
|
+
// The compatible brands follow the minor version, to the end of the ftyp box. Only those inside the
|
|
78
|
+
// prefix count: the box size is the sender's claim, and a verdict must not depend on bytes a caller
|
|
79
|
+
// that sniffs `FILE_TYPE_PREFIX_BYTES` never reads.
|
|
80
|
+
const boxEnd = Math.min(bytes.length, FILE_TYPE_PREFIX_BYTES, ((bytes[0] ?? 0) << 24) | ((bytes[1] ?? 0) << 16) | ((bytes[2] ?? 0) << 8) | (bytes[3] ?? 0));
|
|
81
|
+
const compatible = [];
|
|
82
|
+
for (let offset = 16; offset + 4 <= boxEnd; offset += 4)
|
|
83
|
+
compatible.push(brandAt(offset));
|
|
84
|
+
// A HEIF-family file whose major brand is the generic `mif1`/`msf1`/`miaf` names its codec among
|
|
85
|
+
// the compatible brands: AVIF says `avif`/`avis`.
|
|
86
|
+
const avif = (name) => name === "avif" || name === "avis";
|
|
87
|
+
const generic = brand === "mif1" || brand === "msf1" || brand === "miaf";
|
|
88
|
+
if (avif(brand) || (generic && compatible.some(avif)))
|
|
89
|
+
return { mime: "image/avif", ext: "avif" };
|
|
90
|
+
if (brand.startsWith("hei") || brand.startsWith("hev") || generic) {
|
|
91
|
+
return { mime: "image/heic", ext: "heic" };
|
|
92
|
+
}
|
|
93
|
+
// Audio brands share the ISO-BMFF container but are NOT video - labeling them `video/mp4` would
|
|
94
|
+
// both reject real audio under an `audio/*` allow-list and admit it under `video/*`. `M4A `/`M4B `
|
|
95
|
+
// are AAC audio / audiobooks.
|
|
96
|
+
if (brand === "M4A " || brand === "M4B ")
|
|
97
|
+
return { mime: "audio/mp4", ext: "m4a" };
|
|
98
|
+
return { mime: "video/mp4", ext: "mp4" };
|
|
99
|
+
}
|
|
100
|
+
// A/V + archives
|
|
101
|
+
if (at(0, 0x1a, 0x45, 0xdf, 0xa3))
|
|
102
|
+
return { mime: "video/webm", ext: "webm" }; // Matroska/WebM
|
|
103
|
+
if (at(0, 0x4f, 0x67, 0x67, 0x53))
|
|
104
|
+
return { mime: "audio/ogg", ext: "ogg" };
|
|
105
|
+
if (at(0, 0x49, 0x44, 0x33))
|
|
106
|
+
return { mime: "audio/mpeg", ext: "mp3" }; // ID3 tag
|
|
107
|
+
if (mpegAudioFrame(bytes))
|
|
108
|
+
return { mime: "audio/mpeg", ext: "mp3" }; // an untagged MP3
|
|
109
|
+
if (at(0, 0x25, 0x50, 0x44, 0x46))
|
|
110
|
+
return { mime: "application/pdf", ext: "pdf" }; // "%PDF"
|
|
111
|
+
if (at(0, 0x50, 0x4b, 0x03, 0x04) || at(0, 0x50, 0x4b, 0x05, 0x06)) {
|
|
112
|
+
return { mime: "application/zip", ext: "zip" }; // also docx/xlsx/odt containers
|
|
113
|
+
}
|
|
114
|
+
if (at(0, 0x1f, 0x8b))
|
|
115
|
+
return { mime: "application/gzip", ext: "gz" };
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=file-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-type.js","sourceRoot":"","sources":["../src/file-type.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and
|
|
16
16
|
* `check:publish` asserts it equals `@nifrajs/core`'s package version.
|
|
17
17
|
*/
|
|
18
|
-
export declare const VERSION: "5.
|
|
18
|
+
export declare const VERSION: "5.6.0";
|
|
19
19
|
export type Version = typeof VERSION;
|
|
20
20
|
export { FrameworkError, RouteConfigError, type RouteConfigErrorCode } from "./errors.js";
|
|
21
21
|
export { FRAMEWORK_NAME, type FrameworkName } from "./internal/brand.js";
|
|
@@ -24,6 +24,7 @@ export { ROUTE_PATTERN_OVERLAP_MAX_STATES, RoutePatternOverlapLimitError, routeP
|
|
|
24
24
|
export { METHODS, type Method, type RouteMethod, Router, type RouterMatch, } from "./router/router.js";
|
|
25
25
|
export type { InferInput, InferOutput, StandardIssue, StandardResult, StandardSchemaV1, StandardTypes, ValidationOutcome, } from "./schema/standard.js";
|
|
26
26
|
export { type AuthenticationFailure, type AuthenticationFailureReason, type AuthenticationInput, type AuthenticationResult, type AuthenticationStage, type AuthenticationSuccess, type AuthHeaders, type AuthMaybePromise, authenticated, isAuthenticatedRequest, markAuthenticatedRequest, rejected, } from "./server/auth.js";
|
|
27
|
+
export { beforeHandler } from "./server/before-handler.js";
|
|
27
28
|
export type { Context, Params, Platform, Prettify, RequestPath, ResponseControls, RouteSchema, } from "./server/context.js";
|
|
28
29
|
export { type CookieOptions, type CookieSecret, cookieNamePrefix, hasDuplicateCookie, parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
29
30
|
export { type DurableObjectNamespaceLike, type ExecutionContext, type ScheduledController, type ScheduledHandler, toFetchHandler, } from "./server/edge.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,13 +15,14 @@
|
|
|
15
15
|
* read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and
|
|
16
16
|
* `check:publish` asserts it equals `@nifrajs/core`'s package version.
|
|
17
17
|
*/
|
|
18
|
-
export const VERSION = "5.
|
|
18
|
+
export const VERSION = "5.6.0";
|
|
19
19
|
export { FrameworkError, RouteConfigError } from "./errors.js";
|
|
20
20
|
export { FRAMEWORK_NAME } from "./internal/brand.js";
|
|
21
21
|
export { isSameOriginForm, isSameOriginRequest } from "./internal/same-origin.js";
|
|
22
22
|
export { ROUTE_PATTERN_OVERLAP_MAX_STATES, RoutePatternOverlapLimitError, routePatternOverlap, } from "./router/overlap.js";
|
|
23
23
|
export { METHODS, Router, } from "./router/router.js";
|
|
24
24
|
export { authenticated, isAuthenticatedRequest, markAuthenticatedRequest, rejected, } from "./server/auth.js";
|
|
25
|
+
export { beforeHandler } from "./server/before-handler.js";
|
|
25
26
|
export { cookieNamePrefix, hasDuplicateCookie, parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
26
27
|
export { toFetchHandler, } from "./server/edge.js";
|
|
27
28
|
export { isSameOriginPath, pathnameOf, urlPartsOf } from "./server/http.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAgB,CAAA;AAIvC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,OAAO,EAGP,MAAM,GAEP,MAAM,oBAAoB,CAAA;AAU3B,OAAO,EASL,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,QAAQ,GACT,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAgB,CAAA;AAIvC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,OAAO,EAGP,MAAM,GAEP,MAAM,oBAAoB,CAAA;AAU3B,OAAO,EASL,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,QAAQ,GACT,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAU1D,OAAO,EAGL,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAKL,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAiB,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC1F,OAAO,EACL,oBAAoB,EACpB,UAAU,EAIV,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAUL,eAAe,EACf,gBAAgB,EAChB,eAAe,GAEhB,MAAM,+BAA+B,CAAA;AAStC,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAIL,MAAM,GACP,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAOL,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EA8BlB,MAAM,EAEN,MAAM,GAEP,MAAM,oBAAoB,CAAA"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* of rediscovering which lifecycle features are present.
|
|
8
8
|
*/
|
|
9
9
|
import type { StandardSchemaV1 } from "../schema/standard.js";
|
|
10
|
+
import type { Logger } from "../server/logger.js";
|
|
10
11
|
import type { Registry } from "../server/registry.js";
|
|
11
12
|
import { type ResponseResult } from "../server/runtime-core.js";
|
|
12
13
|
import type { CtxSet, MaybePromise, RawContext, RequestSource, Server } from "../server/server.js";
|
|
@@ -73,6 +74,16 @@ export declare function compileRouteProgram(input: RouteProgramInput): RouteProg
|
|
|
73
74
|
* buffered, and with a replay entry and program when the key already holds a response.
|
|
74
75
|
*/
|
|
75
76
|
export type IdempotencyResume<T> = (entry: RouteEntry, program: RouteProgram) => ProgramResult<T>;
|
|
77
|
+
/**
|
|
78
|
+
* Run the `authenticate()` stages a mount was registered after, in order, against the request the
|
|
79
|
+
* mount would receive: `undefined` once each one authenticated, else the response that refuses it. A
|
|
80
|
+
* stage that throws or decides nothing valid answers 503, and its cause goes to `logger`, as a route
|
|
81
|
+
* error no hook answers does.
|
|
82
|
+
*/
|
|
83
|
+
export declare function authenticateMount(stages: readonly RawAuthStage[], request: Request, platform: {
|
|
84
|
+
readonly env?: unknown;
|
|
85
|
+
readonly clientIp?: string | undefined;
|
|
86
|
+
} | undefined, logger: Logger): MaybePromise<Response | undefined>;
|
|
76
87
|
type ProgramResult<T> = MaybePromise<T>;
|
|
77
88
|
/** Execute the general program. The first synchronous stage sequence stays synchronous. */
|
|
78
89
|
export declare function executeRouteProgram<T, R extends Registry, Ctx>(runtime: Server<R, Ctx>, entry: RouteEntry, program: RouteProgram, source: RequestSource, ctx: RawContext, finalize: (result: unknown, set: CtxSet, ctx?: RawContext) => T, wrapResponse: (response: Response | ResponseResult) => T): ProgramResult<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-program.d.ts","sourceRoot":"","sources":["../../src/internal/route-program.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"route-program.d.ts","sourceRoot":"","sources":["../../src/internal/route-program.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { markAuthenticatedRequest } from "../server/auth.js";
|
|
|
10
10
|
import { declaredHeaderNames } from "../server/headers.js";
|
|
11
11
|
import { pathnameOf } from "../server/http.js";
|
|
12
12
|
import { queryObjectOf } from "../server/query.js";
|
|
13
|
+
import { toResponse } from "../server/respond.js";
|
|
13
14
|
import { CONTEXT_SEARCH, CONTEXT_SET, EMPTY_RESPONSE_CONTROLS, isResponseResult, requestOf, status, } from "../server/runtime-core.js";
|
|
14
15
|
/** Build the immutable stage sequence once, while the server is still configurable. */
|
|
15
16
|
export function compileRouteProgram(input) {
|
|
@@ -119,6 +120,70 @@ function authenticationInputOf(source, ctx) {
|
|
|
119
120
|
signal: ctx.signal,
|
|
120
121
|
});
|
|
121
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Run the `authenticate()` stages a mount was registered after, in order, against the request the
|
|
125
|
+
* mount would receive: `undefined` once each one authenticated, else the response that refuses it. A
|
|
126
|
+
* stage that throws or decides nothing valid answers 503, and its cause goes to `logger`, as a route
|
|
127
|
+
* error no hook answers does.
|
|
128
|
+
*/
|
|
129
|
+
export function authenticateMount(stages, request, platform, logger) {
|
|
130
|
+
let query;
|
|
131
|
+
const search = (() => {
|
|
132
|
+
const at = request.url.indexOf("?");
|
|
133
|
+
return at === -1 ? "" : request.url.slice(at);
|
|
134
|
+
})();
|
|
135
|
+
const input = Object.freeze({
|
|
136
|
+
method: request.method,
|
|
137
|
+
pathname: pathnameOf(request.url),
|
|
138
|
+
headers: authHeadersOf(request),
|
|
139
|
+
params: Object.freeze({}),
|
|
140
|
+
search,
|
|
141
|
+
get query() {
|
|
142
|
+
query ??= frozenQueryOf(search);
|
|
143
|
+
return query;
|
|
144
|
+
},
|
|
145
|
+
request,
|
|
146
|
+
env: platform?.env,
|
|
147
|
+
clientIp: platform?.clientIp,
|
|
148
|
+
signal: request.signal,
|
|
149
|
+
});
|
|
150
|
+
const unavailable = (error) => {
|
|
151
|
+
logger.error("authenticate() stage failed before a mount", {
|
|
152
|
+
method: request.method,
|
|
153
|
+
path: input.pathname,
|
|
154
|
+
error: error instanceof Error ? error.message : String(error),
|
|
155
|
+
});
|
|
156
|
+
return toResponse(defaultAuthenticationResponse("unavailable"), EMPTY_RESPONSE_CONTROLS);
|
|
157
|
+
};
|
|
158
|
+
const decide = (index, result) => {
|
|
159
|
+
if (!isAuthenticationDecision(result)) {
|
|
160
|
+
const id = stages[index]?.id;
|
|
161
|
+
return unavailable(new TypeError(`authenticate() stage "${id}" returned an invalid decision`));
|
|
162
|
+
}
|
|
163
|
+
if (result.kind === "rejected") {
|
|
164
|
+
const refusal = result.response ?? defaultAuthenticationResponse(result.reason);
|
|
165
|
+
return refusal instanceof Response ? refusal : toResponse(refusal, EMPTY_RESPONSE_CONTROLS);
|
|
166
|
+
}
|
|
167
|
+
markAuthenticatedRequest(request);
|
|
168
|
+
return run(index + 1);
|
|
169
|
+
};
|
|
170
|
+
const run = (index) => {
|
|
171
|
+
const stage = stages[index];
|
|
172
|
+
if (stage === undefined)
|
|
173
|
+
return undefined;
|
|
174
|
+
let outcome;
|
|
175
|
+
try {
|
|
176
|
+
outcome = stage.run(input);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
return unavailable(error);
|
|
180
|
+
}
|
|
181
|
+
return outcome instanceof Promise
|
|
182
|
+
? outcome.then((settled) => decide(index, settled), unavailable)
|
|
183
|
+
: decide(index, outcome);
|
|
184
|
+
};
|
|
185
|
+
return run(0);
|
|
186
|
+
}
|
|
122
187
|
function defaultAuthenticationResponse(reason) {
|
|
123
188
|
if (reason === "forbidden")
|
|
124
189
|
return status(403, { ok: false, error: "forbidden" });
|
|
@@ -126,6 +191,20 @@ function defaultAuthenticationResponse(reason) {
|
|
|
126
191
|
return status(503, { ok: false, error: "auth_unavailable" });
|
|
127
192
|
return status(401, { ok: false, error: "unauthorized" });
|
|
128
193
|
}
|
|
194
|
+
/** Whether a stage returned a decision it may: a rejection with a known reason and a response, if
|
|
195
|
+
* any, that answers; or a principal. */
|
|
196
|
+
function isAuthenticationDecision(result) {
|
|
197
|
+
return (result !== null &&
|
|
198
|
+
typeof result === "object" &&
|
|
199
|
+
(result.kind === "rejected"
|
|
200
|
+
? validAuthenticationFailureReason(result.reason) &&
|
|
201
|
+
(result.response === undefined ||
|
|
202
|
+
result.response instanceof Response ||
|
|
203
|
+
isResponseResult(result.response))
|
|
204
|
+
: result.kind === "authenticated" &&
|
|
205
|
+
result.principal !== null &&
|
|
206
|
+
result.principal !== undefined));
|
|
207
|
+
}
|
|
129
208
|
function validAuthenticationFailureReason(value) {
|
|
130
209
|
return (value === undefined ||
|
|
131
210
|
value === "unauthenticated" ||
|
|
@@ -176,16 +255,7 @@ function runAuthenticationStages(host, entry, program, source, ctx, finalize, wr
|
|
|
176
255
|
return finishAuthentication(host, entry, program, source, ctx, finalize, wrapResponse, outcome, start + 1, validationComplete);
|
|
177
256
|
}
|
|
178
257
|
function finishAuthentication(host, entry, program, source, ctx, finalize, wrapResponse, result, next, validationComplete = false) {
|
|
179
|
-
if (result
|
|
180
|
-
typeof result !== "object" ||
|
|
181
|
-
(result.kind === "rejected"
|
|
182
|
-
? !validAuthenticationFailureReason(result.reason) ||
|
|
183
|
-
(result.response !== undefined &&
|
|
184
|
-
!(result.response instanceof Response) &&
|
|
185
|
-
!isResponseResult(result.response))
|
|
186
|
-
: result.kind !== "authenticated" ||
|
|
187
|
-
result.principal === null ||
|
|
188
|
-
result.principal === undefined)) {
|
|
258
|
+
if (!isAuthenticationDecision(result)) {
|
|
189
259
|
const id = program.authStages[next - 1].id;
|
|
190
260
|
const error = new TypeError(`authenticate() stage "${id}" returned an invalid decision`);
|
|
191
261
|
return failAuthentication(host, entry, ctx, finalize, wrapResponse, error);
|
|
@@ -223,7 +293,8 @@ async function continueFastAuthenticatedProgram(host, entry, program, source, ct
|
|
|
223
293
|
const settled = await pending;
|
|
224
294
|
if (settled !== undefined)
|
|
225
295
|
return wrapResponse(settled);
|
|
226
|
-
|
|
296
|
+
const outcome = runFastAuthenticatedProgram(host, entry, program, source, ctx, finalize, wrapResponse, validationIndex);
|
|
297
|
+
return outcome instanceof Promise ? await outcome : outcome;
|
|
227
298
|
}
|
|
228
299
|
catch (error) {
|
|
229
300
|
return await host.handleProgramError(entry, error, ctx, finalize, wrapResponse);
|
|
@@ -261,7 +332,8 @@ async function continueValidationBeforeAuthentication(host, entry, program, sour
|
|
|
261
332
|
const settled = await pending;
|
|
262
333
|
if (settled !== undefined)
|
|
263
334
|
return wrapResponse(settled);
|
|
264
|
-
|
|
335
|
+
const outcome = runValidationBeforeAuthentication(host, entry, program, source, ctx, finalize, wrapResponse, validationIndex);
|
|
336
|
+
return outcome instanceof Promise ? await outcome : outcome;
|
|
265
337
|
}
|
|
266
338
|
catch (error) {
|
|
267
339
|
return await host.handleProgramError(entry, error, ctx, finalize, wrapResponse);
|
|
@@ -273,23 +345,27 @@ function runValidatedProgram(host, entry, program, source, ctx, finalize, wrapRe
|
|
|
273
345
|
return runSync(host, entry, program, source, ctx, finalize, wrapResponse, 0, undefined);
|
|
274
346
|
}
|
|
275
347
|
/** Opt-in sensitive-route lane: run authentication/policy hooks before parsing untrusted input. */
|
|
276
|
-
|
|
348
|
+
function runAuthBeforeValidation(host, entry, program, source, ctx, finalize, wrapResponse, gated = false, deriveStart = 0, beforeStart = 0, validationStart = 0) {
|
|
277
349
|
try {
|
|
278
350
|
if (!gated) {
|
|
279
|
-
if (program.hasDecorations)
|
|
351
|
+
if (deriveStart === 0 && beforeStart === 0 && program.hasDecorations)
|
|
280
352
|
Object.assign(ctx, program.decorations);
|
|
281
|
-
for (
|
|
282
|
-
const result =
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
353
|
+
for (let i = deriveStart; i < program.derives.length; i++) {
|
|
354
|
+
const result = program.derives[i](ctx);
|
|
355
|
+
if (result instanceof Promise) {
|
|
356
|
+
return continueProgram(host, entry, program, source, ctx, finalize, wrapResponse, { kind: "derive", next: i + 1, policy: true }, result, undefined);
|
|
357
|
+
}
|
|
358
|
+
if (isEarly(result))
|
|
359
|
+
return finishEarly(host, entry, ctx, result, finalize, wrapResponse);
|
|
360
|
+
Object.assign(ctx, result);
|
|
287
361
|
}
|
|
288
|
-
for (
|
|
289
|
-
const result =
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
362
|
+
for (let i = beforeStart; i < program.beforeHandle.length; i++) {
|
|
363
|
+
const result = program.beforeHandle[i](ctx);
|
|
364
|
+
if (result instanceof Promise) {
|
|
365
|
+
return continueProgram(host, entry, program, source, ctx, finalize, wrapResponse, { kind: "before", next: i + 1, policy: true }, result, undefined);
|
|
366
|
+
}
|
|
367
|
+
if (result !== undefined)
|
|
368
|
+
return finishEarly(host, entry, ctx, result, finalize, wrapResponse);
|
|
293
369
|
}
|
|
294
370
|
// The policy hooks have passed, so the idempotency gate may buffer the body now. Not awaited:
|
|
295
371
|
// the gate reports its own failures, and one the resumed program let escape must skip this catch.
|
|
@@ -297,23 +373,23 @@ async function runAuthBeforeValidation(host, entry, program, source, ctx, finali
|
|
|
297
373
|
return runIdempotencyGate(host, entry, ctx, finalize, wrapResponse, (e, p) => runAuthBeforeValidation(host, e, p, source, ctx, finalize, wrapResponse, true));
|
|
298
374
|
}
|
|
299
375
|
}
|
|
300
|
-
for (
|
|
376
|
+
for (let i = validationStart; i < program.validationStages.length; i++) {
|
|
377
|
+
const stage = program.validationStages[i];
|
|
301
378
|
const result = stage.kind === "body"
|
|
302
|
-
?
|
|
379
|
+
? host.readProgramBody(entry, source, ctx)
|
|
303
380
|
: host.validateProgramStage(entry, stage, source, ctx);
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
for (const after of program.afterHandle) {
|
|
310
|
-
const transformed = after(result, ctx);
|
|
311
|
-
result = transformed instanceof Promise ? await transformed : transformed;
|
|
381
|
+
if (result instanceof Promise) {
|
|
382
|
+
return continueProgram(host, entry, program, source, ctx, finalize, wrapResponse, { kind: "validation", next: i + 1, policy: true }, result, undefined);
|
|
383
|
+
}
|
|
384
|
+
if (result !== undefined)
|
|
385
|
+
return wrapResponse(result);
|
|
312
386
|
}
|
|
313
|
-
|
|
387
|
+
// A pending outcome here already met the error boundary (continueProgram or the response
|
|
388
|
+
// contract), so wrapping it in another catch would only add a promise.
|
|
389
|
+
return runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, program.derives.length, program.beforeHandle.length, undefined);
|
|
314
390
|
}
|
|
315
391
|
catch (error) {
|
|
316
|
-
return
|
|
392
|
+
return host.handleProgramError(entry, error, ctx, finalize, wrapResponse);
|
|
317
393
|
}
|
|
318
394
|
}
|
|
319
395
|
/** Execute the general program. The first synchronous stage sequence stays synchronous. */
|
|
@@ -356,9 +432,9 @@ function runSync(host, entry, program, source, ctx, finalize, wrapResponse, vali
|
|
|
356
432
|
if (outcome !== undefined)
|
|
357
433
|
return wrapResponse(outcome);
|
|
358
434
|
}
|
|
359
|
-
return runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, 0, 0,
|
|
435
|
+
return runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, 0, 0, initial);
|
|
360
436
|
}
|
|
361
|
-
function runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, deriveIndex, beforeIndex,
|
|
437
|
+
function runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, deriveIndex, beforeIndex, initial) {
|
|
362
438
|
for (let i = deriveIndex; i < program.derives.length; i++) {
|
|
363
439
|
const outcome = program.derives[i](ctx);
|
|
364
440
|
if (outcome instanceof Promise) {
|
|
@@ -380,7 +456,9 @@ function runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse,
|
|
|
380
456
|
if (output instanceof Promise) {
|
|
381
457
|
return continueProgram(host, entry, program, source, ctx, finalize, wrapResponse, { kind: "handler" }, output, initial);
|
|
382
458
|
}
|
|
383
|
-
|
|
459
|
+
return runAfterSync(host, entry, program, source, ctx, finalize, wrapResponse, 0, output);
|
|
460
|
+
}
|
|
461
|
+
function runAfterSync(host, entry, program, source, ctx, finalize, wrapResponse, afterIndex, result) {
|
|
384
462
|
for (let i = afterIndex; i < program.afterHandle.length; i++) {
|
|
385
463
|
const outcome = program.afterHandle[i](result, ctx);
|
|
386
464
|
if (outcome instanceof Promise) {
|
|
@@ -413,58 +491,28 @@ async function continueProgram(host, entry, program, source, ctx, finalize, wrap
|
|
|
413
491
|
else {
|
|
414
492
|
result = settled;
|
|
415
493
|
}
|
|
416
|
-
|
|
494
|
+
const outcome = runAsyncStages(host, entry, program, source, ctx, finalize, wrapResponse, pendingPhase, result);
|
|
495
|
+
return outcome instanceof Promise ? await outcome : outcome;
|
|
417
496
|
}
|
|
418
497
|
catch (error) {
|
|
419
498
|
return await host.handleProgramError(entry, error, ctx, finalize, wrapResponse);
|
|
420
499
|
}
|
|
421
500
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const outcome = stage.kind === "body"
|
|
429
|
-
? await host.readProgramBody(entry, source, ctx)
|
|
430
|
-
: host.validateProgramStage(entry, stage, source, ctx);
|
|
431
|
-
const settled = outcome instanceof Promise ? await outcome : outcome;
|
|
432
|
-
if (settled !== undefined)
|
|
433
|
-
return wrapResponse(settled);
|
|
434
|
-
}
|
|
501
|
+
function runAsyncStages(host, entry, program, source, ctx, finalize, wrapResponse, pendingPhase, result) {
|
|
502
|
+
// After an actual async boundary, resume the same sync runner until the next pending stage.
|
|
503
|
+
// Sync hooks and finalization need no async function wrapper or additional microtask turn.
|
|
504
|
+
if (pendingPhase.kind === "validation") {
|
|
505
|
+
if (pendingPhase.policy) {
|
|
506
|
+
return runAuthBeforeValidation(host, entry, program, source, ctx, finalize, wrapResponse, true, 0, 0, pendingPhase.next);
|
|
435
507
|
}
|
|
436
|
-
|
|
437
|
-
if (pendingPhase.kind === "validation" || pendingPhase.kind === "derive") {
|
|
438
|
-
for (let i = deriveStart; i < program.derives.length; i++) {
|
|
439
|
-
const outcome = program.derives[i](ctx);
|
|
440
|
-
const settled = outcome instanceof Promise ? await outcome : outcome;
|
|
441
|
-
if (isEarly(settled))
|
|
442
|
-
return finishEarly(host, entry, ctx, settled, finalize, wrapResponse);
|
|
443
|
-
Object.assign(ctx, settled);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
const beforeStart = pendingPhase.kind === "before" ? pendingPhase.next : 0;
|
|
447
|
-
if (pendingPhase.kind === "validation" ||
|
|
448
|
-
pendingPhase.kind === "derive" ||
|
|
449
|
-
pendingPhase.kind === "before") {
|
|
450
|
-
for (let i = beforeStart; i < program.beforeHandle.length; i++) {
|
|
451
|
-
const outcome = program.beforeHandle[i](ctx);
|
|
452
|
-
const settled = outcome instanceof Promise ? await outcome : outcome;
|
|
453
|
-
if (settled !== undefined)
|
|
454
|
-
return finishEarly(host, entry, ctx, settled, finalize, wrapResponse);
|
|
455
|
-
}
|
|
456
|
-
const output = program.handler(ctx);
|
|
457
|
-
result = output instanceof Promise ? await output : output;
|
|
458
|
-
}
|
|
459
|
-
const afterStart = pendingPhase.kind === "after" ? pendingPhase.next : 0;
|
|
460
|
-
for (let i = afterStart; i < program.afterHandle.length; i++) {
|
|
461
|
-
const outcome = program.afterHandle[i](result, ctx);
|
|
462
|
-
result = outcome instanceof Promise ? await outcome : outcome;
|
|
463
|
-
}
|
|
464
|
-
return await host.finishProgramResult(entry, ctx, result, finalize, wrapResponse);
|
|
508
|
+
return runSync(host, entry, program, source, ctx, finalize, wrapResponse, pendingPhase.next, result);
|
|
465
509
|
}
|
|
466
|
-
|
|
467
|
-
|
|
510
|
+
if (pendingPhase.kind === "derive" || pendingPhase.kind === "before") {
|
|
511
|
+
if (pendingPhase.policy) {
|
|
512
|
+
return runAuthBeforeValidation(host, entry, program, source, ctx, finalize, wrapResponse, false, pendingPhase.kind === "derive" ? pendingPhase.next : program.derives.length, pendingPhase.kind === "before" ? pendingPhase.next : 0);
|
|
513
|
+
}
|
|
514
|
+
return runHooksSync(host, entry, program, source, ctx, finalize, wrapResponse, pendingPhase.kind === "derive" ? pendingPhase.next : program.derives.length, pendingPhase.kind === "before" ? pendingPhase.next : 0, result);
|
|
468
515
|
}
|
|
516
|
+
return runAfterSync(host, entry, program, source, ctx, finalize, wrapResponse, pendingPhase.kind === "after" ? pendingPhase.next : 0, result);
|
|
469
517
|
}
|
|
470
518
|
//# sourceMappingURL=route-program.js.map
|