@loozo/angular-router 0.0.5 → 0.0.7

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 CHANGED
@@ -294,7 +294,7 @@ The package root exports exactly `defineRoute`, `createUrl`, `stringParam`, `num
294
294
 
295
295
  ## Building URLs
296
296
 
297
- `createUrl` builds a root-relative URL from a declaration, synchronously and without running any parsers:
297
+ `createUrl` builds a root-relative URL from a declaration, synchronously and without running any parsers. It's typed `` `/${string}` ``, so it fits APIs that take only root-relative URLs, such as Launch's `redirect()`:
298
298
 
299
299
  `snippets/src/product-url.ts`
300
300
 
@@ -367,12 +367,12 @@ export function itemLinks() {
367
367
  route.link({ params: { teamId: 7, id: 8 } }); // this route
368
368
  route.link(".", { params: { teamId: 7, id: 8 } }); // same as above
369
369
  route.link("/teams/$teamId/items/$id", { params: { teamId: 7, id: 9 } }); // absolute
370
- route.link("../..", { params: { teamId: 7 } }); // relative
370
+ route.link("..", { params: { teamId: 7 } }); // parent route
371
371
  void route.navigate(report, { params: { reportId: 42 } }); // another route's destination
372
372
  }
373
373
  ```
374
374
 
375
- The first argument, when given, is a string literal selecting a route by its full authored path, never a concrete URL. Absolute selectors start with `/`. Relative selectors start with `.`, `./` or `..`; each `..` removes one segment of the path template, not one directory or parent. TypeScript only offers selectors that resolve to a known route, and the values are always typed for the selected route.
375
+ The first argument, when given, is a string literal selecting a route by its full authored path, never a concrete URL. Absolute selectors start with `/`. `"."` selects this route, and `".."` its parent route: the nearest route above it with a shorter path, or the root route for a top-level route. There are no other relative selectors. TypeScript only offers selectors that resolve to a known route, and the values are always typed for the selected route.
376
376
 
377
377
  Values are never carried over from the current URL. Pass every required param and search value explicitly, and pass `fragment` only when the target declares it. There is no extras argument; use `RouterLink` inputs such as `replaceUrl` or `state` for those.
378
378
 
@@ -529,7 +529,28 @@ Declarations look the same, but the builder never creates or edits them, and dir
529
529
 
530
530
  The generated routes work with Angular SSR and `provideClientHydration` without extra setup; there's no transfer cache or custom renderer. Parsing is synchronous and resolvers keep Angular's stability pending, so server-rendered HTML contains parsed values and resolved data.
531
531
 
532
- [`examples/angular-router/ssr-proof`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.5/examples/angular-router/ssr-proof/README.md) is a working SSR app with a search fallback, a resolver, a redirect and hydration.
532
+ [`examples/angular-router/ssr-proof`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.7/examples/angular-router/ssr-proof/README.md) is a working SSR app with a search fallback, a resolver, a redirect and hydration.
533
+
534
+ ## Unit tests and i18n extraction
535
+
536
+ Point Angular's unit-test and extract-i18n builders at the router's application target, the same way `ng new` points them at the official one:
537
+
538
+ ```json
539
+ "test": {
540
+ "builder": "@angular/build:unit-test",
541
+ "options": { "buildTarget": "app:build" }
542
+ },
543
+ "extract-i18n": {
544
+ "builder": "@angular/build:extract-i18n",
545
+ "options": { "buildTarget": "app:build" }
546
+ }
547
+ ```
548
+
549
+ Neither builder runs generation; both use the generated files already on disk. After you add, move or remove routes, run `ng build` first, or keep `ng serve` running. Otherwise `ng test` can't match the new routes, and `ng extract-i18n` silently leaves out the messages of pages the stale routes don't load. In CI, committed generated files and `ng build --configuration ci` cover this.
550
+
551
+ `ng test` warns that the `buildTarget` uses `@loozo/angular-router:application`, "which is not supported". The warning is expected: the unit-test builder reads the target's options, and Angular ignores the router's own ones.
552
+
553
+ The rest is the usual Angular setup. Give specs their own `tsconfig.spec.json` with `"types": ["vitest/globals"]`, and exclude `src/**/*.spec.ts` from the application tsconfig. For `i18n` attributes, add `@angular/localize/init` to the build target's `polyfills`.
533
554
 
534
555
  ## What gets generated
535
556
 
@@ -591,9 +612,9 @@ To go back to native file events, set `"poll": false` in the serve target or one
591
612
 
592
613
  ## Further reading
593
614
 
