@nifrajs/core 5.9.0 → 5.11.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/edge-kit.d.ts +2 -1
  3. package/dist/edge-kit.d.ts.map +1 -1
  4. package/dist/edge-kit.js +2 -1
  5. package/dist/edge-kit.js.map +1 -1
  6. package/dist/guard-deny.d.ts +38 -0
  7. package/dist/guard-deny.d.ts.map +1 -0
  8. package/dist/guard-deny.js +43 -0
  9. package/dist/guard-deny.js.map +1 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/router/path-codec.d.ts +22 -0
  15. package/dist/router/path-codec.d.ts.map +1 -0
  16. package/dist/router/path-codec.js +87 -0
  17. package/dist/router/path-codec.js.map +1 -0
  18. package/dist/router/pattern.d.ts +21 -1
  19. package/dist/router/pattern.d.ts.map +1 -1
  20. package/dist/router/pattern.js +117 -0
  21. package/dist/router/pattern.js.map +1 -1
  22. package/dist/router/same-origin-path.d.ts +22 -0
  23. package/dist/router/same-origin-path.d.ts.map +1 -0
  24. package/dist/router/same-origin-path.js +37 -0
  25. package/dist/router/same-origin-path.js.map +1 -0
  26. package/dist/server/core-copies.js +1 -1
  27. package/dist/server/core-copies.js.map +1 -1
  28. package/dist/server/http.d.ts +1 -18
  29. package/dist/server/http.d.ts.map +1 -1
  30. package/dist/server/http.js +1 -33
  31. package/dist/server/http.js.map +1 -1
  32. package/dist/server/idle-timeout.d.ts +1 -1
  33. package/dist/server/idle-timeout.d.ts.map +1 -1
  34. package/dist/server/idle-timeout.js.map +1 -1
  35. package/dist/server/json-response.d.ts +14 -0
  36. package/dist/server/json-response.d.ts.map +1 -1
  37. package/dist/server/json-response.js +205 -0
  38. package/dist/server/json-response.js.map +1 -1
  39. package/dist/single-copy-register.js +5 -3
  40. package/dist/single-copy-register.js.map +1 -1
  41. package/dist/single-copy.d.ts +1 -1
  42. package/dist/single-copy.d.ts.map +1 -1
  43. package/dist/single-copy.js +49 -2
  44. package/dist/single-copy.js.map +1 -1
  45. package/package.json +6 -1
  46. package/src/edge-kit.ts +2 -1
  47. package/src/guard-deny.ts +61 -0
  48. package/src/index.ts +1 -1
  49. package/src/router/path-codec.ts +93 -0
  50. package/src/router/pattern.ts +127 -0
  51. package/src/router/same-origin-path.ts +36 -0
  52. package/src/server/core-copies.ts +1 -1
  53. package/src/server/http.ts +1 -33
  54. package/src/server/idle-timeout.ts +2 -4
  55. package/src/server/json-response.ts +209 -0
  56. package/src/single-copy-register.ts +5 -3
  57. package/src/single-copy.ts +51 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @nifrajs/core
2
2
 
3
+ ## 5.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d76f9d7: The three auth packages' guards deny a missing session through one owner: `@nifrajs/core/guard-deny` now holds `UnauthenticatedResponse`, the default `401` it builds (`unauthenticatedResult`), and the fail-loud check `assertUnauthenticated`, which refuses a denial that both redirects and answers, and a status outside 400-599. A new argument carries the package name, so every error keeps its prefix (`[nifra/auth]`, `[nifra/authjs]`, `[nifra/better-auth]`). Each package re-exports `UnauthenticatedResponse` and keeps its own guard options and its redirect rejection; no behavior and no message changed. The new subpath imports only the status lane, so it costs nothing beyond the grammar itself.
8
+
9
+ ### Patch Changes
10
+
11
+ - 9a0f0a0: `withIdleTimeout(c, seconds, work)` accepts the context of any route, including one that declares a `body`, `query` or `headers` schema.
12
+ - abf5a0b: Resolve the single-copy declaration from the app root when Bun runs a filtered workspace script.
13
+
14
+ ## 5.10.0
15
+
16
+ ### Minor Changes
17
+
18
+ - a6af4c9: A path segment has one spelling in every place a framework writes one. `@nifrajs/core/pattern` exports `encodePathSegment(value)`, `decodePathSegment(raw)`, `browserPathSegment(value)` and `fillRoutePath(pattern, params)`. `encodePathSegment` leaves `A-Za-z0-9 - . _ ~ ! $ & ' ( ) * + , : = @` as written and percent-encodes everything else in upper-case hex, so `;`, `[`, `]` and `|` are escaped (a proxy that reads `;` as a path parameter cannot change the path). A value no segment can carry (`.`, `..`, a lone surrogate) throws `RangeError`. `fillRoutePath` reports a value the router would read back as different params, such as `name` = `a.b` in `:name.:ext`, as invalid.
19
+
20
+ `getStaticPaths` output, the prerender report and written files, `enumerateStaticRoutes`, the typed client's path params and the contract fuzzer's request paths all use it. A `getStaticPaths` entry that leaves out a param or holds one no path can carry is skipped, and the prerender report names the param. Files in `public/` are served under the spelling a page links and the one a browser sends for the same name.
21
+ - 1faf86c: `href({ to, params, search, hash })` builds an in-app URL from a route pattern and returns an `Href`; `rawHref(path)` returns one for a same-origin path built elsewhere (a CMS link, `/llms.txt`). `to` is a key of the generated `RouteTable`, so a misspelt route, a missing, misspelt or extra param, and a `search` that breaks the route's schema are compile errors. A route without a `searchSchema` takes any `search`. Each param is encoded as one path segment, so a value such as `a/b` or `//evil.com` cannot change where the URL goes; a param that is missing, empty, `.`, `..` or an unpaired surrogate throws a `TypeError` naming it and the pattern. `rawHref` throws a `TypeError` unless `isSameOriginPath` accepts the path. Both are exported by `@nifrajs/web` and by the `/router` entry of every adapter.
22
+
23
+ `navigate` takes an `Href` or a history delta. A string, a template literal and the `{ to, search }` object form are compile errors, and a value forged past the types is still held to the same-origin check the browser navigate makes. `<Navigate to>` and the `useSearchParams` setter in `@nifrajs/web-react` pass their path through `rawHref`, so an off-origin `to` throws instead of doing nothing. `isSameOriginPath` is exported from `@nifrajs/core/pattern` as well as `@nifrajs/core/server`.
24
+
25
+ Upgrade: `navigate("/users/7")` becomes `navigate(href({ to: "/users/:id", params: { id: "7" } }))`, `navigate({ to, search, replace: true })` becomes `navigate(href({ to, search }), { replace: true })`, and a path built elsewhere is `navigate(rawHref(path))`. `resolveNavigate`, `NavigateTargetInput` and `NavigateSearchOf` are removed from `@nifrajs/web`.
26
+
27
+ ### Patch Changes
28
+
29
+ - 7e292dd: Reject adjacent mixed-route parameter values that the router would split differently, including percent-encoded values that would become malformed captures.
30
+
31
+ Make internal-link diagnostics account for stripped backend mounts, ignore commented-out and script-string anchors in Vue/Svelte components, and honor template-comment suppressions. Detect navigation imports from browser-safe router and client subpaths when checking route-table coverage.
32
+
3
33
  ## 5.9.0
4
34
 
5
35
  ### Minor Changes
@@ -9,6 +9,7 @@
9
9
  *
10
10
  * - {@link readBodyFramed} read + cap + proto-guard + content-type framing (JSON / urlencoded / 415)
11
11
  * - {@link capBodyBytes} the same byte cap on a handler's own reads of the raw request
12
+ * - {@link boundedJsonText} preflight JSON output against an exact UTF-8 byte budget
12
13
  * - {@link renderResult} render a {@link ResponseResult} (e.g. a 413 / 415 rejection) to a `Response`
13
14
  * - {@link toResponse} render any handler result, a handler's own `Response` included
14
15
  * - {@link plainError} the structured rejection envelope the lane returns
@@ -23,7 +24,7 @@ export { type ErrorLogDetail, emitRequestErrorLog } from "./server/bare-error-la
23
24
  export { assertByteLimit, capBodyBytes } from "./server/body.js";