594
- - [`SPEC.md`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.5/packages/angular-router/SPEC.md): the full contract, including every edge case
595
- - [`examples/angular-router`](https://github.com/theo-matzavinos/loozo/tree/angular-router@0.0.5/examples/angular-router): a minimal app using the builders
596
- - [`examples/angular-router/ssr-proof`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.5/examples/angular-router/ssr-proof/README.md): SSR and hydration
615
+ - [`SPEC.md`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.7/packages/angular-router/SPEC.md): the full contract, including every edge case
616
+ - [`examples/angular-router`](https://github.com/theo-matzavinos/loozo/tree/angular-router@0.0.7/examples/angular-router): a minimal app using the builders
617
+ - [`examples/angular-router/ssr-proof`](https://github.com/theo-matzavinos/loozo/blob/angular-router@0.0.7/examples/angular-router/ssr-proof/README.md): SSR and hydration
597
618
 
598
619
  ## Developing this package
599
620
 
@@ -609,7 +630,7 @@ pnpm run test # root runtime, published-docs and schema tests
609
630
 
610
631
  `build` regenerates `schemas/application.json` from the installed `@angular/build`; `pnpm test` fails when the committed schema is stale.
611
632
 
612
- The browser tests use real Angular builds and Chromium (`/usr/bin/chromium`). Each takes a fresh absolute directory, which must not exist yet, for its evidence:
633
+ The browser tests use real Angular builds and Playwright's Chromium (`pnpm exec playwright install chromium`). Each takes a fresh absolute directory, which must not exist yet, for its evidence:
613
634
 
614
635
  ```sh
615
636
  pnpm run test:application /absolute/new-directory
@@ -617,6 +638,7 @@ pnpm run test:navigation /absolute/new-directory
617
638
  pnpm run test:lifecycle /absolute/new-directory
618
639
  pnpm run test:ssr /absolute/new-directory
619
640
  pnpm run test:filesystem /absolute/new-directory
641
+ pnpm run test:tooling /absolute/new-directory # ng test and ng extract-i18n, no browser
620
642
  node tests/packed.mjs /absolute/new-directory # packed-package consumer check
621
643
  ```
622
644
 
@@ -361,8 +361,8 @@ function createUrl(route, values) {
361
361
  if (!has(search, key) || value === void 0) continue;
362
362
  query.push(`${encode(key)}=${stringify(metadata.search[key], value, false)}`);
363
363
  }
364
- if (query.length > 0) url += `?${query.join("&")}`;
365
- if (has(options, "fragment")) url += `#${encode(options.fragment)}`;
364
+ if (query.length > 0) url = `${url}?${query.join("&")}`;
365
+ if (has(options, "fragment")) url = `${url}#${encode(options.fragment)}`;
366
366
  return url;
367
367
  }
368
368
  export { booleanParam, codecFallback, createUrl, defineRoute, enumParam, numberParam, routeMetadata, stringParam, withFallback };
@@ -1 +1 @@
1
- {"version":3,"file":"loozo-angular-router-_core.mjs","names":[],"sources":["../../_core/src/codecs.ts","../../_core/src/path.ts","../../_core/src/records.ts","../../_core/src/route.ts","../../_core/src/url.ts"],"sourcesContent":["/**\n * Converts one decoded path or search value to and from an application value.\n *\n * @remarks\n * Both methods are synchronous, and parsing should be pure and deterministic:\n * like Angular's matching callbacks, it runs once while matching and again for\n * the activated route. Neither method performs URL encoding. Codecs have no\n * Angular injection context, and their returned objects are not recursively frozen.\n * For a terminal `$name[]` path, this codec applies to each element separately.\n *\n * @typeParam Value - The logical value, never a promise of that value.\n *\n * @example\n * ```ts\n * const dateParam: ParamCodec<Date> = {\n * parse: (raw) => new Date(raw),\n * stringify: (value) => value.toISOString(),\n * };\n * ```\n */\nexport interface ParamCodec<Value> {\n /**\n * Parses one already percent-decoded value; do not decode it again.\n *\n * @param raw - A single logical string from Angular's URL inputs.\n * @returns The logical value, synchronously. Returning a promise or other\n * thenable is a programming error that fails the navigation with a TypeError.\n * @throws An application error for invalid input: an invalid path value makes\n * the route not match, and an invalid search value reads as absent or as its fallback.\n */\n parse(raw: string): Value;\n /**\n * Serializes one logical value without percent-encoding it.\n *\n * @param value - The application value to serialize.\n * @returns An unencoded string. Path output must not be empty, `.` or `..`.\n * @throws An application error when the value cannot be serialized.\n */\n stringify(value: Value): string;\n}\n\ndeclare const searchFallback: unique symbol;\n\n/**\n * A search-only codec whose key reads a fallback value when it is missing,\n * repeated or invalid, while URL creation may still omit it.\n */\nexport type FallbackCodec<Value> = ParamCodec<Value> & {\n readonly [searchFallback]: true;\n};\nexport type PathCodec = ParamCodec<any> & { readonly [searchFallback]?: never };\nexport type CodecValue<Codec> = Codec extends ParamCodec<infer Value> ? Value : never;\nexport type HasFallback<Codec> = Codec extends { readonly [searchFallback]: true } ? true : false;\n\n/** Type-only marker: a codec whose parse returns a promise fails where it is declared. */\nexport interface SynchronousParse {\n /** Never present: `parse` must return its value synchronously, not a Promise. */\n readonly \"ParamCodec.parse must return its value synchronously, not a Promise\": never;\n}\ntype ParseResult<Codec> = Codec extends { parse(raw: string): infer Result } ? Result : never;\nexport type SyncValue<Value> =\n Extract<Value, PromiseLike<unknown>> extends never ? unknown : SynchronousParse;\nexport type SyncCodecs<Codecs> = {\n [Key in keyof Codecs]: SyncValue<ParseResult<Codecs[Key]>>;\n};\n\nconst fallbacks = new WeakMap<object, { readonly value: unknown }>();\n\nexport function codecFallback(codec: object): { readonly value: unknown } | undefined {\n return fallbacks.get(codec);\n}\n\nexport function validateCodec(codec: unknown): asserts codec is ParamCodec<any> {\n if (\n codec === null ||\n (typeof codec !== \"object\" && typeof codec !== \"function\") ||\n typeof (codec as ParamCodec<unknown>).parse !== \"function\" ||\n typeof (codec as ParamCodec<unknown>).stringify !== \"function\"\n ) {\n throw new TypeError(\"Codec must have callable parse and stringify methods\");\n }\n}\n\n/**\n * Preserves strings verbatim, including empty strings and literal percent text.\n *\n * @remarks\n * Empty, dot and dotdot values are valid codec values but cannot be serialized\n * into path segments by URL creation. Search values may contain them.\n */\nexport const stringParam: ParamCodec<string> = {\n parse(raw) {\n return raw;\n },\n stringify(value) {\n if (typeof value !== \"string\") {\n throw new TypeError(\"Expected a string\");\n }\n\n return value;\n },\n};\n\n/**\n * Parses nonblank text with JavaScript `Number` and requires a finite result.\n *\n * @remarks\n * Whitespace around numbers, exponent notation and hexadecimal text are accepted.\n * Blank text, NaN and infinities throw. Stringification requires a finite number\n * and uses its JavaScript string representation (including `-0` becoming `\"0\"`).\n */\nexport const numberParam: ParamCodec<number> = {\n parse(raw) {\n const value = Number(raw);\n\n if (raw.trim() === \"\" || !Number.isFinite(value)) {\n throw new Error(\"Expected a finite number\");\n }\n\n return value;\n },\n stringify(value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(\"Expected a finite number\");\n }\n\n return String(value);\n },\n};\n\n/**\n * Parses only lowercase `\"true\"` and `\"false\"`, and emits those same strings.\n * Other representations and nonboolean values throw.\n */\nexport const booleanParam: ParamCodec<boolean> = {\n parse(raw) {\n if (raw === \"true\") {\n return true;\n }\n\n if (raw === \"false\") {\n return false;\n }\n\n throw new Error(\"Expected true or false\");\n },\n stringify(value) {\n if (value === true) {\n return \"true\";\n }\n\n if (value === false) {\n return \"false\";\n }\n\n throw new Error(\"Expected a boolean\");\n },\n};\n\n/**\n * Creates a case-sensitive string codec from a snapshotted list of members.\n *\n * @typeParam Values - The literal list from which the value union is inferred.\n * @param values - Allowed decoded strings; an empty string is valid when listed.\n * @returns A codec whose parser and stringifier reject nonmembers.\n * @throws TypeError if the list or its entries are malformed.\n *\n * @example\n * ```ts\n * const tab = enumParam([\"details\", \"reviews\"]);\n * tab.parse(\"reviews\"); // \"reviews\"\n * ```\n */\nexport function enumParam<const Values extends readonly string[]>(\n values: Values,\n): ParamCodec<Values[number]> {\n if (!Array.isArray(values)) {\n throw new TypeError(\"Enum values must be a string list\");\n }\n\n const members = new Set<string>();\n\n for (const value of values) {\n if (typeof value !== \"string\") {\n throw new TypeError(\"Enum values must be strings\");\n }\n\n members.add(value);\n }\n\n return {\n parse(raw) {\n if (!members.has(raw)) {\n throw new Error(\"Unknown enum value\");\n }\n\n return raw as Values[number];\n },\n stringify(value) {\n if (!members.has(value)) {\n throw new Error(\"Unknown enum value\");\n }\n\n return value;\n },\n };\n}\n\n/**\n * Gives a search key a value read in place of a missing, repeated or invalid one.\n *\n * @remarks\n * Every search key is optional: a plain codec's key reads as absent when its\n * value is missing, repeated or invalid. With a fallback, the key always reads a\n * value of the codec's type, while URL creation, links, navigation and redirect\n * replacements may still omit it. The fallback is returned as is: it is neither\n * parsed nor copied. Present values delegate to the wrapped codec unchanged.\n * Fallback codecs are search-only: a path param can't use one.\n *\n * @example\n * ```ts\n * search: { page: withFallback(numberParam, 1) }\n * // ?page=abc, ?page=1&page=2 and no page all read as 1.\n * ```\n *\n * @typeParam Value - The wrapped codec's logical value.\n * @param codec - The codec used for present search values.\n * @param fallback - The value read when the key is missing, repeated or invalid.\n * @returns A search-only codec that reads the fallback in place of an absent value.\n * @throws TypeError if the codec lacks callable parse/stringify methods or already\n * has a fallback.\n */\nexport function withFallback<Value>(\n codec: ParamCodec<Value> & SyncValue<NoInfer<Value>>,\n fallback: NoInfer<Value>,\n): FallbackCodec<Value> {\n validateCodec(codec);\n\n if (codecFallback(codec)) {\n throw new TypeError(\"withFallback cannot wrap a codec that already has a fallback\");\n }\n\n const wrapper: ParamCodec<Value> = {\n parse(raw) {\n return codec.parse(raw);\n },\n stringify(value) {\n return codec.stringify(value);\n },\n };\n\n fallbacks.set(wrapper, Object.freeze({ value: fallback }));\n\n return wrapper as FallbackCodec<Value>;\n}\n","type ValidName<Name extends string> = Name extends\n | \"\"\n | \"__proto__\"\n | `...${string}`\n | `${string}?${string}`\n | `${string}*${string}`\n | `${string}[]${string}`\n ? false\n : true;\ntype SegmentValid<Segment extends string> = Segment extends `$${infer Name}`\n ? ValidName<Name>\n : Segment extends \"\" | \".\" | \"..\" | \"*\" | \"**\" | `:${string}`\n ? false\n : true;\ntype ValidateSegments<\n Path extends string,\n Scalars extends string = never,\n> = Path extends `${infer Head}/${infer Tail}`\n ? Head extends `$${string}[]`\n ? false\n : SegmentValid<Head> extends true\n ? ValidateSegments<Tail, Scalars | ScalarName<Head>>\n : false\n : Path extends `$${infer Name}[]`\n ? ValidName<Name> extends true\n ? Name extends Scalars\n ? false\n : true\n : false\n : SegmentValid<Path>;\nexport type ValidPath<Path extends string> = string extends Path\n ? never\n : Path extends \"\"\n ? Path\n : ValidateSegments<Path> extends true\n ? Path\n : never;\ntype ScalarName<Segment extends string> = Segment extends `$${infer Name}` ? Name : never;\ntype SegmentName<Segment extends string> = Segment extends `$${infer Name}[]`\n ? Name\n : ScalarName<Segment>;\nexport type PathNames<Path extends string> = Path extends `${infer Head}/${infer Tail}`\n ? SegmentName<Head> | PathNames<Tail>\n : SegmentName<Path>;\nexport type CatchallName<Path extends string> = Path extends `${string}/${infer Tail}`\n ? CatchallName<Tail>\n : Path extends `$${infer Name}[]`\n ? Name\n : never;\n\nexport type Segment =\n | { readonly kind: \"static\"; readonly text: string }\n | { readonly kind: \"scalar\" | \"catchall\"; readonly name: string };\n\nexport function parsePath(path: unknown): readonly Segment[] {\n if (typeof path !== \"string\") {\n throw new TypeError(\"Path must be a string\");\n }\n\n if (path === \"\") {\n return Object.freeze([]);\n }\n\n const segments: Segment[] = [];\n const scalarNames = new Set<string>();\n const parts = path.split(\"/\");\n\n for (let index = 0; index < parts.length; index += 1) {\n const part = parts[index];\n\n if (part.startsWith(\"$\")) {\n let name = part.slice(1);\n let kind: \"scalar\" | \"catchall\" = \"scalar\";\n\n if (name.endsWith(\"[]\")) {\n name = name.slice(0, -2);\n kind = \"catchall\";\n }\n\n if (\n name === \"\" ||\n name === \"__proto__\" ||\n name.startsWith(\"...\") ||\n name.includes(\"?\") ||\n name.includes(\"*\") ||\n name.includes(\"[]\")\n ) {\n throw new TypeError(`Invalid parameter name: ${name}`);\n }\n\n if (kind === \"catchall\" && (index !== parts.length - 1 || scalarNames.has(name))) {\n throw new TypeError(\"Catchall must be terminal and cannot repeat a scalar name\");\n }\n\n scalarNames.add(name);\n segments.push(Object.freeze({ kind, name }));\n } else {\n if (\n part === \"\" ||\n part === \".\" ||\n part === \"..\" ||\n part === \"*\" ||\n part === \"**\" ||\n part.startsWith(\":\")\n ) {\n throw new TypeError(`Invalid static segment: ${part}`);\n }\n\n if (!part.isWellFormed()) {\n throw new TypeError(\"Static path Unicode must be well formed\");\n }\n\n segments.push(Object.freeze({ kind: \"static\", text: part }));\n }\n }\n\n return Object.freeze(segments);\n}\n","export function ownRecord(\n value: unknown,\n label: string,\n allowSymbols = false,\n): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new TypeError(`${label} must be an own record`);\n }\n\n const prototype = Object.getPrototypeOf(value);\n\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(`${label} cannot contain inherited entries`);\n }\n\n for (const key of Reflect.ownKeys(value)) {\n if (\n (!allowSymbols && typeof key !== \"string\") ||\n !Object.prototype.propertyIsEnumerable.call(value, key)\n ) {\n throw new TypeError(`${label} contains an unsupported key`);\n }\n }\n\n return value as Record<string, unknown>;\n}\n\nexport function checkKeys(\n record: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n label: string,\n): void {\n for (const key of Object.keys(record)) {\n if (!allowed.has(key)) {\n throw new TypeError(`Unknown ${label} key: ${key}`);\n }\n }\n}\n\nexport function has(record: object, key: PropertyKey): boolean {\n return Object.hasOwn(record, key);\n}\n","import { codecFallback, validateCodec, type ParamCodec, type PathCodec } from \"./codecs.js\";\nimport { parsePath, type Segment, type ValidPath, type CatchallName } from \"./path.js\";\nimport { checkKeys, has, ownRecord } from \"./records.js\";\nimport type {\n AnyRoute,\n CodecMap,\n EffectiveParams,\n EffectiveSearch,\n Route,\n RouteConfig,\n SearchOf,\n} from \"./types.js\";\n\nexport interface RouteMetadata {\n readonly parent?: AnyRoute;\n readonly localSegments: readonly Segment[];\n readonly segments: readonly Segment[];\n readonly localParams: Readonly<Record<string, ParamCodec<any>>>;\n readonly localSearch: Readonly<Record<string, ParamCodec<any>>>;\n readonly params: Readonly<Record<string, ParamCodec<any>>>;\n readonly search: Readonly<Record<string, ParamCodec<any>>>;\n readonly fragments: readonly string[];\n readonly config: Readonly<Record<string, unknown>>;\n}\n\nconst routes = new WeakMap<object, RouteMetadata>();\nconst configKeys = new Set([\n \"parent\",\n \"params\",\n \"search\",\n \"resolve\",\n \"runGuardsAndResolvers\",\n \"redirect\",\n \"fragments\",\n \"canActivate\",\n \"canActivateChild\",\n \"canMatch\",\n \"onInvalidParams\",\n \"canDeactivate\",\n \"providers\",\n \"title\",\n \"data\",\n]);\nconst policies = new Set([\n \"pathParamsChange\",\n \"pathParamsOrQueryParamsChange\",\n \"paramsChange\",\n \"paramsOrQueryParamsChange\",\n \"always\",\n]);\nconst identityKey = \"__loozoAngularRouterRouteId\";\n\nexport function routeMetadata(route: unknown): RouteMetadata {\n if (route === null || typeof route !== \"object\" || !routes.has(route)) {\n throw new TypeError(\"Expected a genuine route from this package instance\");\n }\n\n return routes.get(route)!;\n}\n\nfunction copyCodecs(value: unknown, path: boolean): Readonly<Record<string, ParamCodec<any>>> {\n const record = ownRecord(value, \"Codec map\");\n const result: Record<string, ParamCodec<any>> = Object.create(null);\n\n for (const key of Object.keys(record)) {\n const codec = record[key];\n\n validateCodec(codec);\n\n if (path && codecFallback(codec)) {\n throw new TypeError(\"withFallback codecs are search-only\");\n }\n\n result[key] = codec;\n }\n\n return Object.freeze(result);\n}\n\nfunction snapshotRedirect(\n value: unknown,\n source: RouteMetadata,\n): Readonly<Record<string, unknown>> {\n const redirect = ownRecord(value, \"Redirect\");\n\n checkKeys(redirect, new Set([\"to\", \"params\", \"search\", \"fragment\"]), \"redirect\");\n\n const target = routeMetadata(redirect.to);\n const mapping: Record<string, string> = Object.create(null);\n\n if (has(redirect, \"params\")) {\n const supplied = ownRecord(redirect.params, \"Redirect params\");\n\n checkKeys(supplied, new Set(Object.keys(target.params)), \"redirect params\");\n\n for (const key of Object.keys(target.params)) {\n const sourceKey = supplied[key];\n\n if (!has(supplied, key) || typeof sourceKey !== \"string\" || !has(source.params, sourceKey)) {\n throw new TypeError(`Missing or invalid redirect mapping: ${key}`);\n }\n\n mapping[key] = sourceKey;\n }\n } else {\n for (const key of Object.keys(target.params)) {\n if (!has(source.params, key)) {\n throw new TypeError(`Cannot forward redirect param: ${key}`);\n }\n\n mapping[key] = key;\n }\n }\n\n const search = ownRecord(redirect.search, \"Redirect search\");\n let searchSnapshot: Record<string, unknown>;\n\n if (search.mode === \"replace\") {\n checkKeys(search, new Set([\"mode\", \"values\"]), \"redirect search\");\n\n const values = ownRecord(search.values, \"Redirect replacement\");\n\n checkKeys(values, new Set(Object.keys(target.search)), \"search values\");\n searchSnapshot = { mode: \"replace\", values: Object.freeze({ ...values }) };\n } else if (search.mode === \"preserve\" || search.mode === \"drop\") {\n checkKeys(search, new Set([\"mode\"]), \"redirect search\");\n searchSnapshot = { mode: search.mode };\n } else {\n throw new TypeError(\"Invalid redirect search policy\");\n }\n\n const fragment = ownRecord(redirect.fragment, \"Redirect fragment\");\n\n if (fragment.mode === \"replace\") {\n checkKeys(fragment, new Set([\"mode\", \"value\"]), \"redirect fragment\");\n\n if (typeof fragment.value !== \"string\" || !target.fragments.includes(fragment.value)) {\n throw new TypeError(\"Redirect fragment must belong to target declaration\");\n }\n } else if (fragment.mode === \"preserve\" || fragment.mode === \"drop\") {\n checkKeys(fragment, new Set([\"mode\"]), \"redirect fragment\");\n } else {\n throw new TypeError(\"Invalid redirect fragment policy\");\n }\n\n return Object.freeze({\n to: redirect.to,\n params: Object.freeze(mapping),\n search: Object.freeze(searchSnapshot),\n fragment: Object.freeze({ ...fragment }),\n });\n}\n\n/**\n * Declares a nominal typed route without executing codecs or native callbacks.\n *\n * @remarks\n * Paths are decoded authored text, not URLs: use `\"\"` for root/pathless nodes,\n * `$name` for a scalar segment and terminal `$name[]` for a zero-or-more\n * catchall. Repeated local scalar names reuse one value. Leading/trailing or\n * repeated slashes, dot segments and Angular `:name`/wildcard notation are invalid.\n *\n * Parents compose effective params/search transitively, including through\n * pathless nodes. Children cannot redeclare ancestor-owned keys or have a\n * catchall parent. Fragment names belong only to this declaration.\n * The route and copied containers are shallow-frozen; application codecs,\n * callbacks, providers and opaque values retain identity and are not deep-frozen.\n *\n * For generation, author a direct default export of this call with a literal\n * path and inline config. Parent and redirect targets must be direct default\n * imports of admitted declarations. Angular owns activation and navigation;\n * declaration alone does not register a route with Angular.\n *\n * @param path - The literal local path, relative to the authored parent.\n * @param config - Local codecs, parent, fragments and supported native behavior.\n * Structural Angular options such as children, component and matcher are\n * generator-owned and cannot be overridden.\n * @returns A frozen route preserving inferred effective input and local data types.\n * @throws TypeError for invalid paths/configuration, missing or extra local\n * codecs, fallback codecs in path params, inherited key conflicts, or\n * nongenuine parent/redirect routes.\n *\n * @example\n * ```ts\n * const product = defineRoute(\"products/$productId\", {\n * params: { productId: numberParam },\n * search: { tab: withFallback(enumParam([\"details\", \"reviews\"]), \"details\") },\n * fragments: [\"summary\", \"reviews\"],\n * });\n * ```\n */\nexport function defineRoute<\n const Path extends string,\n Parent extends AnyRoute | undefined = undefined,\n Params extends Record<string, PathCodec> = {},\n Search extends CodecMap = {},\n Resolvers extends Record<string, (...args: any[]) => unknown> = {},\n const Fragments extends readonly string[] = [],\n Target extends AnyRoute | undefined = undefined,\n ReplacementKeys extends keyof SearchOf<NoInfer<Target>> = never,\n>(\n path: Path & ValidPath<Path>,\n config: RouteConfig<Path, Parent, Params, Search, Resolvers, Fragments, Target, ReplacementKeys>,\n): Route<\n Path,\n EffectiveParams<Path, Params, Parent>,\n EffectiveSearch<Search, Parent>,\n Resolvers,\n Fragments[number],\n CatchallName<Path> extends never ? false : true\n>;\n\nexport function defineRoute(path: unknown, config: unknown): AnyRoute {\n const supplied = ownRecord(config, \"Route config\");\n\n checkKeys(supplied, configKeys, \"route config\");\n\n const localSegments = parsePath(path);\n let parent: AnyRoute | undefined;\n let inherited: RouteMetadata | undefined;\n\n if (has(supplied, \"parent\")) {\n inherited = routeMetadata(supplied.parent);\n parent = supplied.parent as AnyRoute;\n\n for (const segment of inherited.segments) {\n if (segment.kind === \"catchall\") {\n throw new TypeError(\"Catchall declarations cannot have children\");\n }\n }\n }\n\n const localNames = new Set<string>();\n\n for (const segment of localSegments) {\n if (segment.kind !== \"static\") {\n localNames.add(segment.name);\n }\n }\n\n let localParams: Readonly<Record<string, ParamCodec<any>>> = Object.freeze(Object.create(null));\n\n if (localNames.size === 0) {\n if (has(supplied, \"params\")) {\n throw new TypeError(\"Static paths cannot declare params\");\n }\n } else {\n localParams = copyCodecs(supplied.params, true);\n checkKeys(localParams, localNames, \"local params\");\n\n for (const key of localNames) {\n if (!has(localParams, key)) {\n throw new TypeError(`Missing local codec: ${key}`);\n }\n\n if (inherited && has(inherited.params, key)) {\n throw new TypeError(`Inherited param already owned: ${key}`);\n }\n }\n }\n\n let localSearch: Readonly<Record<string, ParamCodec<any>>> = Object.freeze(Object.create(null));\n\n if (has(supplied, \"search\")) {\n localSearch = copyCodecs(supplied.search, false);\n }\n\n for (const key of Object.keys(localSearch)) {\n if (inherited && has(inherited.search, key)) {\n throw new TypeError(`Inherited search already owned: ${key}`);\n }\n }\n\n const retained: Record<string, unknown> = { ...supplied };\n const result: {\n path: string;\n resolve?: Readonly<Record<PropertyKey, unknown>>;\n runGuardsAndResolvers?: unknown;\n } = { path: path as string };\n\n if (has(supplied, \"resolve\")) {\n const resolve = ownRecord(supplied.resolve, \"Resolvers\", true) as Record<PropertyKey, unknown>;\n const copied: Record<PropertyKey, unknown> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolve)) {\n if (key === identityKey || typeof resolve[key] !== \"function\") {\n throw new TypeError(`Invalid resolver: ${String(key)}`);\n }\n\n copied[key] = resolve[key];\n }\n\n result.resolve = Object.freeze(copied);\n retained.resolve = result.resolve;\n }\n\n if (has(supplied, \"runGuardsAndResolvers\")) {\n const policy = supplied.runGuardsAndResolvers;\n\n if (typeof policy !== \"function\" && (typeof policy !== \"string\" || !policies.has(policy))) {\n throw new TypeError(\"Invalid native rerun policy\");\n }\n\n result.runGuardsAndResolvers = policy;\n }\n\n for (const key of [\"canActivate\", \"canActivateChild\", \"canMatch\", \"canDeactivate\", \"providers\"]) {\n if (!has(supplied, key)) {\n continue;\n }\n\n const list = supplied[key];\n\n if (!Array.isArray(list)) {\n throw new TypeError(`${key} must be an array`);\n }\n\n if (key === \"canActivate\" || key === \"canActivateChild\" || key === \"canMatch\") {\n for (const callback of list) {\n if (typeof callback !== \"function\") {\n throw new TypeError(`${key} entries must be callbacks`);\n }\n }\n } else if (key === \"canDeactivate\") {\n for (const guard of list) {\n if (\n guard === null ||\n (typeof guard !== \"function\" && typeof guard !== \"object\" && typeof guard !== \"string\")\n ) {\n throw new TypeError(\"canDeactivate entries must be native callbacks or tokens\");\n }\n }\n }\n\n retained[key] = Object.freeze([...list]);\n }\n\n if (has(supplied, \"onInvalidParams\")) {\n if (typeof supplied.onInvalidParams !== \"function\") {\n throw new TypeError(\"onInvalidParams must be a callback\");\n }\n\n if (localNames.size === 0) {\n throw new TypeError(\"onInvalidParams requires local path params\");\n }\n }\n\n if (\n has(supplied, \"title\") &&\n typeof supplied.title !== \"string\" &&\n typeof supplied.title !== \"function\"\n ) {\n throw new TypeError(\"Title must be a string or a callback\");\n }\n\n if (has(supplied, \"data\")) {\n const data = ownRecord(supplied.data, \"Static data\", true);\n\n if (has(data, identityKey)) {\n throw new TypeError(\"Static data cannot set generated identity\");\n }\n\n retained.data = Object.freeze({ ...data });\n }\n\n const fragments: string[] = [];\n\n if (has(supplied, \"fragments\")) {\n if (!Array.isArray(supplied.fragments)) {\n throw new TypeError(\"Fragments must be a string list\");\n }\n\n for (const name of supplied.fragments) {\n if (typeof name !== \"string\") {\n throw new TypeError(\"Fragment names must be strings\");\n }\n\n fragments.push(name);\n }\n }\n\n retained.fragments = Object.freeze(fragments);\n retained.params = localParams;\n retained.search = localSearch;\n\n const metadata: RouteMetadata = {\n parent,\n localSegments,\n segments: Object.freeze([...(inherited?.segments ?? []), ...localSegments]),\n localParams,\n localSearch,\n params: Object.freeze({ ...inherited?.params, ...localParams }),\n search: Object.freeze({ ...inherited?.search, ...localSearch }),\n fragments: retained.fragments as readonly string[],\n config: retained,\n };\n\n if (has(supplied, \"redirect\")) {\n if (\n has(supplied, \"canActivate\") ||\n has(supplied, \"canMatch\") ||\n has(supplied, \"onInvalidParams\")\n ) {\n throw new TypeError(\"Redirect cannot declare own canActivate, canMatch or onInvalidParams\");\n }\n\n retained.redirect = snapshotRedirect(supplied.redirect, metadata);\n }\n\n Object.freeze(retained);\n routes.set(result, Object.freeze(metadata));\n\n return Object.freeze(result) as AnyRoute;\n}\n","import type { ParamCodec } from \"./codecs.js\";\nimport { ownRecord, checkKeys, has } from \"./records.js\";\nimport { routeMetadata } from \"./route.js\";\nimport type { AnyRoute, SearchOf, UrlValues } from \"./types.js\";\n\nfunction encode(value: string): string {\n return encodeURIComponent(value).replaceAll(\"(\", \"%28\").replaceAll(\")\", \"%29\");\n}\n\nfunction stringify(codec: ParamCodec<any>, value: unknown, path: boolean): string {\n const text = codec.stringify(value);\n\n if (typeof text !== \"string\") {\n throw new TypeError(\"Codec stringify must return a string\");\n }\n\n if (path && (text === \"\" || text === \".\" || text === \"..\")) {\n throw new TypeError(\"Path output cannot be empty, dot or dotdot\");\n }\n\n return encode(text);\n}\n\n/**\n * Synchronously serializes a route's explicit values into a root-relative URL.\n *\n * @remarks\n * Includes inherited path/search declarations, but only this route's fragment\n * names. Every effective path value must be supplied; any search key may be\n * omitted. Searchless/paramless routes forbid those records. Catchalls require readonly arrays, including a valid empty array.\n * Values are never taken from a current navigation.\n *\n * Stringifies without calling parsers, guards, resolvers or redirects. Static\n * segments and logical values are component-encoded (also escaping parentheses),\n * so a dynamic slash becomes `%2F`. Search keys are globally sorted; omitted\n * and `undefined` values are left out. An empty effective path produces `/`.\n * Redirect declarations serialize their source URL, not their redirect target.\n *\n * @param route - A genuine declaration from this physical package instance,\n * not a generated destination, spread/copy or structural lookalike.\n * @param values - Explicit destination-typed params, search and optional fragment.\n * Pass an empty object when the route needs no values.\n * @returns A root-relative URL string; this does not navigate or return a UrlTree.\n * @throws TypeError for invalid routes/records, missing or unknown keys,\n * undeclared fragments, nonarray catchalls, nonstring codec output, or empty/dot\n * path output. Application stringifier failures propagate unchanged.\n * @throws URIError for ill-formed Unicode in a serialized value.\n *\n * @example\n * ```ts\n * const product = defineRoute(\"products/$productId\", {\n * params: { productId: numberParam },\n * fragments: [\"summary\"],\n * });\n * createUrl(product, { params: { productId: 42 }, fragment: \"summary\" });\n * // /products/42#summary\n * ```\n */\nexport function createUrl<\n Target extends AnyRoute,\n SearchKeys extends keyof SearchOf<NoInfer<Target>> = never,\n>(route: Target, values: UrlValues<NoInfer<Target>, SearchKeys>): string;\n\nexport function createUrl(route: unknown, values: unknown): string {\n const metadata = routeMetadata(route);\n const options = ownRecord(values, \"URL options\");\n\n checkKeys(options, new Set([\"params\", \"search\", \"fragment\"]), \"URL options\");\n\n const paramKeys = Object.keys(metadata.params);\n let params: Record<string, unknown> = Object.create(null);\n\n if (paramKeys.length === 0) {\n if (has(options, \"params\")) {\n throw new TypeError(\"Route has no path params\");\n }\n } else {\n params = ownRecord(options.params, \"Path values\");\n checkKeys(params, new Set(paramKeys), \"path values\");\n\n for (const key of paramKeys) {\n if (!has(params, key)) {\n throw new TypeError(`Missing path value: ${key}`);\n }\n }\n }\n\n const searchKeys = Object.keys(metadata.search).sort();\n let search: Record<string, unknown> = Object.create(null);\n\n if (searchKeys.length === 0) {\n if (has(options, \"search\")) {\n throw new TypeError(\"Route has no search declarations\");\n }\n } else {\n if (has(options, \"search\")) {\n search = ownRecord(options.search, \"Search values\");\n }\n\n checkKeys(search, new Set(searchKeys), \"search values\");\n }\n\n if (has(options, \"fragment\")) {\n if (typeof options.fragment !== \"string\" || !metadata.fragments.includes(options.fragment)) {\n throw new TypeError(\"Fragment must belong to this declaration\");\n }\n }\n\n // Check all cardinalities before invoking application stringifiers.\n for (const segment of metadata.segments) {\n if (segment.kind === \"catchall\" && !Array.isArray(params[segment.name])) {\n throw new TypeError(`Catchall requires an array: ${segment.name}`);\n }\n }\n\n const parts: string[] = [];\n\n for (const segment of metadata.segments) {\n if (segment.kind === \"static\") {\n parts.push(encode(segment.text));\n } else if (segment.kind === \"scalar\") {\n parts.push(stringify(metadata.params[segment.name], params[segment.name], true));\n } else {\n for (const value of params[segment.name] as readonly unknown[]) {\n parts.push(stringify(metadata.params[segment.name], value, true));\n }\n }\n }\n\n let url = `/${parts.join(\"/\")}`;\n const query: string[] = [];\n\n for (const key of searchKeys) {\n const value = search[key];\n\n if (!has(search, key) || value === undefined) {\n continue;\n }\n\n query.push(`${encode(key)}=${stringify(metadata.search[key], value, false)}`);\n }\n\n if (query.length > 0) {\n url += `?${query.join(\"&\")}`;\n }\n\n if (has(options, \"fragment\")) {\n url += `#${encode(options.fragment as string)}`;\n }\n\n return url;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"loozo-angular-router-_core.mjs","names":[],"sources":["../../_core/src/codecs.ts","../../_core/src/path.ts","../../_core/src/records.ts","../../_core/src/route.ts","../../_core/src/url.ts"],"sourcesContent":["/**\n * Converts one decoded path or search value to and from an application value.\n *\n * @remarks\n * Both methods are synchronous, and parsing should be pure and deterministic:\n * like Angular's matching callbacks, it runs once while matching and again for\n * the activated route. Neither method performs URL encoding. Codecs have no\n * Angular injection context, and their returned objects are not recursively frozen.\n * For a terminal `$name[]` path, this codec applies to each element separately.\n *\n * @typeParam Value - The logical value, never a promise of that value.\n *\n * @example\n * ```ts\n * const dateParam: ParamCodec<Date> = {\n * parse: (raw) => new Date(raw),\n * stringify: (value) => value.toISOString(),\n * };\n * ```\n */\nexport interface ParamCodec<Value> {\n /**\n * Parses one already percent-decoded value; do not decode it again.\n *\n * @param raw - A single logical string from Angular's URL inputs.\n * @returns The logical value, synchronously. Returning a promise or other\n * thenable is a programming error that fails the navigation with a TypeError.\n * @throws An application error for invalid input: an invalid path value makes\n * the route not match, and an invalid search value reads as absent or as its fallback.\n */\n parse(raw: string): Value;\n /**\n * Serializes one logical value without percent-encoding it.\n *\n * @param value - The application value to serialize.\n * @returns An unencoded string. Path output must not be empty, `.` or `..`.\n * @throws An application error when the value cannot be serialized.\n */\n stringify(value: Value): string;\n}\n\ndeclare const searchFallback: unique symbol;\n\n/**\n * A search-only codec whose key reads a fallback value when it is missing,\n * repeated or invalid, while URL creation may still omit it.\n */\nexport type FallbackCodec<Value> = ParamCodec<Value> & {\n readonly [searchFallback]: true;\n};\nexport type PathCodec = ParamCodec<any> & { readonly [searchFallback]?: never };\nexport type CodecValue<Codec> = Codec extends ParamCodec<infer Value> ? Value : never;\nexport type HasFallback<Codec> = Codec extends { readonly [searchFallback]: true } ? true : false;\n\n/** Type-only marker: a codec whose parse returns a promise fails where it is declared. */\nexport interface SynchronousParse {\n /** Never present: `parse` must return its value synchronously, not a Promise. */\n readonly \"ParamCodec.parse must return its value synchronously, not a Promise\": never;\n}\ntype ParseResult<Codec> = Codec extends { parse(raw: string): infer Result } ? Result : never;\nexport type SyncValue<Value> =\n Extract<Value, PromiseLike<unknown>> extends never ? unknown : SynchronousParse;\nexport type SyncCodecs<Codecs> = {\n [Key in keyof Codecs]: SyncValue<ParseResult<Codecs[Key]>>;\n};\n\nconst fallbacks = new WeakMap<object, { readonly value: unknown }>();\n\nexport function codecFallback(codec: object): { readonly value: unknown } | undefined {\n return fallbacks.get(codec);\n}\n\nexport function validateCodec(codec: unknown): asserts codec is ParamCodec<any> {\n if (\n codec === null ||\n (typeof codec !== \"object\" && typeof codec !== \"function\") ||\n typeof (codec as ParamCodec<unknown>).parse !== \"function\" ||\n typeof (codec as ParamCodec<unknown>).stringify !== \"function\"\n ) {\n throw new TypeError(\"Codec must have callable parse and stringify methods\");\n }\n}\n\n/**\n * Preserves strings verbatim, including empty strings and literal percent text.\n *\n * @remarks\n * Empty, dot and dotdot values are valid codec values but cannot be serialized\n * into path segments by URL creation. Search values may contain them.\n */\nexport const stringParam: ParamCodec<string> = {\n parse(raw) {\n return raw;\n },\n stringify(value) {\n if (typeof value !== \"string\") {\n throw new TypeError(\"Expected a string\");\n }\n\n return value;\n },\n};\n\n/**\n * Parses nonblank text with JavaScript `Number` and requires a finite result.\n *\n * @remarks\n * Whitespace around numbers, exponent notation and hexadecimal text are accepted.\n * Blank text, NaN and infinities throw. Stringification requires a finite number\n * and uses its JavaScript string representation (including `-0` becoming `\"0\"`).\n */\nexport const numberParam: ParamCodec<number> = {\n parse(raw) {\n const value = Number(raw);\n\n if (raw.trim() === \"\" || !Number.isFinite(value)) {\n throw new Error(\"Expected a finite number\");\n }\n\n return value;\n },\n stringify(value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(\"Expected a finite number\");\n }\n\n return String(value);\n },\n};\n\n/**\n * Parses only lowercase `\"true\"` and `\"false\"`, and emits those same strings.\n * Other representations and nonboolean values throw.\n */\nexport const booleanParam: ParamCodec<boolean> = {\n parse(raw) {\n if (raw === \"true\") {\n return true;\n }\n\n if (raw === \"false\") {\n return false;\n }\n\n throw new Error(\"Expected true or false\");\n },\n stringify(value) {\n if (value === true) {\n return \"true\";\n }\n\n if (value === false) {\n return \"false\";\n }\n\n throw new Error(\"Expected a boolean\");\n },\n};\n\n/**\n * Creates a case-sensitive string codec from a snapshotted list of members.\n *\n * @typeParam Values - The literal list from which the value union is inferred.\n * @param values - Allowed decoded strings; an empty string is valid when listed.\n * @returns A codec whose parser and stringifier reject nonmembers.\n * @throws TypeError if the list or its entries are malformed.\n *\n * @example\n * ```ts\n * const tab = enumParam([\"details\", \"reviews\"]);\n * tab.parse(\"reviews\"); // \"reviews\"\n * ```\n */\nexport function enumParam<const Values extends readonly string[]>(\n values: Values,\n): ParamCodec<Values[number]> {\n if (!Array.isArray(values)) {\n throw new TypeError(\"Enum values must be a string list\");\n }\n\n const members = new Set<string>();\n\n for (const value of values) {\n if (typeof value !== \"string\") {\n throw new TypeError(\"Enum values must be strings\");\n }\n\n members.add(value);\n }\n\n return {\n parse(raw) {\n if (!members.has(raw)) {\n throw new Error(\"Unknown enum value\");\n }\n\n return raw as Values[number];\n },\n stringify(value) {\n if (!members.has(value)) {\n throw new Error(\"Unknown enum value\");\n }\n\n return value;\n },\n };\n}\n\n/**\n * Gives a search key a value read in place of a missing, repeated or invalid one.\n *\n * @remarks\n * Every search key is optional: a plain codec's key reads as absent when its\n * value is missing, repeated or invalid. With a fallback, the key always reads a\n * value of the codec's type, while URL creation, links, navigation and redirect\n * replacements may still omit it. The fallback is returned as is: it is neither\n * parsed nor copied. Present values delegate to the wrapped codec unchanged.\n * Fallback codecs are search-only: a path param can't use one.\n *\n * @example\n * ```ts\n * search: { page: withFallback(numberParam, 1) }\n * // ?page=abc, ?page=1&page=2 and no page all read as 1.\n * ```\n *\n * @typeParam Value - The wrapped codec's logical value.\n * @param codec - The codec used for present search values.\n * @param fallback - The value read when the key is missing, repeated or invalid.\n * @returns A search-only codec that reads the fallback in place of an absent value.\n * @throws TypeError if the codec lacks callable parse/stringify methods or already\n * has a fallback.\n */\nexport function withFallback<Value>(\n codec: ParamCodec<Value> & SyncValue<NoInfer<Value>>,\n fallback: NoInfer<Value>,\n): FallbackCodec<Value> {\n validateCodec(codec);\n\n if (codecFallback(codec)) {\n throw new TypeError(\"withFallback cannot wrap a codec that already has a fallback\");\n }\n\n const wrapper: ParamCodec<Value> = {\n parse(raw) {\n return codec.parse(raw);\n },\n stringify(value) {\n return codec.stringify(value);\n },\n };\n\n fallbacks.set(wrapper, Object.freeze({ value: fallback }));\n\n return wrapper as FallbackCodec<Value>;\n}\n","type ValidName<Name extends string> = Name extends\n | \"\"\n | \"__proto__\"\n | `...${string}`\n | `${string}?${string}`\n | `${string}*${string}`\n | `${string}[]${string}`\n ? false\n : true;\ntype SegmentValid<Segment extends string> = Segment extends `$${infer Name}`\n ? ValidName<Name>\n : Segment extends \"\" | \".\" | \"..\" | \"*\" | \"**\" | `:${string}`\n ? false\n : true;\ntype ValidateSegments<\n Path extends string,\n Scalars extends string = never,\n> = Path extends `${infer Head}/${infer Tail}`\n ? Head extends `$${string}[]`\n ? false\n : SegmentValid<Head> extends true\n ? ValidateSegments<Tail, Scalars | ScalarName<Head>>\n : false\n : Path extends `$${infer Name}[]`\n ? ValidName<Name> extends true\n ? Name extends Scalars\n ? false\n : true\n : false\n : SegmentValid<Path>;\nexport type ValidPath<Path extends string> = string extends Path\n ? never\n : Path extends \"\"\n ? Path\n : ValidateSegments<Path> extends true\n ? Path\n : never;\ntype ScalarName<Segment extends string> = Segment extends `$${infer Name}` ? Name : never;\ntype SegmentName<Segment extends string> = Segment extends `$${infer Name}[]`\n ? Name\n : ScalarName<Segment>;\nexport type PathNames<Path extends string> = Path extends `${infer Head}/${infer Tail}`\n ? SegmentName<Head> | PathNames<Tail>\n : SegmentName<Path>;\nexport type CatchallName<Path extends string> = Path extends `${string}/${infer Tail}`\n ? CatchallName<Tail>\n : Path extends `$${infer Name}[]`\n ? Name\n : never;\n\nexport type Segment =\n | { readonly kind: \"static\"; readonly text: string }\n | { readonly kind: \"scalar\" | \"catchall\"; readonly name: string };\n\nexport function parsePath(path: unknown): readonly Segment[] {\n if (typeof path !== \"string\") {\n throw new TypeError(\"Path must be a string\");\n }\n\n if (path === \"\") {\n return Object.freeze([]);\n }\n\n const segments: Segment[] = [];\n const scalarNames = new Set<string>();\n const parts = path.split(\"/\");\n\n for (let index = 0; index < parts.length; index += 1) {\n const part = parts[index];\n\n if (part.startsWith(\"$\")) {\n let name = part.slice(1);\n let kind: \"scalar\" | \"catchall\" = \"scalar\";\n\n if (name.endsWith(\"[]\")) {\n name = name.slice(0, -2);\n kind = \"catchall\";\n }\n\n if (\n name === \"\" ||\n name === \"__proto__\" ||\n name.startsWith(\"...\") ||\n name.includes(\"?\") ||\n name.includes(\"*\") ||\n name.includes(\"[]\")\n ) {\n throw new TypeError(`Invalid parameter name: ${name}`);\n }\n\n if (kind === \"catchall\" && (index !== parts.length - 1 || scalarNames.has(name))) {\n throw new TypeError(\"Catchall must be terminal and cannot repeat a scalar name\");\n }\n\n scalarNames.add(name);\n segments.push(Object.freeze({ kind, name }));\n } else {\n if (\n part === \"\" ||\n part === \".\" ||\n part === \"..\" ||\n part === \"*\" ||\n part === \"**\" ||\n part.startsWith(\":\")\n ) {\n throw new TypeError(`Invalid static segment: ${part}`);\n }\n\n if (!part.isWellFormed()) {\n throw new TypeError(\"Static path Unicode must be well formed\");\n }\n\n segments.push(Object.freeze({ kind: \"static\", text: part }));\n }\n }\n\n return Object.freeze(segments);\n}\n","export function ownRecord(\n value: unknown,\n label: string,\n allowSymbols = false,\n): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new TypeError(`${label} must be an own record`);\n }\n\n const prototype = Object.getPrototypeOf(value);\n\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(`${label} cannot contain inherited entries`);\n }\n\n for (const key of Reflect.ownKeys(value)) {\n if (\n (!allowSymbols && typeof key !== \"string\") ||\n !Object.prototype.propertyIsEnumerable.call(value, key)\n ) {\n throw new TypeError(`${label} contains an unsupported key`);\n }\n }\n\n return value as Record<string, unknown>;\n}\n\nexport function checkKeys(\n record: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n label: string,\n): void {\n for (const key of Object.keys(record)) {\n if (!allowed.has(key)) {\n throw new TypeError(`Unknown ${label} key: ${key}`);\n }\n }\n}\n\nexport function has(record: object, key: PropertyKey): boolean {\n return Object.hasOwn(record, key);\n}\n","import { codecFallback, validateCodec, type ParamCodec, type PathCodec } from \"./codecs.js\";\nimport { parsePath, type Segment, type ValidPath, type CatchallName } from \"./path.js\";\nimport { checkKeys, has, ownRecord } from \"./records.js\";\nimport type {\n AnyRoute,\n CodecMap,\n EffectiveParams,\n EffectiveSearch,\n Route,\n RouteConfig,\n SearchOf,\n} from \"./types.js\";\n\nexport interface RouteMetadata {\n readonly parent?: AnyRoute;\n readonly localSegments: readonly Segment[];\n readonly segments: readonly Segment[];\n readonly localParams: Readonly<Record<string, ParamCodec<any>>>;\n readonly localSearch: Readonly<Record<string, ParamCodec<any>>>;\n readonly params: Readonly<Record<string, ParamCodec<any>>>;\n readonly search: Readonly<Record<string, ParamCodec<any>>>;\n readonly fragments: readonly string[];\n readonly config: Readonly<Record<string, unknown>>;\n}\n\nconst routes = new WeakMap<object, RouteMetadata>();\nconst configKeys = new Set([\n \"parent\",\n \"params\",\n \"search\",\n \"resolve\",\n \"runGuardsAndResolvers\",\n \"redirect\",\n \"fragments\",\n \"canActivate\",\n \"canActivateChild\",\n \"canMatch\",\n \"onInvalidParams\",\n \"canDeactivate\",\n \"providers\",\n \"title\",\n \"data\",\n]);\nconst policies = new Set([\n \"pathParamsChange\",\n \"pathParamsOrQueryParamsChange\",\n \"paramsChange\",\n \"paramsOrQueryParamsChange\",\n \"always\",\n]);\nconst identityKey = \"__loozoAngularRouterRouteId\";\n\nexport function routeMetadata(route: unknown): RouteMetadata {\n if (route === null || typeof route !== \"object\" || !routes.has(route)) {\n throw new TypeError(\"Expected a genuine route from this package instance\");\n }\n\n return routes.get(route)!;\n}\n\nfunction copyCodecs(value: unknown, path: boolean): Readonly<Record<string, ParamCodec<any>>> {\n const record = ownRecord(value, \"Codec map\");\n const result: Record<string, ParamCodec<any>> = Object.create(null);\n\n for (const key of Object.keys(record)) {\n const codec = record[key];\n\n validateCodec(codec);\n\n if (path && codecFallback(codec)) {\n throw new TypeError(\"withFallback codecs are search-only\");\n }\n\n result[key] = codec;\n }\n\n return Object.freeze(result);\n}\n\nfunction snapshotRedirect(\n value: unknown,\n source: RouteMetadata,\n): Readonly<Record<string, unknown>> {\n const redirect = ownRecord(value, \"Redirect\");\n\n checkKeys(redirect, new Set([\"to\", \"params\", \"search\", \"fragment\"]), \"redirect\");\n\n const target = routeMetadata(redirect.to);\n const mapping: Record<string, string> = Object.create(null);\n\n if (has(redirect, \"params\")) {\n const supplied = ownRecord(redirect.params, \"Redirect params\");\n\n checkKeys(supplied, new Set(Object.keys(target.params)), \"redirect params\");\n\n for (const key of Object.keys(target.params)) {\n const sourceKey = supplied[key];\n\n if (!has(supplied, key) || typeof sourceKey !== \"string\" || !has(source.params, sourceKey)) {\n throw new TypeError(`Missing or invalid redirect mapping: ${key}`);\n }\n\n mapping[key] = sourceKey;\n }\n } else {\n for (const key of Object.keys(target.params)) {\n if (!has(source.params, key)) {\n throw new TypeError(`Cannot forward redirect param: ${key}`);\n }\n\n mapping[key] = key;\n }\n }\n\n const search = ownRecord(redirect.search, \"Redirect search\");\n let searchSnapshot: Record<string, unknown>;\n\n if (search.mode === \"replace\") {\n checkKeys(search, new Set([\"mode\", \"values\"]), \"redirect search\");\n\n const values = ownRecord(search.values, \"Redirect replacement\");\n\n checkKeys(values, new Set(Object.keys(target.search)), \"search values\");\n searchSnapshot = { mode: \"replace\", values: Object.freeze({ ...values }) };\n } else if (search.mode === \"preserve\" || search.mode === \"drop\") {\n checkKeys(search, new Set([\"mode\"]), \"redirect search\");\n searchSnapshot = { mode: search.mode };\n } else {\n throw new TypeError(\"Invalid redirect search policy\");\n }\n\n const fragment = ownRecord(redirect.fragment, \"Redirect fragment\");\n\n if (fragment.mode === \"replace\") {\n checkKeys(fragment, new Set([\"mode\", \"value\"]), \"redirect fragment\");\n\n if (typeof fragment.value !== \"string\" || !target.fragments.includes(fragment.value)) {\n throw new TypeError(\"Redirect fragment must belong to target declaration\");\n }\n } else if (fragment.mode === \"preserve\" || fragment.mode === \"drop\") {\n checkKeys(fragment, new Set([\"mode\"]), \"redirect fragment\");\n } else {\n throw new TypeError(\"Invalid redirect fragment policy\");\n }\n\n return Object.freeze({\n to: redirect.to,\n params: Object.freeze(mapping),\n search: Object.freeze(searchSnapshot),\n fragment: Object.freeze({ ...fragment }),\n });\n}\n\n/**\n * Declares a nominal typed route without executing codecs or native callbacks.\n *\n * @remarks\n * Paths are decoded authored text, not URLs: use `\"\"` for root/pathless nodes,\n * `$name` for a scalar segment and terminal `$name[]` for a zero-or-more\n * catchall. Repeated local scalar names reuse one value. Leading/trailing or\n * repeated slashes, dot segments and Angular `:name`/wildcard notation are invalid.\n *\n * Parents compose effective params/search transitively, including through\n * pathless nodes. Children cannot redeclare ancestor-owned keys or have a\n * catchall parent. Fragment names belong only to this declaration.\n * The route and copied containers are shallow-frozen; application codecs,\n * callbacks, providers and opaque values retain identity and are not deep-frozen.\n *\n * For generation, author a direct default export of this call with a literal\n * path and inline config. Parent and redirect targets must be direct default\n * imports of admitted declarations. Angular owns activation and navigation;\n * declaration alone does not register a route with Angular.\n *\n * @param path - The literal local path, relative to the authored parent.\n * @param config - Local codecs, parent, fragments and supported native behavior.\n * Structural Angular options such as children, component and matcher are\n * generator-owned and cannot be overridden.\n * @returns A frozen route preserving inferred effective input and local data types.\n * @throws TypeError for invalid paths/configuration, missing or extra local\n * codecs, fallback codecs in path params, inherited key conflicts, or\n * nongenuine parent/redirect routes.\n *\n * @example\n * ```ts\n * const product = defineRoute(\"products/$productId\", {\n * params: { productId: numberParam },\n * search: { tab: withFallback(enumParam([\"details\", \"reviews\"]), \"details\") },\n * fragments: [\"summary\", \"reviews\"],\n * });\n * ```\n */\nexport function defineRoute<\n const Path extends string,\n Parent extends AnyRoute | undefined = undefined,\n Params extends Record<string, PathCodec> = {},\n Search extends CodecMap = {},\n Resolvers extends Record<string, (...args: any[]) => unknown> = {},\n const Fragments extends readonly string[] = [],\n Target extends AnyRoute | undefined = undefined,\n ReplacementKeys extends keyof SearchOf<NoInfer<Target>> = never,\n>(\n path: Path & ValidPath<Path>,\n config: RouteConfig<Path, Parent, Params, Search, Resolvers, Fragments, Target, ReplacementKeys>,\n): Route<\n Path,\n EffectiveParams<Path, Params, Parent>,\n EffectiveSearch<Search, Parent>,\n Resolvers,\n Fragments[number],\n CatchallName<Path> extends never ? false : true\n>;\n\nexport function defineRoute(path: unknown, config: unknown): AnyRoute {\n const supplied = ownRecord(config, \"Route config\");\n\n checkKeys(supplied, configKeys, \"route config\");\n\n const localSegments = parsePath(path);\n let parent: AnyRoute | undefined;\n let inherited: RouteMetadata | undefined;\n\n if (has(supplied, \"parent\")) {\n inherited = routeMetadata(supplied.parent);\n parent = supplied.parent as AnyRoute;\n\n for (const segment of inherited.segments) {\n if (segment.kind === \"catchall\") {\n throw new TypeError(\"Catchall declarations cannot have children\");\n }\n }\n }\n\n const localNames = new Set<string>();\n\n for (const segment of localSegments) {\n if (segment.kind !== \"static\") {\n localNames.add(segment.name);\n }\n }\n\n let localParams: Readonly<Record<string, ParamCodec<any>>> = Object.freeze(Object.create(null));\n\n if (localNames.size === 0) {\n if (has(supplied, \"params\")) {\n throw new TypeError(\"Static paths cannot declare params\");\n }\n } else {\n localParams = copyCodecs(supplied.params, true);\n checkKeys(localParams, localNames, \"local params\");\n\n for (const key of localNames) {\n if (!has(localParams, key)) {\n throw new TypeError(`Missing local codec: ${key}`);\n }\n\n if (inherited && has(inherited.params, key)) {\n throw new TypeError(`Inherited param already owned: ${key}`);\n }\n }\n }\n\n let localSearch: Readonly<Record<string, ParamCodec<any>>> = Object.freeze(Object.create(null));\n\n if (has(supplied, \"search\")) {\n localSearch = copyCodecs(supplied.search, false);\n }\n\n for (const key of Object.keys(localSearch)) {\n if (inherited && has(inherited.search, key)) {\n throw new TypeError(`Inherited search already owned: ${key}`);\n }\n }\n\n const retained: Record<string, unknown> = { ...supplied };\n const result: {\n path: string;\n resolve?: Readonly<Record<PropertyKey, unknown>>;\n runGuardsAndResolvers?: unknown;\n } = { path: path as string };\n\n if (has(supplied, \"resolve\")) {\n const resolve = ownRecord(supplied.resolve, \"Resolvers\", true) as Record<PropertyKey, unknown>;\n const copied: Record<PropertyKey, unknown> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolve)) {\n if (key === identityKey || typeof resolve[key] !== \"function\") {\n throw new TypeError(`Invalid resolver: ${String(key)}`);\n }\n\n copied[key] = resolve[key];\n }\n\n result.resolve = Object.freeze(copied);\n retained.resolve = result.resolve;\n }\n\n if (has(supplied, \"runGuardsAndResolvers\")) {\n const policy = supplied.runGuardsAndResolvers;\n\n if (typeof policy !== \"function\" && (typeof policy !== \"string\" || !policies.has(policy))) {\n throw new TypeError(\"Invalid native rerun policy\");\n }\n\n result.runGuardsAndResolvers = policy;\n }\n\n for (const key of [\"canActivate\", \"canActivateChild\", \"canMatch\", \"canDeactivate\", \"providers\"]) {\n if (!has(supplied, key)) {\n continue;\n }\n\n const list = supplied[key];\n\n if (!Array.isArray(list)) {\n throw new TypeError(`${key} must be an array`);\n }\n\n if (key === \"canActivate\" || key === \"canActivateChild\" || key === \"canMatch\") {\n for (const callback of list) {\n if (typeof callback !== \"function\") {\n throw new TypeError(`${key} entries must be callbacks`);\n }\n }\n } else if (key === \"canDeactivate\") {\n for (const guard of list) {\n if (\n guard === null ||\n (typeof guard !== \"function\" && typeof guard !== \"object\" && typeof guard !== \"string\")\n ) {\n throw new TypeError(\"canDeactivate entries must be native callbacks or tokens\");\n }\n }\n }\n\n retained[key] = Object.freeze([...list]);\n }\n\n if (has(supplied, \"onInvalidParams\")) {\n if (typeof supplied.onInvalidParams !== \"function\") {\n throw new TypeError(\"onInvalidParams must be a callback\");\n }\n\n if (localNames.size === 0) {\n throw new TypeError(\"onInvalidParams requires local path params\");\n }\n }\n\n if (\n has(supplied, \"title\") &&\n typeof supplied.title !== \"string\" &&\n typeof supplied.title !== \"function\"\n ) {\n throw new TypeError(\"Title must be a string or a callback\");\n }\n\n if (has(supplied, \"data\")) {\n const data = ownRecord(supplied.data, \"Static data\", true);\n\n if (has(data, identityKey)) {\n throw new TypeError(\"Static data cannot set generated identity\");\n }\n\n retained.data = Object.freeze({ ...data });\n }\n\n const fragments: string[] = [];\n\n if (has(supplied, \"fragments\")) {\n if (!Array.isArray(supplied.fragments)) {\n throw new TypeError(\"Fragments must be a string list\");\n }\n\n for (const name of supplied.fragments) {\n if (typeof name !== \"string\") {\n throw new TypeError(\"Fragment names must be strings\");\n }\n\n fragments.push(name);\n }\n }\n\n retained.fragments = Object.freeze(fragments);\n retained.params = localParams;\n retained.search = localSearch;\n\n const metadata: RouteMetadata = {\n parent,\n localSegments,\n segments: Object.freeze([...(inherited?.segments ?? []), ...localSegments]),\n localParams,\n localSearch,\n params: Object.freeze({ ...inherited?.params, ...localParams }),\n search: Object.freeze({ ...inherited?.search, ...localSearch }),\n fragments: retained.fragments as readonly string[],\n config: retained,\n };\n\n if (has(supplied, \"redirect\")) {\n if (\n has(supplied, \"canActivate\") ||\n has(supplied, \"canMatch\") ||\n has(supplied, \"onInvalidParams\")\n ) {\n throw new TypeError(\"Redirect cannot declare own canActivate, canMatch or onInvalidParams\");\n }\n\n retained.redirect = snapshotRedirect(supplied.redirect, metadata);\n }\n\n Object.freeze(retained);\n routes.set(result, Object.freeze(metadata));\n\n return Object.freeze(result) as AnyRoute;\n}\n","import type { ParamCodec } from \"./codecs.js\";\nimport { ownRecord, checkKeys, has } from \"./records.js\";\nimport { routeMetadata } from \"./route.js\";\nimport type { AnyRoute, SearchOf, UrlValues } from \"./types.js\";\n\nfunction encode(value: string): string {\n return encodeURIComponent(value).replaceAll(\"(\", \"%28\").replaceAll(\")\", \"%29\");\n}\n\nfunction stringify(codec: ParamCodec<any>, value: unknown, path: boolean): string {\n const text = codec.stringify(value);\n\n if (typeof text !== \"string\") {\n throw new TypeError(\"Codec stringify must return a string\");\n }\n\n if (path && (text === \"\" || text === \".\" || text === \"..\")) {\n throw new TypeError(\"Path output cannot be empty, dot or dotdot\");\n }\n\n return encode(text);\n}\n\n/**\n * Synchronously serializes a route's explicit values into a root-relative URL.\n *\n * @remarks\n * Includes inherited path/search declarations, but only this route's fragment\n * names. Every effective path value must be supplied; any search key may be\n * omitted. Searchless/paramless routes forbid those records. Catchalls require readonly arrays, including a valid empty array.\n * Values are never taken from a current navigation.\n *\n * Stringifies without calling parsers, guards, resolvers or redirects. Static\n * segments and logical values are component-encoded (also escaping parentheses),\n * so a dynamic slash becomes `%2F`. Search keys are globally sorted; omitted\n * and `undefined` values are left out. An empty effective path produces `/`.\n * Redirect declarations serialize their source URL, not their redirect target.\n *\n * @param route - A genuine declaration from this physical package instance,\n * not a generated destination, spread/copy or structural lookalike.\n * @param values - Explicit destination-typed params, search and optional fragment.\n * Pass an empty object when the route needs no values.\n * @returns A root-relative URL string, typed `` `/${string}` ``; this does not navigate or\n * return a UrlTree.\n * @throws TypeError for invalid routes/records, missing or unknown keys,\n * undeclared fragments, nonarray catchalls, nonstring codec output, or empty/dot\n * path output. Application stringifier failures propagate unchanged.\n * @throws URIError for ill-formed Unicode in a serialized value.\n *\n * @example\n * ```ts\n * const product = defineRoute(\"products/$productId\", {\n * params: { productId: numberParam },\n * fragments: [\"summary\"],\n * });\n * createUrl(product, { params: { productId: 42 }, fragment: \"summary\" });\n * // /products/42#summary\n * ```\n */\nexport function createUrl<\n Target extends AnyRoute,\n SearchKeys extends keyof SearchOf<NoInfer<Target>> = never,\n>(route: Target, values: UrlValues<NoInfer<Target>, SearchKeys>): `/${string}`;\n\nexport function createUrl(route: unknown, values: unknown): `/${string}` {\n const metadata = routeMetadata(route);\n const options = ownRecord(values, \"URL options\");\n\n checkKeys(options, new Set([\"params\", \"search\", \"fragment\"]), \"URL options\");\n\n const paramKeys = Object.keys(metadata.params);\n let params: Record<string, unknown> = Object.create(null);\n\n if (paramKeys.length === 0) {\n if (has(options, \"params\")) {\n throw new TypeError(\"Route has no path params\");\n }\n } else {\n params = ownRecord(options.params, \"Path values\");\n checkKeys(params, new Set(paramKeys), \"path values\");\n\n for (const key of paramKeys) {\n if (!has(params, key)) {\n throw new TypeError(`Missing path value: ${key}`);\n }\n }\n }\n\n const searchKeys = Object.keys(metadata.search).sort();\n let search: Record<string, unknown> = Object.create(null);\n\n if (searchKeys.length === 0) {\n if (has(options, \"search\")) {\n throw new TypeError(\"Route has no search declarations\");\n }\n } else {\n if (has(options, \"search\")) {\n search = ownRecord(options.search, \"Search values\");\n }\n\n checkKeys(search, new Set(searchKeys), \"search values\");\n }\n\n if (has(options, \"fragment\")) {\n if (typeof options.fragment !== \"string\" || !metadata.fragments.includes(options.fragment)) {\n throw new TypeError(\"Fragment must belong to this declaration\");\n }\n }\n\n // Check all cardinalities before invoking application stringifiers.\n for (const segment of metadata.segments) {\n if (segment.kind === \"catchall\" && !Array.isArray(params[segment.name])) {\n throw new TypeError(`Catchall requires an array: ${segment.name}`);\n }\n }\n\n const parts: string[] = [];\n\n for (const segment of metadata.segments) {\n if (segment.kind === \"static\") {\n parts.push(encode(segment.text));\n } else if (segment.kind === \"scalar\") {\n parts.push(stringify(metadata.params[segment.name], params[segment.name], true));\n } else {\n for (const value of params[segment.name] as readonly unknown[]) {\n parts.push(stringify(metadata.params[segment.name], value, true));\n }\n }\n }\n\n let url: `/${string}` = `/${parts.join(\"/\")}`;\n const query: string[] = [];\n\n for (const key of searchKeys) {\n const value = search[key];\n\n if (!has(search, key) || value === undefined) {\n continue;\n }\n\n query.push(`${encode(key)}=${stringify(metadata.search[key], value, false)}`);\n }\n\n if (query.length > 0) {\n url = `${url}?${query.join(\"&\")}`;\n }\n\n if (has(options, \"fragment\")) {\n url = `${url}#${encode(options.fragment as string)}`;\n }\n\n return url;\n}\n"],"mappings":"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"}
@@ -341,7 +341,7 @@ function injectGeneratedRoute(set, id) {
341
341
  if (typeof selector === "string") {
342
342
  if (selector !== ".") {
343
343
  if (Object.hasOwn(set.absolute, selector)) target = set.absolute[selector];
344
- else if (Object.hasOwn(set.relative[id], selector)) target = set.relative[id][selector];
344
+ else if (selector === ".." && Object.hasOwn(set.parents, id)) target = set.parents[id];
345
345
  else throw new TypeError(`Unknown generated selector: ${selector}`);
346
346
  }
347
347
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"loozo-angular-router-_generated.mjs","names":[],"sources":["../../_generated/src/inputs.ts","../../_generated/src/callbacks.ts","../../_generated/src/handle.ts","../../_generated/src/index.ts"],"sourcesContent":["import type { ActivatedRouteSnapshot, PartialMatchRouteSnapshot } from \"@angular/router\";\nimport { codecFallback, routeMetadata, type AnyRoute } from \"@loozo/angular-router/_core\";\n\nexport interface RecordBinding {\n readonly definition: () => AnyRoute;\n readonly owners: readonly string[];\n}\nexport interface RouteSet {\n readonly records: Readonly<Record<string, RecordBinding>>;\n readonly destinations: Readonly<Record<string, () => AnyRoute>>;\n readonly absolute: Readonly<Record<string, string>>;\n readonly relative: Readonly<Record<string, Readonly<Record<string, string>>>>;\n}\nexport interface Parsed {\n readonly params: Readonly<Record<string, unknown>>;\n readonly search: Readonly<Record<string, unknown>>;\n}\nexport interface Job {\n readonly key: string;\n readonly raws: readonly string[];\n readonly array: boolean;\n readonly codec: { parse(raw: string): unknown };\n}\n\nexport function hasIdentity(\n snapshot: Pick<ActivatedRouteSnapshot, \"routeConfig\">,\n id: string,\n): boolean {\n const data = snapshot.routeConfig?.data;\n\n return (\n !!data &&\n Object.hasOwn(data, \"__loozoAngularRouterRouteId\") &&\n data.__loozoAngularRouterRouteId === id\n );\n}\n\nexport function assertIdentity(\n snapshot: Pick<ActivatedRouteSnapshot, \"routeConfig\">,\n id: string,\n): void {\n if (!hasIdentity(snapshot, id)) {\n throw new Error(`Generated route wiring identity mismatch: ${id}`);\n }\n}\n\n// Private: input errors are Errors with source/key/reason, not an exported class.\nclass InputError extends Error {\n readonly source = \"path\";\n\n constructor(\n readonly key: string,\n readonly reason: \"missing\" | \"repeated\" | \"invalid\",\n cause?: unknown,\n ) {\n super(`Invalid path input ${key}: ${reason}`, { cause });\n }\n}\n\nexport function validateRaw(\n key: string,\n raws: readonly unknown[],\n array: boolean,\n): asserts raws is readonly string[] {\n if (!array && raws.length === 0) {\n throw new InputError(key, \"missing\");\n }\n\n if (!array && raws.length > 1) {\n throw new InputError(key, \"repeated\");\n }\n\n if (raws.some((raw) => typeof raw !== \"string\")) {\n throw new InputError(key, \"invalid\", new TypeError(\"Raw input must be a decoded string\"));\n }\n}\n\n/**\n * Runs one parser. A throw is invalid input; a thenable is a programming error,\n * thrown as a TypeError so it fails the navigation instead of reading as invalid.\n */\nfunction parse(codec: Job[\"codec\"], raw: string): { value: unknown } | { cause: unknown } {\n let value: unknown;\n\n try {\n value = codec.parse(raw);\n } catch (cause) {\n return { cause };\n }\n\n if (\n value !== null &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n typeof (value as PromiseLike<unknown>).then === \"function\"\n ) {\n // Observe the stray result so its rejection can't surface as unhandled.\n Promise.resolve(value).catch(() => undefined);\n\n throw new TypeError(\"ParamCodec.parse must return its value synchronously, not a Promise\");\n }\n\n return { value };\n}\n\nexport function pathJobs(definition: AnyRoute, url: readonly { path: string }[]): Job[] {\n const metadata = routeMetadata(definition);\n const local = new Map<string, Job>();\n\n for (let index = 0; index < metadata.localSegments.length; index += 1) {\n const segment = metadata.localSegments[index];\n\n if (segment.kind === \"static\") {\n continue;\n }\n\n let raws: unknown[] = [];\n const array = segment.kind === \"catchall\";\n\n if (array) {\n raws = url.slice(index).map((value) => value.path);\n } else if (index < url.length) {\n raws = [url[index].path];\n }\n\n validateRaw(segment.name, raws, array);\n // Repeated local scalars intentionally use Angular's last positional occurrence.\n local.set(segment.name, {\n key: segment.name,\n raws,\n array,\n codec: metadata.localParams[segment.name],\n });\n }\n\n return [...local.values()];\n}\n\n/** Parses prechecked path jobs; the first codec failure is an input error. */\nexport function runPathJobs(jobs: readonly Job[]): Readonly<Record<string, unknown>> {\n const params: Record<string, unknown> = Object.create(null);\n\n for (const job of jobs) {\n const values: unknown[] = [];\n\n for (const raw of job.raws) {\n const result = parse(job.codec, raw);\n\n if (\"cause\" in result) {\n throw new InputError(job.key, \"invalid\", result.cause);\n }\n\n values.push(result.value);\n }\n\n if (job.array) {\n params[job.key] = Object.freeze(values);\n } else {\n params[job.key] = values[0];\n }\n }\n\n return Object.freeze(params);\n}\n\n/**\n * Parses a declaration's effective search. It never fails on input: a missing,\n * repeated or invalid value reads as the key's fallback, or leaves it absent.\n */\nexport function parseSearch(\n definition: AnyRoute,\n snapshot: Pick<ActivatedRouteSnapshot, \"queryParamMap\">,\n): Readonly<Record<string, unknown>> {\n const metadata = routeMetadata(definition);\n const search: Record<string, unknown> = Object.create(null);\n\n for (const key of Object.keys(metadata.search)) {\n const codec = metadata.search[key];\n const raws: unknown[] = snapshot.queryParamMap.getAll(key);\n\n if (raws.length === 1 && typeof raws[0] === \"string\") {\n const result = parse(codec, raws[0]);\n\n if (\"value\" in result) {\n search[key] = result.value;\n\n continue;\n }\n }\n\n const fallback = codecFallback(codec);\n\n if (fallback) {\n search[key] = fallback.value;\n }\n }\n\n return Object.freeze(search);\n}\n\ntype Outcome<Value> = { readonly value: Value } | { readonly error: unknown };\ntype Cache<Value> = WeakMap<object, WeakMap<object, Outcome<Value>>>;\n\nconst full: Cache<Parsed> = new WeakMap();\nconst paths: Cache<Readonly<Record<string, unknown>>> = new WeakMap();\nconst matching: Cache<Parsed | undefined> = new WeakMap();\n\n// One result or failure per exact declaration and snapshot, shared by every reader.\nfunction memo<Value>(\n cache: Cache<Value>,\n definition: AnyRoute,\n snapshot: object,\n run: () => Value,\n): Value {\n let snapshots = cache.get(definition);\n\n if (!snapshots) {\n snapshots = new WeakMap();\n cache.set(definition, snapshots);\n }\n\n let outcome = snapshots.get(snapshot);\n\n if (!outcome) {\n try {\n outcome = { value: run() };\n } catch (error) {\n outcome = { error };\n }\n\n snapshots.set(snapshot, outcome);\n }\n\n if (\"error\" in outcome) {\n throw outcome.error;\n }\n\n return outcome.value;\n}\n\n/** The effective inputs of a complete snapshot, shared by guards, resolvers and handles. */\nexport function parseInputs(set: RouteSet, id: string, snapshot: ActivatedRouteSnapshot): Parsed {\n assertIdentity(snapshot, id);\n\n const binding = set.records[id];\n\n return memo(full, binding.definition(), snapshot, () => {\n const jobs: Job[] = [];\n\n for (const ownerId of binding.owners) {\n const definition = set.records[ownerId].definition();\n\n // Pathless/static owners contribute no positional input. Effective search belongs\n // to this complete future record; inherited data is never positional authority.\n if (!routeMetadata(definition).localSegments.some((segment) => segment.kind !== \"static\")) {\n continue;\n }\n\n const owner = [...snapshot.pathFromRoot]\n .reverse()\n .find((record) => hasIdentity(record, ownerId));\n\n if (!owner) {\n throw new Error(`Generated route ancestor missing: ${ownerId}`);\n }\n\n assertIdentity(owner, ownerId);\n jobs.push(...pathJobs(definition, owner.url));\n }\n\n const params = runPathJobs(jobs);\n\n return Object.freeze({ params, search: parseSearch(binding.definition(), snapshot) });\n });\n}\n\n/**\n * Parses a matching candidate's own path params only. Angular passes one partial\n * snapshot to all of a candidate's canMatch guards, so they share this result.\n *\n * @returns An input error when a param is invalid; throws only programming errors.\n */\nexport function pathInputs(\n set: RouteSet,\n id: string,\n snapshot: PartialMatchRouteSnapshot,\n): { params: Readonly<Record<string, unknown>> } | { error: Error } {\n assertIdentity(snapshot, id);\n\n const definition = set.records[id].definition();\n\n try {\n return {\n params: memo(paths, definition, snapshot, () =>\n runPathJobs(pathJobs(definition, snapshot.url)),\n ),\n };\n } catch (error) {\n if (error instanceof InputError) {\n return { error };\n }\n\n throw error;\n }\n}\n\n/**\n * Local path params plus effective search for a candidate's canMatch guards, the\n * generated one included, or undefined when the path params fail: the generated\n * guard owns that outcome.\n */\nexport function matchingInputs(\n set: RouteSet,\n id: string,\n snapshot: PartialMatchRouteSnapshot,\n): Parsed | undefined {\n const definition = set.records[id].definition();\n\n return memo(matching, definition, snapshot, () => {\n const path = pathInputs(set, id, snapshot);\n\n // Search parses only once the path matches: a candidate the path rules out runs no\n // search codecs.\n if (\"error\" in path) {\n return undefined;\n }\n\n return Object.freeze({ params: path.params, search: parseSearch(definition, snapshot) });\n });\n}\n","import { inject } from \"@angular/core\";\nimport {\n Router,\n RedirectCommand,\n UrlTree,\n type Route,\n type ActivatedRouteSnapshot,\n type RouterStateSnapshot,\n type GuardResult,\n type CanActivateFn,\n type CanActivateChildFn,\n type CanMatchFn,\n type ResolveFn,\n type RedirectFunction,\n} from \"@angular/router\";\nimport { from, isObservable, map, type ObservableInput } from \"rxjs\";\nimport { routeMetadata, type AnyRoute } from \"@loozo/angular-router/_core\";\nimport {\n hasIdentity,\n parseInputs,\n matchingInputs,\n pathInputs,\n runPathJobs,\n validateRaw,\n type Job,\n type RouteSet,\n} from \"./inputs.js\";\n\n// Parsing is synchronous, so every adapter calls its callback in the same call Angular\n// made: Angular's injection context is still active and inject() works at entry.\nexport function callbacks(\n set: RouteSet,\n id: string,\n): Pick<Route, \"canActivate\" | \"canActivateChild\" | \"canMatch\" | \"resolve\" | \"title\"> {\n const metadata = routeMetadata(set.records[id].definition());\n const config = metadata.config;\n const result: Pick<Route, \"canActivate\" | \"canActivateChild\" | \"canMatch\" | \"resolve\" | \"title\"> =\n {};\n const activate = config.canActivate as readonly ((...args: any[]) => any)[] | undefined;\n\n if (activate) {\n result.canActivate = activate.map(\n (callback): CanActivateFn =>\n (snapshot, state) =>\n callback(parseInputs(set, id, snapshot), snapshot, state),\n );\n }\n\n const children = config.canActivateChild as readonly ((...args: any[]) => any)[] | undefined;\n\n if (children) {\n result.canActivateChild = children.map(\n (callback): CanActivateChildFn =>\n (child, state) => {\n let parent: ActivatedRouteSnapshot | undefined;\n\n // The native ancestry includes child itself; only proper ancestors can declare this guard.\n for (let index = child.pathFromRoot.length - 2; index >= 0; index -= 1) {\n const ancestor = child.pathFromRoot[index];\n\n if (hasIdentity(ancestor, id)) {\n parent = ancestor;\n\n break;\n }\n }\n\n if (!parent) {\n throw new Error(`Generated guard ancestor missing: ${id}`);\n }\n\n return callback(parseInputs(set, id, parent), child, state);\n },\n );\n }\n\n const matching = config.canMatch as readonly ((...args: any[]) => any)[] | undefined;\n const canMatch: CanMatchFn[] = [];\n\n // Local path params decide whether this record matches. Angular runs every canMatch\n // guard concurrently and prefers the first non-true result in array order.\n if (\n metadata.localSegments.some((segment) => segment.kind !== \"static\") ||\n Object.keys(metadata.search).length > 0\n ) {\n const handler = config.onInvalidParams as ((...args: any[]) => unknown) | undefined;\n\n canMatch.push((route, segments, snapshot) => {\n const path = pathInputs(set, id, snapshot);\n\n if (!(\"error\" in path)) {\n // Search never decides the match, but Angular runs this guard on every navigation,\n // query-only ones included, so a thenable search parse fails it here.\n matchingInputs(set, id, snapshot);\n\n return true;\n }\n\n if (!handler) {\n return false;\n }\n\n const decision = handler(path.error, route, segments, snapshot);\n\n if (isObservable(decision) || isPromiseResult(decision)) {\n return from(decision as ObservableInput<unknown>).pipe(map(invalidParamsResult));\n }\n\n return invalidParamsResult(decision);\n });\n }\n\n if (matching) {\n for (const callback of matching) {\n canMatch.push((route, segments, snapshot) => {\n const inputs = matchingInputs(set, id, snapshot);\n\n // Invalid path params: the generated guard ahead of this one decides.\n if (inputs === undefined) {\n return false;\n }\n\n return callback(inputs, route, segments, snapshot);\n });\n }\n }\n\n if (canMatch.length > 0) {\n result.canMatch = canMatch;\n }\n\n const resolvers = config.resolve as\n | Record<\n PropertyKey,\n (inputs: unknown, snapshot: ActivatedRouteSnapshot, state: RouterStateSnapshot) => any\n >\n | undefined;\n\n if (resolvers) {\n const resolve: Record<PropertyKey, ResolveFn<unknown>> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolvers)) {\n resolve[key] = (snapshot, state) =>\n resolvers[key](parseInputs(set, id, snapshot), snapshot, state);\n }\n\n result.resolve = resolve;\n }\n\n const title = config.title as\n | string\n | ((inputs: unknown, snapshot: ActivatedRouteSnapshot, state: RouterStateSnapshot) => any)\n | undefined;\n\n // Angular runs a title callback as a resolver, so it's adapted like one.\n if (typeof title === \"function\") {\n result.title = (snapshot, state) => title(parseInputs(set, id, snapshot), snapshot, state);\n } else if (title !== undefined) {\n result.title = title;\n }\n\n return result;\n}\n\nfunction isPromiseResult(value: unknown): value is PromiseLike<unknown> {\n return !!value && typeof (value as PromiseLike<unknown>).then === \"function\";\n}\n\n// Invalid params can't match, so a handler may only refuse or redirect.\nfunction invalidParamsResult(decision: unknown): GuardResult {\n if (decision === false || decision instanceof UrlTree || decision instanceof RedirectCommand) {\n return decision;\n }\n\n throw new TypeError(\"onInvalidParams must return false, a UrlTree or a RedirectCommand\");\n}\n\nexport function redirect(definition: () => AnyRoute): RedirectFunction {\n return (snapshot) => {\n const router = inject(Router);\n const source = routeMetadata(definition());\n const config = source.config.redirect as {\n to: AnyRoute;\n params: Record<string, string>;\n search: { mode: string; values?: Record<string, unknown> };\n fragment: { mode: string; value?: string };\n };\n const target = routeMetadata(config.to);\n const raw = new Map<string, { values: string[]; array: boolean }>();\n\n for (let index = 0; index < source.segments.length; index += 1) {\n const segment = source.segments[index];\n\n if (segment.kind === \"scalar\") {\n raw.set(segment.name, {\n values: snapshot.url.slice(index, index + 1).map((value) => value.path),\n array: false,\n });\n } else if (segment.kind === \"catchall\") {\n raw.set(segment.name, {\n values: snapshot.url.slice(index).map((value) => value.path),\n array: true,\n });\n }\n }\n\n const jobs: Job[] = [];\n\n // Only mapped source params are parsed, each cardinality checked before any parser runs.\n for (const key of new Set(Object.values(config.params))) {\n const input = raw.get(key);\n const raws = input?.values ?? [];\n const array = input?.array ?? false;\n\n validateRaw(key, raws, array);\n jobs.push({ key, raws, array, codec: source.params[key] });\n }\n\n // A failure fails the navigation: a redirect record has no matching guard to fall through.\n const logical = runPathJobs(jobs);\n const params: Record<string, unknown> = Object.create(null);\n\n for (const [key, sourceKey] of Object.entries(config.params)) {\n params[key] = logical[sourceKey];\n }\n\n const path = createUrlForPath(config.to, params);\n const replacement: Record<string, string> = Object.create(null);\n\n if (config.search.mode === \"replace\") {\n const values = config.search.values!;\n\n for (const key of Object.keys(target.search).sort()) {\n if (!Object.hasOwn(values, key) || values[key] === undefined) {\n continue;\n }\n\n const raw = target.search[key].stringify(values[key]);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(`Redirect search codec must stringify to a string: ${key}`);\n }\n\n replacement[key] = raw;\n }\n }\n\n // No native conversion before source codecs and destination stringification succeed.\n const tree = router.parseUrl(path);\n\n if (config.search.mode === \"preserve\") {\n tree.queryParams = { ...snapshot.queryParams };\n } else if (config.search.mode === \"replace\") {\n tree.queryParams = replacement;\n }\n\n if (config.fragment.mode === \"preserve\") {\n tree.fragment = snapshot.fragment;\n } else if (config.fragment.mode === \"replace\") {\n tree.fragment = config.fragment.value!;\n }\n\n return tree;\n };\n}\n\nfunction createUrlForPath(definition: AnyRoute, params: Record<string, unknown>): string {\n const metadata = routeMetadata(definition);\n const parts: string[] = [];\n\n function encode(raw: string): string {\n if (raw === \"\" || raw === \".\" || raw === \"..\") {\n throw new TypeError(\"Invalid redirect path value\");\n }\n\n return encodeURIComponent(raw).replace(/\\(/g, \"%28\").replace(/\\)/g, \"%29\");\n }\n\n for (const segment of metadata.segments) {\n if (segment.kind === \"static\") {\n parts.push(encode(segment.text));\n } else if (segment.kind === \"scalar\") {\n const raw = metadata.params[segment.name].stringify(params[segment.name]);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(\"Redirect codec must stringify to a string\");\n }\n\n parts.push(encode(raw));\n } else {\n const values = params[segment.name];\n\n if (!Array.isArray(values)) {\n throw new TypeError(\"Redirect catchall requires an array\");\n }\n\n for (const value of values) {\n const raw = metadata.params[segment.name].stringify(value);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(\"Redirect codec must stringify to a string\");\n }\n\n parts.push(encode(raw));\n }\n }\n }\n\n return `/${parts.join(\"/\")}`;\n}\n","import { DestroyRef, computed, inject, signal, type Signal } from \"@angular/core\";\nimport { ActivatedRoute, Router, type ActivatedRouteSnapshot } from \"@angular/router\";\nimport { routeMetadata } from \"@loozo/angular-router/_core\";\nimport { merge } from \"rxjs\";\nimport { assertIdentity, parseInputs, type RouteSet } from \"./inputs.js\";\n\n/**\n * Signals of the route's committed snapshot. Angular replaces ActivatedRoute.snapshot\n * only when a navigation activates, so a pending, cancelled or failed navigation\n * leaves the values alone; params, search and data change together, from one snapshot.\n */\nexport function observeRoute(\n set: RouteSet,\n id: string,\n): {\n params: Signal<Readonly<Record<string, unknown>>>;\n search: Signal<Readonly<Record<string, unknown>>>;\n data: Signal<Readonly<Record<PropertyKey, unknown>>>;\n} {\n const activated = inject(ActivatedRoute);\n const router = inject(Router);\n\n assertIdentity(activated.snapshot, id);\n\n const snapshot = signal<ActivatedRouteSnapshot>(activated.snapshot);\n // Activation replaces the snapshot, then emits the route's changed observables, then\n // ActivationEnd. Following both keeps reads current inside subscribers registered after\n // the handle; router events cover a new snapshot whose values are all equal.\n const subscription = merge(\n activated.queryParams,\n activated.fragment,\n activated.params,\n activated.url,\n activated.data,\n router.events,\n ).subscribe(() => {\n snapshot.set(activated.snapshot);\n });\n\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n\n // Shares the parse of guards and resolvers for the same snapshot. An error here\n // means a codec rejected a value it accepted while matching, and reading rethrows it.\n const inputs = computed(() => parseInputs(set, id, snapshot()));\n const resolvers = routeMetadata(set.records[id].definition()).config.resolve ?? {};\n\n return {\n params: computed(() => inputs().params),\n search: computed(() => inputs().search),\n data: computed(() => {\n const data = snapshot().data;\n const own: Record<PropertyKey, unknown> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolvers)) {\n if (Object.hasOwn(data, key)) {\n own[key] = data[key];\n }\n }\n\n return Object.freeze(own);\n }),\n };\n}\n","export { callbacks, redirect } from \"./callbacks.js\";\nexport { assertIdentity, parseInputs } from \"./inputs.js\";\nexport type { RecordBinding, RouteSet } from \"./inputs.js\";\n\nimport { inject, type Signal } from \"@angular/core\";\nimport { Router, type UrlTree } from \"@angular/router\";\nimport {\n createUrl,\n routeMetadata,\n type AnyRoute,\n type ParamsOf,\n type SearchOf,\n type UrlValues,\n} from \"@loozo/angular-router/_core\";\nimport { observeRoute } from \"./handle.js\";\nimport type { RouteSet } from \"./inputs.js\";\n\ndeclare const destinationBrand: unique symbol;\n\n/**\n * An inert nominal reference exported as `destination` by a route-local facade.\n *\n * @remarks\n * Use the exported object with a handle's link/navigate methods; no injection\n * context or target activation is needed. It selects its exact declaration,\n * not a canonical pathless winner. Only references from the caller's generated\n * set are accepted. Copies, spreads, fakes and authored routes are not references.\n * Do not construct this type or pass it to the root createUrl function.\n *\n * @typeParam Target - The referenced route's input and fragment schema.\n * @typeParam Set - The generator's nominal route-set identity.\n * @typeParam Id - The exact generated declaration identity.\n */\nexport declare class Destination<\n Target extends AnyRoute,\n Set = unknown,\n Id extends string = string,\n> {\n // Type-only identity, intentionally not read; object spreads must lose this member.\n // oxlint-disable-next-line no-unused-private-class-members\n readonly #nominal: void;\n /** Type-only nominal brand carrying the reference's identity; not populated at runtime. */\n readonly [destinationBrand]: {\n /** Type-only: the referenced route's input and fragment schema. */\n readonly target: Target;\n /** Type-only: the generator's nominal route-set identity. */\n readonly set: Set;\n /** Type-only: the exact generated declaration identity. */\n readonly id: Id;\n };\n}\n\nconst destinations = new WeakMap<object, { getSet: () => RouteSet; id: string }>();\n\nexport function createDestination<Target extends AnyRoute, Set, Id extends string>(\n getSet: () => RouteSet,\n id: Id,\n): Destination<Target, Set, Id> {\n const destination = Object.freeze({});\n\n destinations.set(destination, { getSet, id });\n\n return destination as Destination<Target, Set, Id>;\n}\n\ntype DataOf<Target> = Target extends { readonly __data?: infer Data } ? Readonly<Data> : never;\ntype IsUnion<Value, Whole = Value> = Value extends unknown\n ? [Whole] extends [Value]\n ? false\n : true\n : never;\n\n/**\n * The noncallable typed handle returned by a colocated `injectRoute()` facade.\n *\n * @remarks\n * Obtain it in an Angular injection context for the exact generated activated\n * record. Params, search and data are readonly Angular Signals of the route's\n * committed snapshot, with values from the first read. Data contains only local\n * resolver results, not static/ancestor data or title.\n *\n * While a navigation is pending, the signals keep the current snapshot's values;\n * when a navigation commits a new snapshot for this route, all three change\n * together. Cancellation, failure or a same-URL skip leaves them unchanged. For\n * pending-navigation UI, read Angular's `Router.currentNavigation()`. There is no\n * resolved-data cache. Reading params or search throws only when a path codec\n * rejects a value it accepted while matching, a programming error.\n *\n * Selectors are single known authored literals, not concrete URLs or string\n * unions. `.` is exact-current; other absolute/relative selections use generated\n * canonical targets. Relative climbs count URL-template segments, not parent\n * edges. Catchall origins permit exact-current, absolute and reference targets,\n * not depth-dependent relative traversal. Every call supplies all target values;\n * there is no current-value reuse, extras argument or implicit query merge.\n *\n * @typeParam Target - The bound declaration's schema.\n * @typeParam Selected - Statically admitted literal selectors and target schemas.\n * @typeParam Set - The generator's nominal route-set identity.\n * @typeParam References - Exact declarations addressable by same-set references.\n *\n * @example\n * ```ts\n * import { injectRoute } from \"./route.generated.js\";\n * import { destination as report } from \"../report/route.generated.js\";\n *\n * const route = injectRoute(); // Inside an Angular injection context.\n * const link = route.link(report, { params: { reportId: 42 } });\n * // Bind link to Angular RouterLink, or call route.navigate with the same values.\n * ```\n */\nexport interface Handle<\n Target extends AnyRoute,\n Selected extends Record<string, AnyRoute> = {},\n Set = unknown,\n References extends Record<string, AnyRoute> = {},\n> {\n /** Effective positional params of the committed snapshot; kept while a navigation is pending. */\n readonly params: Signal<Readonly<ParamsOf<Target>>>;\n /** Effective declared search, from the same snapshot as params; absent keys have no value or fallback. */\n readonly search: Signal<Readonly<SearchOf<Target>>>;\n /** Own native resolver results only, from the same snapshot as params. */\n readonly data: Signal<DataOf<Target>>;\n /**\n * Creates a native UrlTree for this exact declaration without navigating.\n *\n * @param values - Explicit effective params/search and optional own fragment.\n * @returns Router.parseUrl's result, suitable for Angular RouterLink.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n link<Keys extends keyof SearchOf<Target> = never>(values: UrlValues<Target, Keys>): UrlTree;\n /**\n * Creates a UrlTree for the exact bound declaration, not its pathless winner.\n *\n * @param selector - The exact-current literal `.`.\n * @param values - Explicit values for this declaration, with no current-input reuse.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n link<Keys extends keyof SearchOf<Target> = never>(\n selector: \".\",\n values: UrlValues<Target, Keys>,\n ): UrlTree;\n /**\n * Creates a UrlTree for a statically admitted absolute/relative authored selector.\n *\n * @param selector - A single known template literal, never a concrete URL.\n * @param values - The selected target's complete explicit values.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronously for unknown selectors or invalid URL values.\n */\n link<\n const Selector extends keyof Selected & string,\n Keys extends keyof SearchOf<NoInfer<Selected[Selector]>> = never,\n >(\n selector: Selector & (IsUnion<Selector> extends true ? never : unknown),\n values: UrlValues<NoInfer<Selected[Selector]>, Keys>,\n ): UrlTree;\n /**\n * Creates a UrlTree for a generated reference's own exact declaration.\n *\n * @param selector - A genuine destination exported by a facade in this route set.\n * @param values - The referenced declaration's complete explicit values.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronously for foreign/fake references or invalid URL values.\n */\n link<\n const Id extends keyof References & string,\n Keys extends keyof SearchOf<NoInfer<References[Id]>> = never,\n >(\n selector: Destination<NoInfer<References[Id]>, Set, Id> &\n (IsUnion<Id> extends true ? never : unknown),\n values: UrlValues<NoInfer<References[Id]>, Keys>,\n ): UrlTree;\n /**\n * Navigates to this exact declaration via Router.navigateByUrl.\n *\n * @param values - Explicit effective params/search and optional own fragment.\n * @returns Angular's identical Promise; Angular owns skips, redirects and failures.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n navigate<Keys extends keyof SearchOf<Target> = never>(\n values: UrlValues<Target, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to the exact bound declaration, not its pathless winner.\n *\n * @param selector - The exact-current literal `.`.\n * @param values - Explicit values for this declaration, with no current-input reuse.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n navigate<Keys extends keyof SearchOf<Target> = never>(\n selector: \".\",\n values: UrlValues<Target, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to a statically admitted absolute/relative authored selector.\n *\n * @param selector - A single known template literal, never a concrete URL.\n * @param values - The selected target's complete explicit values.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronously for unknown selectors or invalid URL values.\n */\n navigate<\n const Selector extends keyof Selected & string,\n Keys extends keyof SearchOf<NoInfer<Selected[Selector]>> = never,\n >(\n selector: Selector & (IsUnion<Selector> extends true ? never : unknown),\n values: UrlValues<NoInfer<Selected[Selector]>, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to a generated reference's own exact declaration.\n *\n * @param selector - A genuine destination exported by a facade in this route set.\n * @param values - The referenced declaration's complete explicit values.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronously for foreign/fake references or invalid URL values.\n */\n navigate<\n const Id extends keyof References & string,\n Keys extends keyof SearchOf<NoInfer<References[Id]>> = never,\n >(\n selector: Destination<NoInfer<References[Id]>, Set, Id> &\n (IsUnion<Id> extends true ? never : unknown),\n values: UrlValues<NoInfer<References[Id]>, Keys>,\n ): Promise<boolean>;\n}\n\nexport function nativeOptions(definition: AnyRoute): Record<string, unknown> {\n const config = routeMetadata(definition).config;\n const options: Record<string, unknown> = {};\n\n for (const key of [\"providers\", \"data\", \"canDeactivate\", \"runGuardsAndResolvers\"]) {\n if (Object.hasOwn(config, key)) {\n options[key] = config[key];\n }\n }\n\n return options;\n}\n\nexport function injectGeneratedRoute<\n Target extends AnyRoute,\n Selected extends Record<string, AnyRoute>,\n Set,\n References extends Record<string, AnyRoute>,\n>(set: RouteSet, id: string): Handle<Target, Selected, Set, References> {\n const router = inject(Router);\n const view = observeRoute(set, id);\n\n function url(args: readonly unknown[]): string {\n if (args.length !== 1 && args.length !== 2) {\n throw new TypeError(\"Expected values or a selected destination and values\");\n }\n\n let target = id;\n let values = args[0];\n\n if (args.length === 2) {\n const selector = args[0];\n\n values = args[1];\n\n if (typeof selector === \"string\") {\n if (selector !== \".\") {\n if (Object.hasOwn(set.absolute, selector)) {\n target = set.absolute[selector];\n } else if (Object.hasOwn(set.relative[id], selector)) {\n target = set.relative[id][selector];\n } else {\n throw new TypeError(`Unknown generated selector: ${selector}`);\n }\n }\n } else {\n if (typeof selector !== \"object\" || selector === null) {\n throw new TypeError(\"Expected a literal selector or genuine generated destination\");\n }\n\n const destination = destinations.get(selector);\n\n if (\n !destination ||\n destination.getSet() !== set ||\n !Object.hasOwn(set.records, destination.id)\n ) {\n throw new TypeError(\"Expected a destination from the same generated set\");\n }\n\n target = destination.id;\n }\n }\n\n return createUrl(set.destinations[target](), values as UrlValues<AnyRoute>);\n }\n\n return {\n params: view.params as Signal<Readonly<ParamsOf<Target>>>,\n search: view.search as Signal<Readonly<SearchOf<Target>>>,\n data: view.data as Signal<DataOf<Target>>,\n link: ((...args: unknown[]) => router.parseUrl(url(args))) as Handle<\n Target,\n Selected,\n Set,\n References\n >[\"link\"],\n navigate: ((...args: unknown[]) => router.navigateByUrl(url(args))) as Handle<\n Target,\n Selected,\n Set,\n References\n >[\"navigate\"],\n };\n}\n"],"mappings":";;;;AAwBA,SAAgB,YACd,UACA,IAAU;CAEV,MAAM,OAAO,SAAS,aAAa;CAEnC,OACE,CAAC,CAAC,QACF,OAAO,OAAO,MAAM,6BAA6B,KACjD,KAAK,gCAAgC;AAEzC;AAEA,SAAgB,eACd,UACA,IAAU;CAEV,IAAI,CAAC,YAAY,UAAU,EAAE,GAC3B,MAAM,IAAI,MAAM,6CAA6C,IAAI;AAErE;AAGA,IAAM,aAAN,cAAyB,MAAK;CAIjB;CACA;CAJF,SAAS;CAElB,YACW,KACA,QACT,OAAe;EAEf,MAAM,sBAAsB,IAAG,IAAK,UAAU,EAAE,MAAK,CAAE;EAJ9C,KAAA,MAAA;EACA,KAAA,SAAA;CAIX;AACD;AAED,SAAgB,YACd,KACA,MACA,OAAc;CAEd,IAAI,CAAC,SAAS,KAAK,WAAW,GAC5B,MAAM,IAAI,WAAW,KAAK,SAAS;CAGrC,IAAI,CAAC,SAAS,KAAK,SAAS,GAC1B,MAAM,IAAI,WAAW,KAAK,UAAU;CAGtC,IAAI,KAAK,MAAM,QAAQ,OAAO,QAAQ,QAAQ,GAC5C,MAAM,IAAI,WAAW,KAAK,2BAAW,IAAI,UAAU,oCAAoC,CAAC;AAE5F;AAMA,SAAS,MAAM,OAAqB,KAAW;CAC7C,IAAI;CAEJ,IAAI;EACF,QAAQ,MAAM,MAAM,GAAG;CACzB,SAAS,OAAO;EACd,OAAO,EAAE,MAAK;CAChB;CAEA,IACE,UAAU,SACT,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,OAAQ,MAA+B,SAAS,YAChD;EAEA,QAAQ,QAAQ,KAAK,CAAC,CAAC,YAAY,MAAS;EAE5C,MAAM,IAAI,UAAU,qEAAqE;CAC3F;CAEA,OAAO,EAAE,MAAK;AAChB;AAEA,SAAgB,SAAS,YAAsB,KAAgC;CAC7E,MAAM,WAAW,cAAc,UAAU;CACzC,MAAM,wBAAQ,IAAI,IAAG;CAErB,KAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,cAAc,QAAQ,SAAS,GAAG;EACrE,MAAM,UAAU,SAAS,cAAc;EAEvC,IAAI,QAAQ,SAAS,UACnB;EAGF,IAAI,OAAkB,CAAA;EACtB,MAAM,QAAQ,QAAQ,SAAS;EAE/B,IAAI,OACF,OAAO,IAAI,MAAM,KAAK,CAAC,CAAC,KAAK,UAAU,MAAM,IAAI;OAC5C,IAAI,QAAQ,IAAI,QACrB,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI;EAGzB,YAAY,QAAQ,MAAM,MAAM,KAAK;EAErC,MAAM,IAAI,QAAQ,MAAM;GACtB,KAAK,QAAQ;GACb;GACA;GACA,OAAO,SAAS,YAAY,QAAQ;EACrC,CAAA;CACH;CAEA,OAAO,CAAC,GAAG,MAAM,OAAM,CAAE;AAC3B;AAGA,SAAgB,YAAY,MAAoB;CAC9C,MAAM,SAAkC,OAAO,OAAO,IAAI;CAE1D,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,SAAoB,CAAA;EAE1B,KAAK,MAAM,OAAO,IAAI,MAAM;GAC1B,MAAM,SAAS,MAAM,IAAI,OAAO,GAAG;GAEnC,IAAI,WAAW,QACb,MAAM,IAAI,WAAW,IAAI,KAAK,WAAW,OAAO,KAAK;GAGvD,OAAO,KAAK,OAAO,KAAK;EAC1B;EAEA,IAAI,IAAI,OACN,OAAO,IAAI,OAAO,OAAO,OAAO,MAAM;OAEtC,OAAO,IAAI,OAAO,OAAO;CAE7B;CAEA,OAAO,OAAO,OAAO,MAAM;AAC7B;AAMA,SAAgB,YACd,YACA,UAAuD;CAEvD,MAAM,WAAW,cAAc,UAAU;CACzC,MAAM,SAAkC,OAAO,OAAO,IAAI;CAE1D,KAAK,MAAM,OAAO,OAAO,KAAK,SAAS,MAAM,GAAG;EAC9C,MAAM,QAAQ,SAAS,OAAO;EAC9B,MAAM,OAAkB,SAAS,cAAc,OAAO,GAAG;EAEzD,IAAI,KAAK,WAAW,KAAK,OAAO,KAAK,OAAO,UAAU;GACpD,MAAM,SAAS,MAAM,OAAO,KAAK,EAAE;GAEnC,IAAI,WAAW,QAAQ;IACrB,OAAO,OAAO,OAAO;IAErB;GACF;EACF;EAEA,MAAM,WAAW,cAAc,KAAK;EAEpC,IAAI,UACF,OAAO,OAAO,SAAS;CAE3B;CAEA,OAAO,OAAO,OAAO,MAAM;AAC7B;AAKA,MAAM,uBAAsB,IAAI,QAAO;AACvC,MAAM,wBAAkD,IAAI,QAAO;AACnE,MAAM,2BAAsC,IAAI,QAAO;AAGvD,SAAS,KACP,OACA,YACA,UACA,KAAgB;CAEhB,IAAI,YAAY,MAAM,IAAI,UAAU;CAEpC,IAAI,CAAC,WAAW;EACd,4BAAY,IAAI,QAAO;EACvB,MAAM,IAAI,YAAY,SAAS;CACjC;CAEA,IAAI,UAAU,UAAU,IAAI,QAAQ;CAEpC,IAAI,CAAC,SAAS;EACZ,IAAI;GACF,UAAU,EAAE,OAAO,IAAG,EAAE;EAC1B,SAAS,OAAO;GACd,UAAU,EAAE,MAAK;EACnB;EAEA,UAAU,IAAI,UAAU,OAAO;CACjC;CAEA,IAAI,WAAW,SACb,MAAM,QAAQ;CAGhB,OAAO,QAAQ;AACjB;AAGA,SAAgB,YAAY,KAAe,IAAY,UAAgC;CACrF,eAAe,UAAU,EAAE;CAE3B,MAAM,UAAU,IAAI,QAAQ;CAE5B,OAAO,KAAK,MAAM,QAAQ,WAAU,GAAI,gBAAe;EACrD,MAAM,OAAc,CAAA;EAEpB,KAAK,MAAM,WAAW,QAAQ,QAAQ;GACpC,MAAM,aAAa,IAAI,QAAQ,QAAQ,CAAC,WAAU;GAIlD,IAAI,CAAC,cAAc,UAAU,CAAC,CAAC,cAAc,MAAM,YAAY,QAAQ,SAAS,QAAQ,GACtF;GAGF,MAAM,QAAQ,CAAC,GAAG,SAAS,YAAY,CAAC,CACrC,QAAO,CAAE,CACT,MAAM,WAAW,YAAY,QAAQ,OAAO,CAAC;GAEhD,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,qCAAqC,SAAS;GAGhE,eAAe,OAAO,OAAO;GAC7B,KAAK,KAAK,GAAG,SAAS,YAAY,MAAM,GAAG,CAAC;EAC9C;EAEA,MAAM,SAAS,YAAY,IAAI;EAE/B,OAAO,OAAO,OAAO;GAAE;GAAQ,QAAQ,YAAY,QAAQ,WAAU,GAAI,QAAQ;EAAC,CAAE;CACtF,CAAC;AACH;AAQA,SAAgB,WACd,KACA,IACA,UAAmC;CAEnC,eAAe,UAAU,EAAE;CAE3B,MAAM,aAAa,IAAI,QAAQ,GAAG,CAAC,WAAU;CAE7C,IAAI;EACF,OAAO,EACL,QAAQ,KAAK,OAAO,YAAY,gBAC9B,YAAY,SAAS,YAAY,SAAS,GAAG,CAAC,CAAC,EAElD;CACH,SAAS,OAAO;EACd,IAAI,iBAAiB,YACnB,OAAO,EAAE,MAAK;EAGhB,MAAM;CACR;AACF;AAOA,SAAgB,eACd,KACA,IACA,UAAmC;CAEnC,MAAM,aAAa,IAAI,QAAQ,GAAG,CAAC,WAAU;CAE7C,OAAO,KAAK,UAAU,YAAY,gBAAe;EAC/C,MAAM,OAAO,WAAW,KAAK,IAAI,QAAQ;EAIzC,IAAI,WAAW,MACb;EAGF,OAAO,OAAO,OAAO;GAAE,QAAQ,KAAK;GAAQ,QAAQ,YAAY,YAAY,QAAQ;EAAC,CAAE;CACzF,CAAC;AACH;AC1SA,SAAgB,UACd,KACA,IAAU;CAEV,MAAM,WAAW,cAAc,IAAI,QAAQ,GAAG,CAAC,WAAU,CAAE;CAC3D,MAAM,SAAS,SAAS;CACxB,MAAM,SACJ,CAAA;CACF,MAAM,WAAW,OAAO;CAExB,IAAI,UACF,OAAO,cAAc,SAAS,KAC3B,cACE,UAAU,UACT,SAAS,YAAY,KAAK,IAAI,QAAQ,GAAG,UAAU,KAAK,CAAC;CAIjE,MAAM,WAAW,OAAO;CAExB,IAAI,UACF,OAAO,mBAAmB,SAAS,KAChC,cACE,OAAO,UAAS;EACf,IAAI;EAGJ,KAAK,IAAI,QAAQ,MAAM,aAAa,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;GACtE,MAAM,WAAW,MAAM,aAAa;GAEpC,IAAI,YAAY,UAAU,EAAE,GAAG;IAC7B,SAAS;IAET;GACF;EACF;EAEA,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,qCAAqC,IAAI;EAG3D,OAAO,SAAS,YAAY,KAAK,IAAI,MAAM,GAAG,OAAO,KAAK;CAC5D,CAAC;CAIP,MAAM,WAAW,OAAO;CACxB,MAAM,WAAyB,CAAA;CAI/B,IACE,SAAS,cAAc,MAAM,YAAY,QAAQ,SAAS,QAAQ,KAClE,OAAO,KAAK,SAAS,MAAM,CAAC,CAAC,SAAS,GACtC;EACA,MAAM,UAAU,OAAO;EAEvB,SAAS,MAAM,OAAO,UAAU,aAAY;GAC1C,MAAM,OAAO,WAAW,KAAK,IAAI,QAAQ;GAEzC,IAAI,EAAE,WAAW,OAAO;IAGtB,eAAe,KAAK,IAAI,QAAQ;IAEhC,OAAO;GACT;GAEA,IAAI,CAAC,SACH,OAAO;GAGT,MAAM,WAAW,QAAQ,KAAK,OAAO,OAAO,UAAU,QAAQ;GAE9D,IAAI,aAAa,QAAQ,KAAK,gBAAgB,QAAQ,GACpD,OAAO,KAAK,QAAoC,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAC;GAGjF,OAAO,oBAAoB,QAAQ;EACrC,CAAC;CACH;CAEA,IAAI,UACF,KAAK,MAAM,YAAY,UACrB,SAAS,MAAM,OAAO,UAAU,aAAY;EAC1C,MAAM,SAAS,eAAe,KAAK,IAAI,QAAQ;EAG/C,IAAI,WAAW,QACb,OAAO;EAGT,OAAO,SAAS,QAAQ,OAAO,UAAU,QAAQ;CACnD,CAAC;CAIL,IAAI,SAAS,SAAS,GACpB,OAAO,WAAW;CAGpB,MAAM,YAAY,OAAO;CAOzB,IAAI,WAAW;EACb,MAAM,UAAmD,OAAO,OAAO,IAAI;EAE3E,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GACzC,QAAQ,QAAQ,UAAU,UACxB,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,QAAQ,GAAG,UAAU,KAAK;EAGlE,OAAO,UAAU;CACnB;CAEA,MAAM,QAAQ,OAAO;CAMrB,IAAI,OAAO,UAAU,YACnB,OAAO,SAAS,UAAU,UAAU,MAAM,YAAY,KAAK,IAAI,QAAQ,GAAG,UAAU,KAAK;MACpF,IAAI,UAAU,QACnB,OAAO,QAAQ;CAGjB,OAAO;AACT;AAEA,SAAS,gBAAgB,OAAc;CACrC,OAAO,CAAC,CAAC,SAAS,OAAQ,MAA+B,SAAS;AACpE;AAGA,SAAS,oBAAoB,UAAiB;CAC5C,IAAI,aAAa,SAAS,oBAAoB,WAAW,oBAAoB,iBAC3E,OAAO;CAGT,MAAM,IAAI,UAAU,mEAAmE;AACzF;AAEA,SAAgB,SAAS,YAA0B;CACjD,QAAQ,aAAY;EAClB,MAAM,SAAS,OAAO,MAAM;EAC5B,MAAM,SAAS,cAAc,WAAU,CAAE;EACzC,MAAM,SAAS,OAAO,OAAO;EAM7B,MAAM,SAAS,cAAc,OAAO,EAAE;EACtC,MAAM,sBAAM,IAAI,IAAG;EAEnB,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS,QAAQ,SAAS,GAAG;GAC9D,MAAM,UAAU,OAAO,SAAS;GAEhC,IAAI,QAAQ,SAAS,UACnB,IAAI,IAAI,QAAQ,MAAM;IACpB,QAAQ,SAAS,IAAI,MAAM,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,IAAI;IACtE,OAAO;GACR,CAAA;QACI,IAAI,QAAQ,SAAS,YAC1B,IAAI,IAAI,QAAQ,MAAM;IACpB,QAAQ,SAAS,IAAI,MAAM,KAAK,CAAC,CAAC,KAAK,UAAU,MAAM,IAAI;IAC3D,OAAO;GACR,CAAA;EAEL;EAEA,MAAM,OAAc,CAAA;EAGpB,KAAK,MAAM,OAAO,IAAI,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC,GAAG;GACvD,MAAM,QAAQ,IAAI,IAAI,GAAG;GACzB,MAAM,OAAO,OAAO,UAAU,CAAA;GAC9B,MAAM,QAAQ,OAAO,SAAS;GAE9B,YAAY,KAAK,MAAM,KAAK;GAC5B,KAAK,KAAK;IAAE;IAAK;IAAM;IAAO,OAAO,OAAO,OAAO;GAAI,CAAE;EAC3D;EAGA,MAAM,UAAU,YAAY,IAAI;EAChC,MAAM,SAAkC,OAAO,OAAO,IAAI;EAE1D,KAAK,MAAM,CAAC,KAAK,cAAc,OAAO,QAAQ,OAAO,MAAM,GACzD,OAAO,OAAO,QAAQ;EAGxB,MAAM,OAAO,iBAAiB,OAAO,IAAI,MAAM;EAC/C,MAAM,cAAsC,OAAO,OAAO,IAAI;EAE9D,IAAI,OAAO,OAAO,SAAS,WAAW;GACpC,MAAM,SAAS,OAAO,OAAO;GAE7B,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,MAAM,CAAC,CAAC,KAAI,GAAI;IACnD,IAAI,CAAC,OAAO,OAAO,QAAQ,GAAG,KAAK,OAAO,SAAS,QACjD;IAGF,MAAM,MAAM,OAAO,OAAO,IAAI,CAAC,UAAU,OAAO,IAAI;IAEpD,IAAI,OAAO,QAAQ,UACjB,MAAM,IAAI,UAAU,qDAAqD,KAAK;IAGhF,YAAY,OAAO;GACrB;EACF;EAGA,MAAM,OAAO,OAAO,SAAS,IAAI;EAEjC,IAAI,OAAO,OAAO,SAAS,YACzB,KAAK,cAAc,EAAE,GAAG,SAAS,YAAW;OACvC,IAAI,OAAO,OAAO,SAAS,WAChC,KAAK,cAAc;EAGrB,IAAI,OAAO,SAAS,SAAS,YAC3B,KAAK,WAAW,SAAS;OACpB,IAAI,OAAO,SAAS,SAAS,WAClC,KAAK,WAAW,OAAO,SAAS;EAGlC,OAAO;CACT;AACF;AAEA,SAAS,iBAAiB,YAAsB,QAA+B;CAC7E,MAAM,WAAW,cAAc,UAAU;CACzC,MAAM,QAAkB,CAAA;CAExB,SAAS,OAAO,KAAW;EACzB,IAAI,QAAQ,MAAM,QAAQ,OAAO,QAAQ,MACvC,MAAM,IAAI,UAAU,6BAA6B;EAGnD,OAAO,mBAAmB,GAAG,CAAC,CAAC,QAAQ,OAAO,KAAK,CAAC,CAAC,QAAQ,OAAO,KAAK;CAC3E;CAEA,KAAK,MAAM,WAAW,SAAS,UAC7B,IAAI,QAAQ,SAAS,UACnB,MAAM,KAAK,OAAO,QAAQ,IAAI,CAAC;MAC1B,IAAI,QAAQ,SAAS,UAAU;EACpC,MAAM,MAAM,SAAS,OAAO,QAAQ,KAAK,CAAC,UAAU,OAAO,QAAQ,KAAK;EAExE,IAAI,OAAO,QAAQ,UACjB,MAAM,IAAI,UAAU,2CAA2C;EAGjE,MAAM,KAAK,OAAO,GAAG,CAAC;CACxB,OAAO;EACL,MAAM,SAAS,OAAO,QAAQ;EAE9B,IAAI,CAAC,MAAM,QAAQ,MAAM,GACvB,MAAM,IAAI,UAAU,qCAAqC;EAG3D,KAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,MAAM,SAAS,OAAO,QAAQ,KAAK,CAAC,UAAU,KAAK;GAEzD,IAAI,OAAO,QAAQ,UACjB,MAAM,IAAI,UAAU,2CAA2C;GAGjE,MAAM,KAAK,OAAO,GAAG,CAAC;EACxB;CACF;CAGF,OAAO,IAAI,MAAM,KAAK,GAAG;AAC3B;AC1SA,SAAgB,aACd,KACA,IAAU;CAMV,MAAM,YAAY,OAAO,cAAc;CACvC,MAAM,SAAS,OAAO,MAAM;CAE5B,eAAe,UAAU,UAAU,EAAE;CAErC,MAAM,WAAW,OAA+B,UAAU,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAInE,MAAM,eAAe,MACnB,UAAU,aACV,UAAU,UACV,UAAU,QACV,UAAU,KACV,UAAU,MACV,OAAO,MAAM,CACd,CAAC,gBAAe;EACf,SAAS,IAAI,UAAU,QAAQ;CACjC,CAAC;CAED,OAAO,UAAU,CAAC,CAAC,gBAAgB,aAAa,YAAW,CAAE;CAI7D,MAAM,SAAS,eAAe,YAAY,KAAK,IAAI,SAAQ,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CAC/D,MAAM,YAAY,cAAc,IAAI,QAAQ,GAAG,CAAC,WAAU,CAAE,CAAC,CAAC,OAAO,WAAW,CAAA;CAEhF,OAAO;EACL,QAAQ,eAAe,OAAM,CAAE,CAAC,MAAM;EACtC,QAAQ,eAAe,OAAM,CAAE,CAAC,MAAM;EACtC,MAAM,eAAc;GAClB,MAAM,OAAO,SAAQ,CAAE,CAAC;GACxB,MAAM,MAAoC,OAAO,OAAO,IAAI;GAE5D,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GACzC,IAAI,OAAO,OAAO,MAAM,GAAG,GACzB,IAAI,OAAO,KAAK;GAIpB,OAAO,OAAO,OAAO,GAAG;EAC1B,CAAC;CACF;AACH;ACVA,MAAM,+BAAe,IAAI,QAAO;AAEhC,SAAgB,kBACd,QACA,IAAM;CAEN,MAAM,cAAc,OAAO,OAAO,CAAA,CAAE;CAEpC,aAAa,IAAI,aAAa;EAAE;EAAQ;CAAE,CAAE;CAE5C,OAAO;AACT;AAqKA,SAAgB,cAAc,YAAoB;CAChD,MAAM,SAAS,cAAc,UAAU,CAAC,CAAC;CACzC,MAAM,UAAmC,CAAA;CAEzC,KAAK,MAAM,OAAO;EAAC;EAAa;EAAQ;EAAiB;CAAuB,GAC9E,IAAI,OAAO,OAAO,QAAQ,GAAG,GAC3B,QAAQ,OAAO,OAAO;CAI1B,OAAO;AACT;AAEA,SAAgB,qBAKd,KAAe,IAAU;CACzB,MAAM,SAAS,OAAO,MAAM;CAC5B,MAAM,OAAO,aAAa,KAAK,EAAE;CAEjC,SAAS,IAAI,MAAwB;EACnC,IAAI,KAAK,WAAW,KAAK,KAAK,WAAW,GACvC,MAAM,IAAI,UAAU,sDAAsD;EAG5E,IAAI,SAAS;EACb,IAAI,SAAS,KAAK;EAElB,IAAI,KAAK,WAAW,GAAG;GACrB,MAAM,WAAW,KAAK;GAEtB,SAAS,KAAK;GAEd,IAAI,OAAO,aAAa,UACtB;QAAI,aAAa,KAAK;KACpB,IAAI,OAAO,OAAO,IAAI,UAAU,QAAQ,GACtC,SAAS,IAAI,SAAS;UACjB,IAAI,OAAO,OAAO,IAAI,SAAS,KAAK,QAAQ,GACjD,SAAS,IAAI,SAAS,GAAG,CAAC;UAE1B,MAAM,IAAI,UAAU,+BAA+B,UAAU;IAEjE;UACK;IACL,IAAI,OAAO,aAAa,YAAY,aAAa,MAC/C,MAAM,IAAI,UAAU,8DAA8D;IAGpF,MAAM,cAAc,aAAa,IAAI,QAAQ;IAE7C,IACE,CAAC,eACD,YAAY,OAAM,MAAO,OACzB,CAAC,OAAO,OAAO,IAAI,SAAS,YAAY,EAAE,GAE1C,MAAM,IAAI,UAAU,oDAAoD;IAG1E,SAAS,YAAY;GACvB;EACF;EAEA,OAAO,UAAU,IAAI,aAAa,OAAO,CAAA,GAAI,MAA6B;CAC5E;CAEA,OAAO;EACL,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,MAAM,KAAK;EACX,QAAQ,GAAG,SAAoB,OAAO,SAAS,IAAI,IAAI,CAAC;EAMxD,YAAY,GAAG,SAAoB,OAAO,cAAc,IAAI,IAAI,CAAC;CAMlE;AACH"}
1
+ {"version":3,"file":"loozo-angular-router-_generated.mjs","names":[],"sources":["../../_generated/src/inputs.ts","../../_generated/src/callbacks.ts","../../_generated/src/handle.ts","../../_generated/src/index.ts"],"sourcesContent":["import type { ActivatedRouteSnapshot, PartialMatchRouteSnapshot } from \"@angular/router\";\nimport { codecFallback, routeMetadata, type AnyRoute } from \"@loozo/angular-router/_core\";\n\nexport interface RecordBinding {\n readonly definition: () => AnyRoute;\n readonly owners: readonly string[];\n}\nexport interface RouteSet {\n readonly records: Readonly<Record<string, RecordBinding>>;\n readonly destinations: Readonly<Record<string, () => AnyRoute>>;\n readonly absolute: Readonly<Record<string, string>>;\n readonly parents: Readonly<Record<string, string>>;\n}\nexport interface Parsed {\n readonly params: Readonly<Record<string, unknown>>;\n readonly search: Readonly<Record<string, unknown>>;\n}\nexport interface Job {\n readonly key: string;\n readonly raws: readonly string[];\n readonly array: boolean;\n readonly codec: { parse(raw: string): unknown };\n}\n\nexport function hasIdentity(\n snapshot: Pick<ActivatedRouteSnapshot, \"routeConfig\">,\n id: string,\n): boolean {\n const data = snapshot.routeConfig?.data;\n\n return (\n !!data &&\n Object.hasOwn(data, \"__loozoAngularRouterRouteId\") &&\n data.__loozoAngularRouterRouteId === id\n );\n}\n\nexport function assertIdentity(\n snapshot: Pick<ActivatedRouteSnapshot, \"routeConfig\">,\n id: string,\n): void {\n if (!hasIdentity(snapshot, id)) {\n throw new Error(`Generated route wiring identity mismatch: ${id}`);\n }\n}\n\n// Private: input errors are Errors with source/key/reason, not an exported class.\nclass InputError extends Error {\n readonly source = \"path\";\n\n constructor(\n readonly key: string,\n readonly reason: \"missing\" | \"repeated\" | \"invalid\",\n cause?: unknown,\n ) {\n super(`Invalid path input ${key}: ${reason}`, { cause });\n }\n}\n\nexport function validateRaw(\n key: string,\n raws: readonly unknown[],\n array: boolean,\n): asserts raws is readonly string[] {\n if (!array && raws.length === 0) {\n throw new InputError(key, \"missing\");\n }\n\n if (!array && raws.length > 1) {\n throw new InputError(key, \"repeated\");\n }\n\n if (raws.some((raw) => typeof raw !== \"string\")) {\n throw new InputError(key, \"invalid\", new TypeError(\"Raw input must be a decoded string\"));\n }\n}\n\n/**\n * Runs one parser. A throw is invalid input; a thenable is a programming error,\n * thrown as a TypeError so it fails the navigation instead of reading as invalid.\n */\nfunction parse(codec: Job[\"codec\"], raw: string): { value: unknown } | { cause: unknown } {\n let value: unknown;\n\n try {\n value = codec.parse(raw);\n } catch (cause) {\n return { cause };\n }\n\n if (\n value !== null &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n typeof (value as PromiseLike<unknown>).then === \"function\"\n ) {\n // Observe the stray result so its rejection can't surface as unhandled.\n Promise.resolve(value).catch(() => undefined);\n\n throw new TypeError(\"ParamCodec.parse must return its value synchronously, not a Promise\");\n }\n\n return { value };\n}\n\nexport function pathJobs(definition: AnyRoute, url: readonly { path: string }[]): Job[] {\n const metadata = routeMetadata(definition);\n const local = new Map<string, Job>();\n\n for (let index = 0; index < metadata.localSegments.length; index += 1) {\n const segment = metadata.localSegments[index];\n\n if (segment.kind === \"static\") {\n continue;\n }\n\n let raws: unknown[] = [];\n const array = segment.kind === \"catchall\";\n\n if (array) {\n raws = url.slice(index).map((value) => value.path);\n } else if (index < url.length) {\n raws = [url[index].path];\n }\n\n validateRaw(segment.name, raws, array);\n // Repeated local scalars intentionally use Angular's last positional occurrence.\n local.set(segment.name, {\n key: segment.name,\n raws,\n array,\n codec: metadata.localParams[segment.name],\n });\n }\n\n return [...local.values()];\n}\n\n/** Parses prechecked path jobs; the first codec failure is an input error. */\nexport function runPathJobs(jobs: readonly Job[]): Readonly<Record<string, unknown>> {\n const params: Record<string, unknown> = Object.create(null);\n\n for (const job of jobs) {\n const values: unknown[] = [];\n\n for (const raw of job.raws) {\n const result = parse(job.codec, raw);\n\n if (\"cause\" in result) {\n throw new InputError(job.key, \"invalid\", result.cause);\n }\n\n values.push(result.value);\n }\n\n if (job.array) {\n params[job.key] = Object.freeze(values);\n } else {\n params[job.key] = values[0];\n }\n }\n\n return Object.freeze(params);\n}\n\n/**\n * Parses a declaration's effective search. It never fails on input: a missing,\n * repeated or invalid value reads as the key's fallback, or leaves it absent.\n */\nexport function parseSearch(\n definition: AnyRoute,\n snapshot: Pick<ActivatedRouteSnapshot, \"queryParamMap\">,\n): Readonly<Record<string, unknown>> {\n const metadata = routeMetadata(definition);\n const search: Record<string, unknown> = Object.create(null);\n\n for (const key of Object.keys(metadata.search)) {\n const codec = metadata.search[key];\n const raws: unknown[] = snapshot.queryParamMap.getAll(key);\n\n if (raws.length === 1 && typeof raws[0] === \"string\") {\n const result = parse(codec, raws[0]);\n\n if (\"value\" in result) {\n search[key] = result.value;\n\n continue;\n }\n }\n\n const fallback = codecFallback(codec);\n\n if (fallback) {\n search[key] = fallback.value;\n }\n }\n\n return Object.freeze(search);\n}\n\ntype Outcome<Value> = { readonly value: Value } | { readonly error: unknown };\ntype Cache<Value> = WeakMap<object, WeakMap<object, Outcome<Value>>>;\n\nconst full: Cache<Parsed> = new WeakMap();\nconst paths: Cache<Readonly<Record<string, unknown>>> = new WeakMap();\nconst matching: Cache<Parsed | undefined> = new WeakMap();\n\n// One result or failure per exact declaration and snapshot, shared by every reader.\nfunction memo<Value>(\n cache: Cache<Value>,\n definition: AnyRoute,\n snapshot: object,\n run: () => Value,\n): Value {\n let snapshots = cache.get(definition);\n\n if (!snapshots) {\n snapshots = new WeakMap();\n cache.set(definition, snapshots);\n }\n\n let outcome = snapshots.get(snapshot);\n\n if (!outcome) {\n try {\n outcome = { value: run() };\n } catch (error) {\n outcome = { error };\n }\n\n snapshots.set(snapshot, outcome);\n }\n\n if (\"error\" in outcome) {\n throw outcome.error;\n }\n\n return outcome.value;\n}\n\n/** The effective inputs of a complete snapshot, shared by guards, resolvers and handles. */\nexport function parseInputs(set: RouteSet, id: string, snapshot: ActivatedRouteSnapshot): Parsed {\n assertIdentity(snapshot, id);\n\n const binding = set.records[id];\n\n return memo(full, binding.definition(), snapshot, () => {\n const jobs: Job[] = [];\n\n for (const ownerId of binding.owners) {\n const definition = set.records[ownerId].definition();\n\n // Pathless/static owners contribute no positional input. Effective search belongs\n // to this complete future record; inherited data is never positional authority.\n if (!routeMetadata(definition).localSegments.some((segment) => segment.kind !== \"static\")) {\n continue;\n }\n\n const owner = [...snapshot.pathFromRoot]\n .reverse()\n .find((record) => hasIdentity(record, ownerId));\n\n if (!owner) {\n throw new Error(`Generated route ancestor missing: ${ownerId}`);\n }\n\n assertIdentity(owner, ownerId);\n jobs.push(...pathJobs(definition, owner.url));\n }\n\n const params = runPathJobs(jobs);\n\n return Object.freeze({ params, search: parseSearch(binding.definition(), snapshot) });\n });\n}\n\n/**\n * Parses a matching candidate's own path params only. Angular passes one partial\n * snapshot to all of a candidate's canMatch guards, so they share this result.\n *\n * @returns An input error when a param is invalid; throws only programming errors.\n */\nexport function pathInputs(\n set: RouteSet,\n id: string,\n snapshot: PartialMatchRouteSnapshot,\n): { params: Readonly<Record<string, unknown>> } | { error: Error } {\n assertIdentity(snapshot, id);\n\n const definition = set.records[id].definition();\n\n try {\n return {\n params: memo(paths, definition, snapshot, () =>\n runPathJobs(pathJobs(definition, snapshot.url)),\n ),\n };\n } catch (error) {\n if (error instanceof InputError) {\n return { error };\n }\n\n throw error;\n }\n}\n\n/**\n * Local path params plus effective search for a candidate's canMatch guards, the\n * generated one included, or undefined when the path params fail: the generated\n * guard owns that outcome.\n */\nexport function matchingInputs(\n set: RouteSet,\n id: string,\n snapshot: PartialMatchRouteSnapshot,\n): Parsed | undefined {\n const definition = set.records[id].definition();\n\n return memo(matching, definition, snapshot, () => {\n const path = pathInputs(set, id, snapshot);\n\n // Search parses only once the path matches: a candidate the path rules out runs no\n // search codecs.\n if (\"error\" in path) {\n return undefined;\n }\n\n return Object.freeze({ params: path.params, search: parseSearch(definition, snapshot) });\n });\n}\n","import { inject } from \"@angular/core\";\nimport {\n Router,\n RedirectCommand,\n UrlTree,\n type Route,\n type ActivatedRouteSnapshot,\n type RouterStateSnapshot,\n type GuardResult,\n type CanActivateFn,\n type CanActivateChildFn,\n type CanMatchFn,\n type ResolveFn,\n type RedirectFunction,\n} from \"@angular/router\";\nimport { from, isObservable, map, type ObservableInput } from \"rxjs\";\nimport { routeMetadata, type AnyRoute } from \"@loozo/angular-router/_core\";\nimport {\n hasIdentity,\n parseInputs,\n matchingInputs,\n pathInputs,\n runPathJobs,\n validateRaw,\n type Job,\n type RouteSet,\n} from \"./inputs.js\";\n\n// Parsing is synchronous, so every adapter calls its callback in the same call Angular\n// made: Angular's injection context is still active and inject() works at entry.\nexport function callbacks(\n set: RouteSet,\n id: string,\n): Pick<Route, \"canActivate\" | \"canActivateChild\" | \"canMatch\" | \"resolve\" | \"title\"> {\n const metadata = routeMetadata(set.records[id].definition());\n const config = metadata.config;\n const result: Pick<Route, \"canActivate\" | \"canActivateChild\" | \"canMatch\" | \"resolve\" | \"title\"> =\n {};\n const activate = config.canActivate as readonly ((...args: any[]) => any)[] | undefined;\n\n if (activate) {\n result.canActivate = activate.map(\n (callback): CanActivateFn =>\n (snapshot, state) =>\n callback(parseInputs(set, id, snapshot), snapshot, state),\n );\n }\n\n const children = config.canActivateChild as readonly ((...args: any[]) => any)[] | undefined;\n\n if (children) {\n result.canActivateChild = children.map(\n (callback): CanActivateChildFn =>\n (child, state) => {\n let parent: ActivatedRouteSnapshot | undefined;\n\n // The native ancestry includes child itself; only proper ancestors can declare this guard.\n for (let index = child.pathFromRoot.length - 2; index >= 0; index -= 1) {\n const ancestor = child.pathFromRoot[index];\n\n if (hasIdentity(ancestor, id)) {\n parent = ancestor;\n\n break;\n }\n }\n\n if (!parent) {\n throw new Error(`Generated guard ancestor missing: ${id}`);\n }\n\n return callback(parseInputs(set, id, parent), child, state);\n },\n );\n }\n\n const matching = config.canMatch as readonly ((...args: any[]) => any)[] | undefined;\n const canMatch: CanMatchFn[] = [];\n\n // Local path params decide whether this record matches. Angular runs every canMatch\n // guard concurrently and prefers the first non-true result in array order.\n if (\n metadata.localSegments.some((segment) => segment.kind !== \"static\") ||\n Object.keys(metadata.search).length > 0\n ) {\n const handler = config.onInvalidParams as ((...args: any[]) => unknown) | undefined;\n\n canMatch.push((route, segments, snapshot) => {\n const path = pathInputs(set, id, snapshot);\n\n if (!(\"error\" in path)) {\n // Search never decides the match, but Angular runs this guard on every navigation,\n // query-only ones included, so a thenable search parse fails it here.\n matchingInputs(set, id, snapshot);\n\n return true;\n }\n\n if (!handler) {\n return false;\n }\n\n const decision = handler(path.error, route, segments, snapshot);\n\n if (isObservable(decision) || isPromiseResult(decision)) {\n return from(decision as ObservableInput<unknown>).pipe(map(invalidParamsResult));\n }\n\n return invalidParamsResult(decision);\n });\n }\n\n if (matching) {\n for (const callback of matching) {\n canMatch.push((route, segments, snapshot) => {\n const inputs = matchingInputs(set, id, snapshot);\n\n // Invalid path params: the generated guard ahead of this one decides.\n if (inputs === undefined) {\n return false;\n }\n\n return callback(inputs, route, segments, snapshot);\n });\n }\n }\n\n if (canMatch.length > 0) {\n result.canMatch = canMatch;\n }\n\n const resolvers = config.resolve as\n | Record<\n PropertyKey,\n (inputs: unknown, snapshot: ActivatedRouteSnapshot, state: RouterStateSnapshot) => any\n >\n | undefined;\n\n if (resolvers) {\n const resolve: Record<PropertyKey, ResolveFn<unknown>> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolvers)) {\n resolve[key] = (snapshot, state) =>\n resolvers[key](parseInputs(set, id, snapshot), snapshot, state);\n }\n\n result.resolve = resolve;\n }\n\n const title = config.title as\n | string\n | ((inputs: unknown, snapshot: ActivatedRouteSnapshot, state: RouterStateSnapshot) => any)\n | undefined;\n\n // Angular runs a title callback as a resolver, so it's adapted like one.\n if (typeof title === \"function\") {\n result.title = (snapshot, state) => title(parseInputs(set, id, snapshot), snapshot, state);\n } else if (title !== undefined) {\n result.title = title;\n }\n\n return result;\n}\n\nfunction isPromiseResult(value: unknown): value is PromiseLike<unknown> {\n return !!value && typeof (value as PromiseLike<unknown>).then === \"function\";\n}\n\n// Invalid params can't match, so a handler may only refuse or redirect.\nfunction invalidParamsResult(decision: unknown): GuardResult {\n if (decision === false || decision instanceof UrlTree || decision instanceof RedirectCommand) {\n return decision;\n }\n\n throw new TypeError(\"onInvalidParams must return false, a UrlTree or a RedirectCommand\");\n}\n\nexport function redirect(definition: () => AnyRoute): RedirectFunction {\n return (snapshot) => {\n const router = inject(Router);\n const source = routeMetadata(definition());\n const config = source.config.redirect as {\n to: AnyRoute;\n params: Record<string, string>;\n search: { mode: string; values?: Record<string, unknown> };\n fragment: { mode: string; value?: string };\n };\n const target = routeMetadata(config.to);\n const raw = new Map<string, { values: string[]; array: boolean }>();\n\n for (let index = 0; index < source.segments.length; index += 1) {\n const segment = source.segments[index];\n\n if (segment.kind === \"scalar\") {\n raw.set(segment.name, {\n values: snapshot.url.slice(index, index + 1).map((value) => value.path),\n array: false,\n });\n } else if (segment.kind === \"catchall\") {\n raw.set(segment.name, {\n values: snapshot.url.slice(index).map((value) => value.path),\n array: true,\n });\n }\n }\n\n const jobs: Job[] = [];\n\n // Only mapped source params are parsed, each cardinality checked before any parser runs.\n for (const key of new Set(Object.values(config.params))) {\n const input = raw.get(key);\n const raws = input?.values ?? [];\n const array = input?.array ?? false;\n\n validateRaw(key, raws, array);\n jobs.push({ key, raws, array, codec: source.params[key] });\n }\n\n // A failure fails the navigation: a redirect record has no matching guard to fall through.\n const logical = runPathJobs(jobs);\n const params: Record<string, unknown> = Object.create(null);\n\n for (const [key, sourceKey] of Object.entries(config.params)) {\n params[key] = logical[sourceKey];\n }\n\n const path = createUrlForPath(config.to, params);\n const replacement: Record<string, string> = Object.create(null);\n\n if (config.search.mode === \"replace\") {\n const values = config.search.values!;\n\n for (const key of Object.keys(target.search).sort()) {\n if (!Object.hasOwn(values, key) || values[key] === undefined) {\n continue;\n }\n\n const raw = target.search[key].stringify(values[key]);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(`Redirect search codec must stringify to a string: ${key}`);\n }\n\n replacement[key] = raw;\n }\n }\n\n // No native conversion before source codecs and destination stringification succeed.\n const tree = router.parseUrl(path);\n\n if (config.search.mode === \"preserve\") {\n tree.queryParams = { ...snapshot.queryParams };\n } else if (config.search.mode === \"replace\") {\n tree.queryParams = replacement;\n }\n\n if (config.fragment.mode === \"preserve\") {\n tree.fragment = snapshot.fragment;\n } else if (config.fragment.mode === \"replace\") {\n tree.fragment = config.fragment.value!;\n }\n\n return tree;\n };\n}\n\nfunction createUrlForPath(definition: AnyRoute, params: Record<string, unknown>): string {\n const metadata = routeMetadata(definition);\n const parts: string[] = [];\n\n function encode(raw: string): string {\n if (raw === \"\" || raw === \".\" || raw === \"..\") {\n throw new TypeError(\"Invalid redirect path value\");\n }\n\n return encodeURIComponent(raw).replace(/\\(/g, \"%28\").replace(/\\)/g, \"%29\");\n }\n\n for (const segment of metadata.segments) {\n if (segment.kind === \"static\") {\n parts.push(encode(segment.text));\n } else if (segment.kind === \"scalar\") {\n const raw = metadata.params[segment.name].stringify(params[segment.name]);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(\"Redirect codec must stringify to a string\");\n }\n\n parts.push(encode(raw));\n } else {\n const values = params[segment.name];\n\n if (!Array.isArray(values)) {\n throw new TypeError(\"Redirect catchall requires an array\");\n }\n\n for (const value of values) {\n const raw = metadata.params[segment.name].stringify(value);\n\n if (typeof raw !== \"string\") {\n throw new TypeError(\"Redirect codec must stringify to a string\");\n }\n\n parts.push(encode(raw));\n }\n }\n }\n\n return `/${parts.join(\"/\")}`;\n}\n","import { DestroyRef, computed, inject, signal, type Signal } from \"@angular/core\";\nimport { ActivatedRoute, Router, type ActivatedRouteSnapshot } from \"@angular/router\";\nimport { routeMetadata } from \"@loozo/angular-router/_core\";\nimport { merge } from \"rxjs\";\nimport { assertIdentity, parseInputs, type RouteSet } from \"./inputs.js\";\n\n/**\n * Signals of the route's committed snapshot. Angular replaces ActivatedRoute.snapshot\n * only when a navigation activates, so a pending, cancelled or failed navigation\n * leaves the values alone; params, search and data change together, from one snapshot.\n */\nexport function observeRoute(\n set: RouteSet,\n id: string,\n): {\n params: Signal<Readonly<Record<string, unknown>>>;\n search: Signal<Readonly<Record<string, unknown>>>;\n data: Signal<Readonly<Record<PropertyKey, unknown>>>;\n} {\n const activated = inject(ActivatedRoute);\n const router = inject(Router);\n\n assertIdentity(activated.snapshot, id);\n\n const snapshot = signal<ActivatedRouteSnapshot>(activated.snapshot);\n // Activation replaces the snapshot, then emits the route's changed observables, then\n // ActivationEnd. Following both keeps reads current inside subscribers registered after\n // the handle; router events cover a new snapshot whose values are all equal.\n const subscription = merge(\n activated.queryParams,\n activated.fragment,\n activated.params,\n activated.url,\n activated.data,\n router.events,\n ).subscribe(() => {\n snapshot.set(activated.snapshot);\n });\n\n inject(DestroyRef).onDestroy(() => subscription.unsubscribe());\n\n // Shares the parse of guards and resolvers for the same snapshot. An error here\n // means a codec rejected a value it accepted while matching, and reading rethrows it.\n const inputs = computed(() => parseInputs(set, id, snapshot()));\n const resolvers = routeMetadata(set.records[id].definition()).config.resolve ?? {};\n\n return {\n params: computed(() => inputs().params),\n search: computed(() => inputs().search),\n data: computed(() => {\n const data = snapshot().data;\n const own: Record<PropertyKey, unknown> = Object.create(null);\n\n for (const key of Reflect.ownKeys(resolvers)) {\n if (Object.hasOwn(data, key)) {\n own[key] = data[key];\n }\n }\n\n return Object.freeze(own);\n }),\n };\n}\n","export { callbacks, redirect } from \"./callbacks.js\";\nexport { assertIdentity, parseInputs } from \"./inputs.js\";\nexport type { RecordBinding, RouteSet } from \"./inputs.js\";\n\nimport { inject, type Signal } from \"@angular/core\";\nimport { Router, type UrlTree } from \"@angular/router\";\nimport {\n createUrl,\n routeMetadata,\n type AnyRoute,\n type ParamsOf,\n type SearchOf,\n type UrlValues,\n} from \"@loozo/angular-router/_core\";\nimport { observeRoute } from \"./handle.js\";\nimport type { RouteSet } from \"./inputs.js\";\n\ndeclare const destinationBrand: unique symbol;\n\n/**\n * An inert nominal reference exported as `destination` by a route-local facade.\n *\n * @remarks\n * Use the exported object with a handle's link/navigate methods; no injection\n * context or target activation is needed. It selects its exact declaration,\n * not a canonical pathless winner. Only references from the caller's generated\n * set are accepted. Copies, spreads, fakes and authored routes are not references.\n * Do not construct this type or pass it to the root createUrl function.\n *\n * @typeParam Target - The referenced route's input and fragment schema.\n * @typeParam Set - The generator's nominal route-set identity.\n * @typeParam Id - The exact generated declaration identity.\n */\nexport declare class Destination<\n Target extends AnyRoute,\n Set = unknown,\n Id extends string = string,\n> {\n // Type-only identity, intentionally not read; object spreads must lose this member.\n // oxlint-disable-next-line no-unused-private-class-members\n readonly #nominal: void;\n /** Type-only nominal brand carrying the reference's identity; not populated at runtime. */\n readonly [destinationBrand]: {\n /** Type-only: the referenced route's input and fragment schema. */\n readonly target: Target;\n /** Type-only: the generator's nominal route-set identity. */\n readonly set: Set;\n /** Type-only: the exact generated declaration identity. */\n readonly id: Id;\n };\n}\n\nconst destinations = new WeakMap<object, { getSet: () => RouteSet; id: string }>();\n\nexport function createDestination<Target extends AnyRoute, Set, Id extends string>(\n getSet: () => RouteSet,\n id: Id,\n): Destination<Target, Set, Id> {\n const destination = Object.freeze({});\n\n destinations.set(destination, { getSet, id });\n\n return destination as Destination<Target, Set, Id>;\n}\n\ntype DataOf<Target> = Target extends { readonly __data?: infer Data } ? Readonly<Data> : never;\ntype IsUnion<Value, Whole = Value> = Value extends unknown\n ? [Whole] extends [Value]\n ? false\n : true\n : never;\n\n/**\n * The noncallable typed handle returned by a colocated `injectRoute()` facade.\n *\n * @remarks\n * Obtain it in an Angular injection context for the exact generated activated\n * record. Params, search and data are readonly Angular Signals of the route's\n * committed snapshot, with values from the first read. Data contains only local\n * resolver results, not static/ancestor data or title.\n *\n * While a navigation is pending, the signals keep the current snapshot's values;\n * when a navigation commits a new snapshot for this route, all three change\n * together. Cancellation, failure or a same-URL skip leaves them unchanged. For\n * pending-navigation UI, read Angular's `Router.currentNavigation()`. There is no\n * resolved-data cache. Reading params or search throws only when a path codec\n * rejects a value it accepted while matching, a programming error.\n *\n * Selectors are single known authored literals, not concrete URLs or string\n * unions. `.` is exact-current; `..` selects the parent route: the nearest\n * ancestor with a shorter path, or the root for a top-level route. It and\n * absolute selectors use generated canonical targets. Every call supplies all\n * target values; there is no current-value reuse, extras argument or implicit\n * query merge.\n *\n * @typeParam Target - The bound declaration's schema.\n * @typeParam Absolute - Absolute literal selectors and their target schemas.\n * @typeParam Parent - The `..` target's schema, or never when there is none.\n * @typeParam Set - The generator's nominal route-set identity.\n * @typeParam References - Exact declarations addressable by same-set references.\n *\n * @example\n * ```ts\n * import { injectRoute } from \"./route.generated.js\";\n * import { destination as report } from \"../report/route.generated.js\";\n *\n * const route = injectRoute(); // Inside an Angular injection context.\n * const link = route.link(report, { params: { reportId: 42 } });\n * // Bind link to Angular RouterLink, or call route.navigate with the same values.\n * ```\n */\nexport interface Handle<\n Target extends AnyRoute,\n Absolute extends Record<string, AnyRoute> = {},\n Parent extends AnyRoute = never,\n Set = unknown,\n References extends Record<string, AnyRoute> = {},\n> {\n /** Effective positional params of the committed snapshot; kept while a navigation is pending. */\n readonly params: Signal<Readonly<ParamsOf<Target>>>;\n /** Effective declared search, from the same snapshot as params; absent keys have no value or fallback. */\n readonly search: Signal<Readonly<SearchOf<Target>>>;\n /** Own native resolver results only, from the same snapshot as params. */\n readonly data: Signal<DataOf<Target>>;\n /**\n * Creates a native UrlTree for this exact declaration without navigating.\n *\n * @param values - Explicit effective params/search and optional own fragment.\n * @returns Router.parseUrl's result, suitable for Angular RouterLink.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n link<Keys extends keyof SearchOf<Target> = never>(values: UrlValues<Target, Keys>): UrlTree;\n /**\n * Creates a UrlTree for the exact bound declaration, not its pathless winner.\n *\n * @param selector - The exact-current literal `.`.\n * @param values - Explicit values for this declaration, with no current-input reuse.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n link<Keys extends keyof SearchOf<Target> = never>(\n selector: \".\",\n values: UrlValues<Target, Keys>,\n ): UrlTree;\n /**\n * Creates a UrlTree for a statically admitted absolute authored selector.\n *\n * @param selector - A single known template literal, never a concrete URL.\n * @param values - The selected target's complete explicit values.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronously for unknown selectors or invalid URL values.\n */\n link<\n const Selector extends keyof Absolute & string,\n Keys extends keyof SearchOf<NoInfer<Absolute[Selector]>> = never,\n >(\n selector: Selector & (IsUnion<Selector> extends true ? never : unknown),\n values: UrlValues<NoInfer<Absolute[Selector]>, Keys>,\n ): UrlTree;\n /**\n * Creates a UrlTree for the parent route, when the bound declaration has one.\n *\n * @param selector - The literal `..`.\n * @param values - The parent route's complete explicit values.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronously for invalid URL values.\n */\n link<Keys extends keyof SearchOf<Parent> = never>(\n selector: [Parent] extends [never] ? never : \"..\",\n values: UrlValues<Parent, Keys>,\n ): UrlTree;\n /**\n * Creates a UrlTree for a generated reference's own exact declaration.\n *\n * @param selector - A genuine destination exported by a facade in this route set.\n * @param values - The referenced declaration's complete explicit values.\n * @returns Router.parseUrl's result without navigating.\n * @throws Synchronously for foreign/fake references or invalid URL values.\n */\n link<\n const Id extends keyof References & string,\n Keys extends keyof SearchOf<NoInfer<References[Id]>> = never,\n >(\n selector: Destination<NoInfer<References[Id]>, Set, Id> &\n (IsUnion<Id> extends true ? never : unknown),\n values: UrlValues<NoInfer<References[Id]>, Keys>,\n ): UrlTree;\n /**\n * Navigates to this exact declaration via Router.navigateByUrl.\n *\n * @param values - Explicit effective params/search and optional own fragment.\n * @returns Angular's identical Promise; Angular owns skips, redirects and failures.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n navigate<Keys extends keyof SearchOf<Target> = never>(\n values: UrlValues<Target, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to the exact bound declaration, not its pathless winner.\n *\n * @param selector - The exact-current literal `.`.\n * @param values - Explicit values for this declaration, with no current-input reuse.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronous URL validation, encoding or stringifier failures before Angular.\n */\n navigate<Keys extends keyof SearchOf<Target> = never>(\n selector: \".\",\n values: UrlValues<Target, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to a statically admitted absolute authored selector.\n *\n * @param selector - A single known template literal, never a concrete URL.\n * @param values - The selected target's complete explicit values.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronously for unknown selectors or invalid URL values.\n */\n navigate<\n const Selector extends keyof Absolute & string,\n Keys extends keyof SearchOf<NoInfer<Absolute[Selector]>> = never,\n >(\n selector: Selector & (IsUnion<Selector> extends true ? never : unknown),\n values: UrlValues<NoInfer<Absolute[Selector]>, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to the parent route, when the bound declaration has one.\n *\n * @param selector - The literal `..`.\n * @param values - The parent route's complete explicit values.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronously for invalid URL values.\n */\n navigate<Keys extends keyof SearchOf<Parent> = never>(\n selector: [Parent] extends [never] ? never : \"..\",\n values: UrlValues<Parent, Keys>,\n ): Promise<boolean>;\n /**\n * Navigates to a generated reference's own exact declaration.\n *\n * @param selector - A genuine destination exported by a facade in this route set.\n * @param values - The referenced declaration's complete explicit values.\n * @returns Angular's identical Router.navigateByUrl Promise.\n * @throws Synchronously for foreign/fake references or invalid URL values.\n */\n navigate<\n const Id extends keyof References & string,\n Keys extends keyof SearchOf<NoInfer<References[Id]>> = never,\n >(\n selector: Destination<NoInfer<References[Id]>, Set, Id> &\n (IsUnion<Id> extends true ? never : unknown),\n values: UrlValues<NoInfer<References[Id]>, Keys>,\n ): Promise<boolean>;\n}\n\nexport function nativeOptions(definition: AnyRoute): Record<string, unknown> {\n const config = routeMetadata(definition).config;\n const options: Record<string, unknown> = {};\n\n for (const key of [\"providers\", \"data\", \"canDeactivate\", \"runGuardsAndResolvers\"]) {\n if (Object.hasOwn(config, key)) {\n options[key] = config[key];\n }\n }\n\n return options;\n}\n\nexport function injectGeneratedRoute<\n Target extends AnyRoute,\n Absolute extends Record<string, AnyRoute>,\n Parent extends AnyRoute,\n Set,\n References extends Record<string, AnyRoute>,\n>(set: RouteSet, id: string): Handle<Target, Absolute, Parent, Set, References> {\n const router = inject(Router);\n const view = observeRoute(set, id);\n\n function url(args: readonly unknown[]): string {\n if (args.length !== 1 && args.length !== 2) {\n throw new TypeError(\"Expected values or a selected destination and values\");\n }\n\n let target = id;\n let values = args[0];\n\n if (args.length === 2) {\n const selector = args[0];\n\n values = args[1];\n\n if (typeof selector === \"string\") {\n if (selector !== \".\") {\n if (Object.hasOwn(set.absolute, selector)) {\n target = set.absolute[selector];\n } else if (selector === \"..\" && Object.hasOwn(set.parents, id)) {\n target = set.parents[id];\n } else {\n throw new TypeError(`Unknown generated selector: ${selector}`);\n }\n }\n } else {\n if (typeof selector !== \"object\" || selector === null) {\n throw new TypeError(\"Expected a literal selector or genuine generated destination\");\n }\n\n const destination = destinations.get(selector);\n\n if (\n !destination ||\n destination.getSet() !== set ||\n !Object.hasOwn(set.records, destination.id)\n ) {\n throw new TypeError(\"Expected a destination from the same generated set\");\n }\n\n target = destination.id;\n }\n }\n\n return createUrl(set.destinations[target](), values as UrlValues<AnyRoute>);\n }\n\n return {\n params: view.params as Signal<Readonly<ParamsOf<Target>>>,\n search: view.search as Signal<Readonly<SearchOf<Target>>>,\n data: view.data as Signal<DataOf<Target>>,\n link: ((...args: unknown[]) => router.parseUrl(url(args))) as Handle<\n Target,\n Absolute,\n Parent,\n Set,\n References\n >[\"link\"],\n navigate: ((...args: unknown[]) => router.navigateByUrl(url(args))) as Handle<\n Target,\n Absolute,\n Parent,\n Set,\n References\n >[\"navigate\"],\n };\n}\n"],"mappings":"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"}
@@ -2,6 +2,18 @@ import { createBuilder } from "@angular-devkit/architect";
2
2
  import { generate } from "../generation/generate.js";
3
3
  import { message, split } from "./options.js";
4
4
  const officialApplicationBuilder = "@angular/build:application";
5
+ // The conditions @angular/build 22.2's bundler uses when none are configured, chosen from the
6
+ // normalized optimization as it chooses them.
7
+ function defaultConditions(optimization = true) {
8
+ let scripts = optimization;
9
+ if (typeof optimization === "object" && optimization !== null && !Array.isArray(optimization)) {
10
+ scripts = optimization.scripts;
11
+ }
12
+ if (scripts) {
13
+ return ["module", "production"];
14
+ }
15
+ return ["module", "development"];
16
+ }
5
17
  export default createBuilder(async (options, context) => {
6
18
  let stopped = false;
7
19
  let acquisition;
@@ -23,6 +35,11 @@ export default createBuilder(async (options, context) => {
23
35
  if (official.watch === true) {
24
36
  throw new Error("The application builder runs once; it does not support watch: true");
25
37
  }
38
+ // The schema's false marks an omitted conditions (scripts/builder-schemas.mjs). Omitting it
39
+ // here would reach Angular as an explicit [] again, so Angular's default list goes instead.
40
+ if (official.conditions === false) {
41
+ official.conditions = defaultConditions(official.optimization);
42
+ }
26
43
  generation = generate(context.workspaceRoot, router, () => stopped);
27
44
  try {
28
45
  await generation;