24
25
  export { type FormOrigins, readBodyFramed } from "./server/body-lane.js";
25
26
  export { plainError } from "./server/http.js";
26
- export { jsonResponse } from "./server/json-response.js";
27
+ export { boundedJsonText, JsonByteLimitError, jsonResponse } from "./server/json-response.js";
27
28
  export { answerNotFound, type NotFoundHandler, type NotFoundInput, notFoundInput, } from "./server/not-found-answer.js";
28
29
  export type { ProtoPoisoning } from "./server/proto-guard.js";
29
30
  export { type QueryValue, queryObjectOf, searchOf } from "./server/query.js";
@@ -1 +1 @@
1
- {"version":3,"file":"edge-kit.d.ts","sourceRoot":"","sources":["../src/edge-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,KAAK,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,8BAA8B,CAAA;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAC9D,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"edge-kit.d.ts","sourceRoot":"","sources":["../src/edge-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,cAAc,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,KAAK,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7F,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,8BAA8B,CAAA;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAC9D,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA"}
package/dist/edge-kit.js CHANGED
@@ -9,6 +9,7 @@
9
9
  *
10
10
  * - {@link readBodyFramed} read + cap + proto-guard + content-type framing (JSON / urlencoded / 415)
11
11
  * - {@link capBodyBytes} the same byte cap on a handler's own reads of the raw request
12
+ * - {@link boundedJsonText} preflight JSON output against an exact UTF-8 byte budget
12
13
  * - {@link renderResult} render a {@link ResponseResult} (e.g. a 413 / 415 rejection) to a `Response`
13
14
  * - {@link toResponse} render any handler result, a handler's own `Response` included
14
15
  * - {@link plainError} the structured rejection envelope the lane returns
@@ -23,7 +24,7 @@ export { emitRequestErrorLog } from "./server/bare-error-lane.js";
23
24
  export { assertByteLimit, capBodyBytes } from "./server/body.js";
24
25
  export { readBodyFramed } from "./server/body-lane.js";
25
26
  export { plainError } from "./server/http.js";
26
- export { jsonResponse } from "./server/json-response.js";
27
+ export { boundedJsonText, JsonByteLimitError, jsonResponse } from "./server/json-response.js";
27
28
  export { answerNotFound, notFoundInput, } from "./server/not-found-answer.js";
28
29
  export { queryObjectOf, searchOf } from "./server/query.js";
29
30
  export { renderResult, toResponse } from "./server/respond.js";
@@ -1 +1 @@
1
- {"version":3,"file":"edge-kit.js","sourceRoot":"","sources":["../src/edge-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAuB,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAoB,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EACL,cAAc,EAGd,aAAa,GACd,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAmB,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"edge-kit.js","sourceRoot":"","sources":["../src/edge-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAuB,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAoB,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7F,OAAO,EACL,cAAc,EAGd,aAAa,GACd,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAmB,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The denial grammar the three auth packages' route guards share: what a guard rejects a missing
3
+ * session with. `@nifrajs/auth`, `@nifrajs/authjs` and `@nifrajs/better-auth` each keep their own
4
+ * options shape and their own redirect rejection; this subpath owns the `unauthenticated` response
5
+ * type, its construction, and the two fail-loud dev-config checks, so the three cannot drift: a
6
+ * fix made here holds for every guard family at once.
7
+ *
8
+ * The module imports only the status lane, so an app whose guards use it pays nothing besides the
9
+ * grammar itself.
10
+ */
11
+ import { type ResponseResult } from "./server/runtime-core.js";
12
+ /**
13
+ * The response a guard denies a missing session with, in place of the default `401` JSON. Every
14
+ * nifra auth package's guard options named `unauthenticated` takes this shape.
15
+ */
16
+ export interface UnauthenticatedResponse {
17
+ /** An error status, 400-599. Default `401`. */
18
+ readonly status?: number;
19
+ /** The body; present but `undefined` sends none. Default `{ ok: false, error: "unauthorized" }`. */
20
+ readonly body?: unknown;
21
+ /** Response headers, such as a `www-authenticate` challenge. */
22
+ readonly headers?: Readonly<Record<string, string>>;
23
+ }
24
+ /**
25
+ * A dev-authored denial that is not an error status, or that competes with a redirect, fails loud.
26
+ * A mutation-taking guard must say one thing, and `unauthenticated.status` must stay an HTTP error
27
+ * status. `owner` names the package in the message: `[nifra/<owner>]`.
28
+ */
29
+ export declare function assertUnauthenticated(options: {
30
+ readonly redirectTo?: string;
31
+ readonly unauthenticated?: UnauthenticatedResponse;
32
+ }, owner: string): void;
33
+ /**
34
+ * The response one guard rejection carries: what the options declared, or the default `401` JSON
35
+ * (`{ ok: false, error: "unauthorized" }`). An explicit `body` of `undefined` sends no body.
36
+ */
37
+ export declare function unauthenticatedResult(custom: UnauthenticatedResponse | undefined): ResponseResult;
38
+ //# sourceMappingURL=guard-deny.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-deny.d.ts","sourceRoot":"","sources":["../src/guard-deny.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,cAAc,EAAU,MAAM,0BAA0B,CAAA;AAKtE;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,oGAAoG;IACpG,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,uBAAuB,CAAA;CAAE,EAC7F,KAAK,EAAE,MAAM,GACZ,IAAI,CAYN;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAAG,cAAc,CAMjG"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The denial grammar the three auth packages' route guards share: what a guard rejects a missing
3
+ * session with. `@nifrajs/auth`, `@nifrajs/authjs` and `@nifrajs/better-auth` each keep their own
4
+ * options shape and their own redirect rejection; this subpath owns the `unauthenticated` response
5
+ * type, its construction, and the two fail-loud dev-config checks, so the three cannot drift: a
6
+ * fix made here holds for every guard family at once.
7
+ *
8
+ * The module imports only the status lane, so an app whose guards use it pays nothing besides the
9
+ * grammar itself.
10
+ */
11
+ import { status } from "./server/runtime-core.js";
12
+ /** The body a guard sends when the app did not declare its own. */
13
+ const UNAUTHORIZED = { ok: false, error: "unauthorized" };
14
+ /**
15
+ * A dev-authored denial that is not an error status, or that competes with a redirect, fails loud.
16
+ * A mutation-taking guard must say one thing, and `unauthenticated.status` must stay an HTTP error
17
+ * status. `owner` names the package in the message: `[nifra/<owner>]`.
18
+ */
19
+ export function assertUnauthenticated(options, owner) {
20
+ const custom = options.unauthenticated;
21
+ if (custom === undefined)
22
+ return;
23
+ if (options.redirectTo !== undefined) {
24
+ throw new Error(`[nifra/${owner}] a guard takes redirectTo or unauthenticated, not both`);
25
+ }
26
+ const code = custom.status;
27
+ if (code !== undefined && (!Number.isInteger(code) || code < 400 || code > 599)) {
28
+ throw new RangeError(`[nifra/${owner}] guard unauthenticated.status must be an integer 400-599 (got ${String(code)})`);
29
+ }
30
+ }
31
+ /**
32
+ * The response one guard rejection carries: what the options declared, or the default `401` JSON
33
+ * (`{ ok: false, error: "unauthorized" }`). An explicit `body` of `undefined` sends no body.
34
+ */
35
+ export function unauthenticatedResult(custom) {
36
+ if (custom === undefined)
37
+ return status(401, UNAUTHORIZED);
38
+ const body = "body" in custom ? custom.body : UNAUTHORIZED;
39
+ return custom.headers === undefined
40
+ ? status(custom.status ?? 401, body)
41
+ : status(custom.status ?? 401, body, { headers: custom.headers });
42
+ }
43
+ //# sourceMappingURL=guard-deny.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard-deny.js","sourceRoot":"","sources":["../src/guard-deny.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAuB,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAEtE,mEAAmE;AACnE,MAAM,YAAY,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAW,CAAA;AAelE;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAA6F,EAC7F,KAAa;IAEb,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAA;IACtC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAM;IAChC,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,yDAAyD,CAAC,CAAA;IAC3F,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAA;IAC1B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,UAAU,CAClB,UAAU,KAAK,kEAAkE,MAAM,CAAC,IAAI,CAAC,GAAG,CACjG,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAA2C;IAC/E,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAC1D,MAAM,IAAI,GAAG,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAA;IAC1D,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS;QACjC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,CAAC;QACpC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;AACrE,CAAC"}
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.9.0";
18
+ export declare const VERSION: "5.11.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";
@@ -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,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 const VERSION = "5.9.0";
18
+ export const VERSION = "5.11.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";
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;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,EACL,gBAAgB,EAChB,UAAU,EAEV,UAAU,EACV,MAAM,GACP,MAAM,kBAAkB,CAAA;AACzB,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,EACL,kBAAkB,EAElB,YAAY,GACb,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAiB,CAAA;AAIxC,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,EACL,gBAAgB,EAChB,UAAU,EAEV,UAAU,EACV,MAAM,GACP,MAAM,kBAAkB,CAAA;AACzB,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,EACL,kBAAkB,EAElB,YAAY,GACb,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `value` as one path segment. Left as written: letters, digits, the at sign and `- . _ ~ ! $ & ' ( ) * + , : =`.
3
+ * Everything else is percent-encoded, UTF-8 and upper-case hex, including `; [ ] | / ? # % \`.
4
+ *
5
+ * Throws a `RangeError` for a value that no segment can carry: exactly `.` or `..` (a URL parser reads
6
+ * `%2E` and `%2E%2E` as dot segments too) and a lone surrogate (substituting U+FFFD would map distinct
7
+ * values to one URL). The empty string is returned as is; a caller that cannot use it checks for it.
8
+ */
9
+ export declare function encodePathSegment(value: string): string;
10
+ /**
11
+ * `value` as a browser spells it in a request URL: {@link encodePathSegment} with `; [ ] |` left as
12
+ * written. Used for one thing, registering a public file under the spelling its page links request;
13
+ * it differs from the canonical form on those four characters only.
14
+ */
15
+ export declare function browserPathSegment(value: string): string;
16
+ /**
17
+ * `raw` with its percent-escapes decoded, or `undefined` when one is malformed. The inverse of
18
+ * {@link encodePathSegment} and of {@link browserPathSegment}; a segment in any other spelling decodes
19
+ * too. What a malformed escape means is the caller's policy.
20
+ */
21
+ export declare function decodePathSegment(raw: string): string | undefined;
22
+ //# sourceMappingURL=path-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-codec.d.ts","sourceRoot":"","sources":["../../src/router/path-codec.ts"],"names":[],"mappings":"AA4DA;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMjE"}
@@ -0,0 +1,87 @@
1
+ // One URL path segment, encoded and decoded. Every place that spells a value into a path calls this
2
+ // module, so a link, a prerendered file, a client request and a public asset agree on one spelling.
3
+ const HEX = "0123456789ABCDEF";
4
+ const UNRESERVED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
5
+ function rawTable(chars) {
6
+ const table = new Uint8Array(128);
7
+ for (let i = 0; i < chars.length; i++)
8
+ table[chars.charCodeAt(i)] = 1;
9
+ return table;
10
+ }
11
+ // RFC 3986 `pchar` minus `;`: the unreserved set, the sub-delimiters, `:` and `@`. `;` delimits path
12
+ // parameters (RFC 3986 section 3.3) and servlet containers strip them; `[`, `]` and `|` are not valid in
13
+ // a path at all and Tomcat rejects them unencoded by default.
14
+ const CANONICAL = /* @__PURE__ */ rawTable(`${UNRESERVED}!$&'()*+,:=@`);
15
+ // What a browser leaves as written in a path: the canonical set plus `;`, `[`, `]` and `|`.
16
+ const BROWSER = /* @__PURE__ */ rawTable(`${UNRESERVED}!$&'()*+,:=@;[]|`);
17
+ function encodeNonAscii(run) {
18
+ try {
19
+ return encodeURIComponent(run);
20
+ }
21
+ catch {
22
+ throw new RangeError("[nifra/core] a path segment cannot hold a lone surrogate");
23
+ }
24
+ }
25
+ function encodeWith(raw, value) {
26
+ if (value === "." || value === "..") {
27
+ throw new RangeError(`[nifra/core] a path segment cannot be ${JSON.stringify(value)}: every spelling of it is a dot segment to a URL parser`);
28
+ }
29
+ const length = value.length;
30
+ let out = "";
31
+ let start = 0;
32
+ let i = 0;
33
+ while (i < length) {
34
+ const code = value.charCodeAt(i);
35
+ if (code < 128 && raw[code] === 1) {
36
+ i++;
37
+ continue;
38
+ }
39
+ out += value.slice(start, i);
40
+ if (code < 128) {
41
+ out += `%${HEX[code >> 4]}${HEX[code & 15]}`;
42
+ i++;
43
+ }
44
+ else {
45
+ let end = i + 1;
46
+ while (end < length && value.charCodeAt(end) >= 128)
47
+ end++;
48
+ out += encodeNonAscii(value.slice(i, end));
49
+ i = end;
50
+ }
51
+ start = i;
52
+ }
53
+ return start === 0 ? value : out + value.slice(start);
54
+ }
55
+ /**
56
+ * `value` as one path segment. Left as written: letters, digits, the at sign and `- . _ ~ ! $ & ' ( ) * + , : =`.
57
+ * Everything else is percent-encoded, UTF-8 and upper-case hex, including `; [ ] | / ? # % \`.
58
+ *
59
+ * Throws a `RangeError` for a value that no segment can carry: exactly `.` or `..` (a URL parser reads
60
+ * `%2E` and `%2E%2E` as dot segments too) and a lone surrogate (substituting U+FFFD would map distinct
61
+ * values to one URL). The empty string is returned as is; a caller that cannot use it checks for it.
62
+ */
63
+ export function encodePathSegment(value) {
64
+ return encodeWith(CANONICAL, value);
65
+ }
66
+ /**
67
+ * `value` as a browser spells it in a request URL: {@link encodePathSegment} with `; [ ] |` left as
68
+ * written. Used for one thing, registering a public file under the spelling its page links request;
69
+ * it differs from the canonical form on those four characters only.
70
+ */
71
+ export function browserPathSegment(value) {
72
+ return encodeWith(BROWSER, value);
73
+ }
74
+ /**
75
+ * `raw` with its percent-escapes decoded, or `undefined` when one is malformed. The inverse of
76
+ * {@link encodePathSegment} and of {@link browserPathSegment}; a segment in any other spelling decodes
77
+ * too. What a malformed escape means is the caller's policy.
78
+ */
79
+ export function decodePathSegment(raw) {
80
+ try {
81
+ return decodeURIComponent(raw);
82
+ }
83
+ catch {
84
+ return undefined;
85
+ }
86
+ }
87
+ //# sourceMappingURL=path-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-codec.js","sourceRoot":"","sources":["../../src/router/path-codec.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,oGAAoG;AAEpG,MAAM,GAAG,GAAG,kBAAkB,CAAA;AAE9B,MAAM,UAAU,GAAG,oEAAoE,CAAA;AAEvF,SAAS,QAAQ,CAAC,KAAa;IAC7B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACrE,OAAO,KAAK,CAAA;AACd,CAAC;AAED,qGAAqG;AACrG,yGAAyG;AACzG,8DAA8D;AAC9D,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,CAAC,GAAG,UAAU,cAAc,CAAC,CAAA;AAEvE,4FAA4F;AAC5F,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,GAAG,UAAU,kBAAkB,CAAC,CAAA;AAEzE,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAA;IAClF,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAe,EAAE,KAAa;IAChD,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAClB,yCAAyC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yDAAyD,CACxH,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;IAC3B,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,CAAC,EAAE,CAAA;YACH,SAAQ;QACV,CAAC;QACD,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QAC5B,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;YACf,GAAG,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE,CAAA;YAC5C,CAAC,EAAE,CAAA;QACL,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YACf,OAAO,GAAG,GAAG,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG;gBAAE,GAAG,EAAE,CAAA;YAC1D,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;YAC1C,CAAC,GAAG,GAAG,CAAA;QACT,CAAC;QACD,KAAK,GAAG,CAAC,CAAA;IACX,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACvD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC"}
@@ -1,3 +1,5 @@
1
+ export { browserPathSegment, decodePathSegment, encodePathSegment } from "./path-codec.js";
2
+ export { isSameOriginPath } from "./same-origin-path.js";
1
3
  declare const COMPILED_ROUTE_PATTERN: unique symbol;
2
4
  export type RoutePatternSegment = {
3
5
  readonly kind: "static";
@@ -185,7 +187,25 @@ export declare function sortRoutesBySpecificity<T extends {
185
187
  /** Decode router captures under one rule. Plain values take the zero-allocation path; malformed
186
188
  * escapes return `null`, allowing HTTP to emit 400 while client navigation declines the match. */
187
189
  export declare function decodeRouteParams(raw: Record<string, string>): Record<string, string> | null;
190
+ export type FilledRoutePath = {
191
+ readonly ok: true;
192
+ readonly path: string;
193
+ } | {
194
+ readonly ok: false;
195
+ /** Params the pattern names that `params` leaves out or holds as the empty string. */
196
+ readonly missing: readonly string[];
197
+ /** Params whose value cannot be carried or would be split differently by this pattern. */
198
+ readonly invalid: readonly string[];
199
+ };
200
+ /**
201
+ * The path `pattern` names for `params`, every value spelled by {@link encodePathSegment}. A wildcard
202
+ * value is split on `/` and each part encoded, empty parts dropped; a `.` or `..` part is invalid, as
203
+ * a whole-segment value is. Nothing is thrown for a bad value: the caller decides what a missing or
204
+ * invalid param means. A param inside a mixed segment is invalid when its value holds the literal that ends it (`name` = `a.b` in
205
+ * `:name.:ext`), or when it touches the next param and encodes to more than one character, because the
206
+ * router would split it differently. A param's constraint (`:id{[0-9]+}`) is not checked here.
207
+ */
208
+ export declare function fillRoutePath(pattern: string | CompiledRoutePattern, params: Readonly<Record<string, string | undefined>>): FilledRoutePath;
188
209
  /** Match one compiled pattern and return decoded captures. The caller decides cross-pattern order. */
189
210
  export declare function matchRoutePattern(compiled: CompiledRoutePattern, pathname: string): RoutePatternMatch;
190
- export {};
191
211
  //# sourceMappingURL=pattern.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pattern.d.ts","sourceRoot":"","sources":["../../src/router/pattern.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pattern.d.ts","sourceRoot":"","sources":["../../src/router/pattern.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,7 @@
1
1
  import { RouteConfigError } from "../errors.js";
2
+ import { encodePathSegment } from "./path-codec.js";
3
+ export { browserPathSegment, decodePathSegment, encodePathSegment } from "./path-codec.js";
4
+ export { isSameOriginPath } from "./same-origin-path.js";
2
5
  const PARAM_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
3
6
  const RESERVED_PARAM_NAMES = new Set(["__proto__", "constructor", "prototype"]);
4
7
  const COMPILED_ROUTE_PATTERN = Symbol("nifra.compiled-route-pattern");
@@ -517,6 +520,120 @@ export function decodeRouteParams(raw) {
517
520
  }
518
521
  return out ?? raw;
519
522
  }
523
+ /**
524
+ * The path `pattern` names for `params`, every value spelled by {@link encodePathSegment}. A wildcard
525
+ * value is split on `/` and each part encoded, empty parts dropped; a `.` or `..` part is invalid, as
526
+ * a whole-segment value is. Nothing is thrown for a bad value: the caller decides what a missing or
527
+ * invalid param means. A param inside a mixed segment is invalid when its value holds the literal that ends it (`name` = `a.b` in
528
+ * `:name.:ext`), or when it touches the next param and encodes to more than one character, because the
529
+ * router would split it differently. A param's constraint (`:id{[0-9]+}`) is not checked here.
530
+ */
531
+ export function fillRoutePath(pattern, params) {
532
+ const compiled = typeof pattern === "string" ? compileRoutePattern(pattern) : pattern;
533
+ // Built as one string, with the two problem lists made only when a param is bad: a path that fills
534
+ // allocates nothing else.
535
+ let path = "";
536
+ let missing;
537
+ let invalid;
538
+ const segments = compiled.segments;
539
+ for (let s = 0; s < segments.length; s++) {
540
+ const segment = segments[s];
541
+ if (segment.kind === "static") {
542
+ path += `/${segment.value}`;
543
+ }
544
+ else if (segment.kind === "param") {
545
+ const value = fillValue(params, segment.name);
546
+ if (value === undefined) {
547
+ missing = noted(missing, segment.name);
548
+ path += "/";
549
+ continue;
550
+ }
551
+ const encoded = spell(value);
552
+ if (encoded === undefined)
553
+ invalid = noted(invalid, segment.name);
554
+ path += `/${encoded ?? ""}`;
555
+ }
556
+ else if (segment.kind === "wildcard") {
557
+ const value = fillValue(params, segment.name);
558
+ let joined = "";
559
+ let any = false;
560
+ if (value !== undefined) {
561
+ for (const piece of value.split("/")) {
562
+ if (piece === "")
563
+ continue;
564
+ const encoded = spell(piece);
565
+ if (encoded === undefined)
566
+ invalid = noted(invalid, segment.name);
567
+ joined += any ? `/${encoded ?? ""}` : (encoded ?? "");
568
+ any = true;
569
+ }
570
+ }
571
+ if (!any)
572
+ missing = noted(missing, segment.name);
573
+ path += `/${joined}`;
574
+ }
575
+ else {
576
+ let text = "";
577
+ const shape = segment.parts;
578
+ for (let i = 0; i < shape.length; i++) {
579
+ const part = shape[i];
580
+ if (part.t === "lit") {
581
+ text += part.v;
582
+ continue;
583
+ }
584
+ const value = fillValue(params, part.name);
585
+ if (value === undefined) {
586
+ missing = noted(missing, part.name);
587
+ continue;
588
+ }
589
+ const encoded = spell(value);
590
+ if (encoded === undefined) {
591
+ invalid = noted(invalid, part.name);
592
+ continue;
593
+ }
594
+ // matchMixedSegment ends a parameter at the first occurrence of the literal after it, one
595
+ // character in or later. A value holding that literal earlier would come back as different
596
+ // params. A literal in the last place is the segment's tail, which is anchored to its end.
597
+ const next = shape[i + 1];
598
+ // With no separating literal the matcher gives this parameter exactly one raw character.
599
+ // Splitting a percent-escape here would also make the captured parameters malformed.
600
+ if (next?.t === "param" && encoded.length !== 1)
601
+ invalid = noted(invalid, part.name);
602
+ else if (next?.t === "lit" && shape[i + 2] !== undefined) {
603
+ if ((encoded + next.v).indexOf(next.v, 1) !== encoded.length)
604
+ invalid = noted(invalid, part.name);
605
+ }
606
+ text += encoded;
607
+ }
608
+ path += `/${text}`;
609
+ }
610
+ }
611
+ return missing !== undefined || invalid !== undefined
612
+ ? { ok: false, missing: missing ?? [], invalid: invalid ?? [] }
613
+ : { ok: true, path: path === "" ? "/" : path };
614
+ }
615
+ /** A param's value when it is a non-empty string the caller gave, not one inherited from the prototype. */
616
+ function fillValue(params, name) {
617
+ const value = Object.hasOwn(params, name) ? params[name] : undefined;
618
+ return typeof value === "string" && value !== "" ? value : undefined;
619
+ }
620
+ /** `value` spelled as one path segment, or undefined when no segment can carry it. */
621
+ function spell(value) {
622
+ try {
623
+ return encodePathSegment(value);
624
+ }
625
+ catch {
626
+ return undefined;
627
+ }
628
+ }
629
+ /** `list` with `name` in it once, made when there was none. */
630
+ function noted(list, name) {
631
+ if (list === undefined)
632
+ return [name];
633
+ if (!list.includes(name))
634
+ list.push(name);
635
+ return list;
636
+ }
520
637
  /** Match one compiled pattern and return decoded captures. The caller decides cross-pattern order. */
521
638
  export function matchRoutePattern(compiled, pathname) {
522
639
  const matcher = matcherOf(compiled);