@analogjs/router 3.0.0-alpha.3 → 3.0.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/content/package.json +4 -0
  2. package/fesm2022/analogjs-router-content.mjs +63 -0
  3. package/fesm2022/analogjs-router-content.mjs.map +1 -0
  4. package/fesm2022/analogjs-router-server-actions.mjs +309 -1
  5. package/fesm2022/analogjs-router-server-actions.mjs.map +1 -0
  6. package/fesm2022/analogjs-router-server.mjs +2 -2
  7. package/fesm2022/analogjs-router-server.mjs.map +1 -0
  8. package/fesm2022/analogjs-router-tanstack-query-server.mjs +22 -0
  9. package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
  10. package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
  11. package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
  12. package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
  13. package/fesm2022/analogjs-router.mjs +560 -62
  14. package/fesm2022/analogjs-router.mjs.map +1 -0
  15. package/fesm2022/debug.page.mjs +53 -31
  16. package/fesm2022/debug.page.mjs.map +1 -0
  17. package/fesm2022/provide-analog-query.mjs +23 -0
  18. package/fesm2022/provide-analog-query.mjs.map +1 -0
  19. package/fesm2022/route-files.mjs +362 -0
  20. package/fesm2022/route-files.mjs.map +1 -0
  21. package/fesm2022/routes.mjs +5 -278
  22. package/fesm2022/routes.mjs.map +1 -0
  23. package/package.json +71 -25
  24. package/tanstack-query/package.json +4 -0
  25. package/tanstack-query/server/package.json +4 -0
  26. package/types/content/src/index.d.ts +4 -0
  27. package/types/content/src/lib/debug/routes.d.ts +10 -0
  28. package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
  29. package/types/content/src/lib/routes.d.ts +8 -0
  30. package/types/content/src/lib/with-content-routes.d.ts +2 -0
  31. package/types/server/actions/src/define-action.d.ts +54 -0
  32. package/types/server/actions/src/define-api-route.d.ts +57 -0
  33. package/types/server/actions/src/define-page-load.d.ts +55 -0
  34. package/types/server/actions/src/define-server-route.d.ts +68 -0
  35. package/types/server/actions/src/index.d.ts +9 -1
  36. package/types/server/actions/src/parse-request-data.d.ts +9 -0
  37. package/types/server/actions/src/validate.d.ts +8 -0
  38. package/types/server/src/provide-server-context.d.ts +1 -1
  39. package/types/server/src/render.d.ts +1 -1
  40. package/types/server/src/server-component-render.d.ts +1 -1
  41. package/types/src/index.d.ts +16 -5
  42. package/types/src/lib/cache-key.d.ts +1 -1
  43. package/types/src/lib/cookie-interceptor.d.ts +1 -1
  44. package/types/src/lib/debug/debug.page.d.ts +4 -2
  45. package/types/src/lib/define-route.d.ts +6 -1
  46. package/types/src/lib/endpoints.d.ts +1 -1
  47. package/types/src/lib/experimental.d.ts +140 -0
  48. package/types/src/lib/form-action.directive.d.ts +12 -5
  49. package/types/src/lib/inject-load.d.ts +5 -2
  50. package/types/src/lib/inject-navigate.d.ts +23 -0
  51. package/types/src/lib/inject-route-context.d.ts +32 -0
  52. package/types/src/lib/inject-typed-params.d.ts +63 -0
  53. package/types/src/lib/json-ld.d.ts +32 -0
  54. package/types/src/lib/meta-tags.d.ts +3 -1
  55. package/types/src/lib/models.d.ts +3 -0
  56. package/types/src/lib/provide-file-router-base.d.ts +4 -0
  57. package/types/src/lib/provide-file-router.d.ts +2 -8
  58. package/types/src/lib/route-builder.d.ts +5 -0
  59. package/types/src/lib/route-files.d.ts +18 -0
  60. package/types/src/lib/route-path.d.ts +124 -0
  61. package/types/src/lib/route-types.d.ts +2 -1
  62. package/types/src/lib/routes.d.ts +2 -10
  63. package/types/src/lib/validation-errors.d.ts +7 -0
  64. package/types/tanstack-query/server/src/index.d.ts +1 -0
  65. package/types/tanstack-query/src/index.d.ts +2 -0
  66. package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
  67. package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
  68. package/types/tanstack-query/src/server-query.d.ts +16 -0
@@ -0,0 +1,68 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import type { H3Event } from 'nitro/h3';
3
+ export type DefineServerRouteResult = Response | unknown;
4
+ export interface ServerRouteHandler<TQuery = unknown, TBody = unknown, TResult = unknown> {
5
+ (event: H3Event): Promise<Response>;
6
+ readonly _types: {
7
+ readonly query: TQuery;
8
+ readonly body: TBody;
9
+ readonly result: TResult;
10
+ };
11
+ }
12
+ export type InferRouteQuery<T> = T extends ServerRouteHandler<infer Q, any, any> ? Q : never;
13
+ export type InferRouteBody<T> = T extends ServerRouteHandler<any, infer B, any> ? B : never;
14
+ export type InferRouteResult<T> = T extends ServerRouteHandler<any, any, infer R> ? Exclude<R, Response> : never;
15
+ type OptionalSchema = StandardSchemaV1 | undefined;
16
+ type InferSchema<TSchema extends OptionalSchema, TFallback = unknown> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
17
+ type ResolveDataSchema<TInput extends OptionalSchema, TQuery extends OptionalSchema, TBody extends OptionalSchema> = TInput extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TInput> : TQuery extends StandardSchemaV1 ? TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TQuery> | StandardSchemaV1.InferOutput<TBody> : StandardSchemaV1.InferOutput<TQuery> : TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TBody> : unknown;
18
+ export interface DefineServerRouteContext<TInput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined> {
19
+ data: ResolveDataSchema<TInput, TQuery, TBody>;
20
+ query: InferSchema<TQuery, undefined>;
21
+ body: InferSchema<TBody, undefined>;
22
+ params: InferSchema<TParams, H3Event['context']['params']>;
23
+ event: H3Event;
24
+ }
25
+ export interface DefineServerRouteOptions<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineServerRouteResult = DefineServerRouteResult> {
26
+ input?: TInput;
27
+ query?: TQuery;
28
+ body?: TBody;
29
+ params?: TParams;
30
+ output?: TOutput;
31
+ handler: (context: DefineServerRouteContext<TInput, TQuery, TBody, TParams>) => Promise<TResult> | TResult;
32
+ }
33
+ /**
34
+ * Creates an h3-compatible event handler with Standard Schema validation.
35
+ *
36
+ * - `input` schema validates the request body (POST/PUT/PATCH) or query
37
+ * params (GET). Returns 422 with `StandardSchemaV1.Issue[]` on failure.
38
+ * - `output` schema validates the response in development only (stripped
39
+ * in production for zero overhead). Logs a warning on mismatch.
40
+ * - Plain return values are serialized with `json(...)`; raw `Response`
41
+ * objects are returned unchanged.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { defineServerRoute } from '@analogjs/router/server/actions';
46
+ * import * as v from 'valibot';
47
+ *
48
+ * const Input = v.object({
49
+ * name: v.pipe(v.string(), v.minLength(1)),
50
+ * email: v.pipe(v.string(), v.email()),
51
+ * });
52
+ * const Output = v.object({
53
+ * id: v.string(),
54
+ * name: v.string(),
55
+ * });
56
+ *
57
+ * export default defineServerRoute({
58
+ * input: Input,
59
+ * output: Output,
60
+ * handler: async ({ data }) => {
61
+ * const user = await db.users.create(data);
62
+ * return user;
63
+ * },
64
+ * });
65
+ * ```
66
+ */
67
+ export declare function defineServerRoute<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineServerRouteResult = DefineServerRouteResult>(options: DefineServerRouteOptions<TInput, TOutput, TQuery, TBody, TParams, TResult>): ServerRouteHandler<InferSchema<TQuery, undefined>, InferSchema<TBody, undefined>, TResult>;
68
+ export {};
@@ -1 +1,9 @@
1
- export { PageServerAction, json, redirect, fail } from './actions';
1
+ export type { PageServerAction } from './actions';
2
+ export { json, redirect, fail } from './actions';
3
+ export { defineAction } from './define-action';
4
+ export type { DefineActionContext, DefineActionOptions } from './define-action';
5
+ export { defineServerRoute } from './define-server-route';
6
+ export type { DefineServerRouteContext, DefineServerRouteOptions, DefineServerRouteResult, ServerRouteHandler, InferRouteQuery, InferRouteBody, InferRouteResult, } from './define-server-route';
7
+ export { definePageLoad } from './define-page-load';
8
+ export type { PageLoadContext, DefinePageLoadOptions, } from './define-page-load';
9
+ export { validateWithSchema } from './validate';
@@ -0,0 +1,9 @@
1
+ type RequestEntryValue = string | File;
2
+ type ParsedRequestValue = RequestEntryValue | RequestEntryValue[];
3
+ export declare function parseSearchParams(searchParams: URLSearchParams): Record<string, ParsedRequestValue>;
4
+ export declare function parseFormData(formData: FormData): Record<string, ParsedRequestValue>;
5
+ export declare function parseRequestData(event: {
6
+ method: string;
7
+ headers: Headers;
8
+ }): Promise<unknown>;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ /**
3
+ * Validates unknown input against a Standard Schema.
4
+ *
5
+ * Handles both sync and async `validate` implementations — the Standard
6
+ * Schema spec allows either return shape.
7
+ */
8
+ export declare function validateWithSchema<T extends StandardSchemaV1>(schema: T, data: unknown): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<T>>>;
@@ -1,5 +1,5 @@
1
1
  import { StaticProvider } from '@angular/core';
2
- import { ServerInternalFetch, ServerRequest, ServerResponse } from '@analogjs/router/tokens';
2
+ import { ServerInternalFetch, ServerRequest, ServerResponse } from '../../tokens/src/index.js';
3
3
  export declare function provideServerContext({ req, res, fetch, }: {
4
4
  req: ServerRequest;
5
5
  res: ServerResponse;
@@ -1,5 +1,5 @@
1
1
  import { ApplicationConfig, Provider, Type } from '@angular/core';
2
- import type { ServerContext } from '@analogjs/router/tokens';
2
+ import type { ServerContext } from '../../tokens/src/index.js';
3
3
  /**
4
4
  * Returns a function that accepts the navigation URL,
5
5
  * the root HTML, and server context.
@@ -1,4 +1,4 @@
1
1
  import { ApplicationConfig } from '@angular/core';
2
- import { ServerContext } from '@analogjs/router/tokens';
2
+ import type { ServerContext } from '../../tokens/src/index.js';
3
3
  export declare function serverComponentRequest(serverContext: ServerContext): string | undefined;
4
4
  export declare function renderServerComponent(url: string, serverContext: ServerContext, config?: ApplicationConfig): Promise<Response>;
@@ -1,16 +1,27 @@
1
1
  export type { RouteExport } from './lib/models';
2
- export type { Files } from './lib/routes';
2
+ export type { Files } from './lib/route-files';
3
3
  export { routes, createRoutes } from './lib/routes';
4
4
  export { defineRouteMeta, injectActivatedRoute, injectRouter, } from './lib/define-route';
5
- export { RouteMeta } from './lib/models';
5
+ export type { RouteMeta } from './lib/models';
6
6
  export { provideFileRouter, withExtraRoutes } from './lib/provide-file-router';
7
- export { MetaTag } from './lib/meta-tags';
8
- export { PageServerLoad, LoadResult } from './lib/route-types';
9
- export { injectLoad } from './lib/inject-load';
7
+ export type { MetaTag } from './lib/meta-tags';
8
+ export type { PageServerLoad, LoadResult, LoadDataResult, } from './lib/route-types';
9
+ export { injectLoad, injectLoadData } from './lib/inject-load';
10
10
  export { getLoadResolver } from './lib/get-load-resolver';
11
11
  export { requestContextInterceptor } from './lib/request-context';
12
12
  export { injectRouteEndpointURL } from './lib/inject-route-endpoint-url';
13
13
  export { FormAction } from './lib/form-action.directive';
14
+ export type { FormActionState } from './lib/form-action.directive';
14
15
  export { injectDebugRoutes } from './lib/debug/routes';
15
16
  export { withDebugRoutes } from './lib/debug';
16
17
  export { ServerOnly } from './lib/server.component';
18
+ export type { AnalogJsonLdDocument } from './lib/json-ld';
19
+ export { issuesToFieldErrors, issuesToFormErrors, issuePathToFieldName, } from './lib/validation-errors';
20
+ export type { ValidationFieldErrors } from './lib/validation-errors';
21
+ export type { AnalogRouteTable, AnalogRoutePath, RoutePathOptions, RoutePathArgs, RoutePathOptionsBase, RouteParamsOutput, RouteQueryOutput, RouteLinkResult, } from './lib/route-path';
22
+ export { routePath } from './lib/route-path';
23
+ export { injectNavigate } from './lib/inject-navigate';
24
+ export { withTypedRouter, withRouteContext, withLoaderCaching, EXPERIMENTAL_TYPED_ROUTER, EXPERIMENTAL_ROUTE_CONTEXT, EXPERIMENTAL_LOADER_CACHE, } from './lib/experimental';
25
+ export type { TypedRouterOptions, LoaderCacheOptions, } from './lib/experimental';
26
+ export { injectParams, injectQuery } from './lib/inject-typed-params';
27
+ export { injectRouteContext } from './lib/inject-route-context';
@@ -1,3 +1,3 @@
1
1
  import { HttpRequest } from '@angular/common/http';
2
2
  import { StateKey } from '@angular/core';
3
- export declare function makeCacheKey(request: HttpRequest<any>, mappedRequestUrl: string): StateKey<unknown>;
3
+ export declare function makeCacheKey(request: HttpRequest<unknown>, mappedRequestUrl: string): StateKey<unknown>;
@@ -1,4 +1,4 @@
1
1
  import { HttpHandlerFn, HttpRequest, HttpEvent } from '@angular/common/http';
2
2
  import { Observable } from 'rxjs';
3
- import { ServerRequest } from '@analogjs/router/tokens';
3
+ import { type ServerRequest } from '../../tokens/src/index.js';
4
4
  export declare function cookieInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn, location?: object, serverRequest?: ServerRequest | null): Observable<HttpEvent<unknown>>;
@@ -6,12 +6,14 @@ type CollectedRoute = {
6
6
  filename: string;
7
7
  file: string;
8
8
  isLayout: boolean;
9
+ source: 'page' | 'content';
9
10
  };
10
11
  export default class DebugRoutesComponent implements OnInit {
11
12
  collectedRoutes: CollectedRoute[];
12
- debugRoutes: (import('@angular/router').Route & DebugRoute)[];
13
+ private debugRoutes;
14
+ private extraSources;
13
15
  ngOnInit(): void;
14
- traverseRoutes(routes: DebugRoute[], parent?: string): void;
16
+ traverseRoutes(routes: DebugRoute[], parent?: string, source?: 'page' | 'content'): void;
15
17
  static ɵfac: i0.ɵɵFactoryDeclaration<DebugRoutesComponent, never>;
16
18
  static ɵcmp: i0.ɵɵComponentDeclaration<DebugRoutesComponent, "analogjs-debug-routes-page", never, {}, {}, never, never, true, never>;
17
19
  }
@@ -1,7 +1,12 @@
1
1
  import { Route as NgRoute, Router } from '@angular/router';
2
2
  import { ActivatedRoute } from '@angular/router';
3
+ import { AnalogJsonLdDocument } from './json-ld';
4
+ import { MetaTag } from './meta-tags';
3
5
  type RouteOmitted = 'component' | 'loadComponent' | 'loadChildren' | 'path' | 'pathMatch';
4
- type RestrictedRoute = Omit<NgRoute, RouteOmitted>;
6
+ type RestrictedRoute = Omit<NgRoute, RouteOmitted> & {
7
+ meta?: MetaTag[];
8
+ jsonLd?: AnalogJsonLdDocument;
9
+ };
5
10
  /**
6
11
  * @deprecated Use `RouteMeta` type instead.
7
12
  * For more info see: https://github.com/analogjs/analog/issues/223
@@ -2,4 +2,4 @@ export declare const ANALOG_META_KEY: unique symbol;
2
2
  /**
3
3
  * This variable reference is replaced with a glob of all route endpoints.
4
4
  */
5
- export declare const ANALOG_PAGE_ENDPOINTS: any;
5
+ export declare const ANALOG_PAGE_ENDPOINTS: Record<string, () => Promise<unknown>>;
@@ -0,0 +1,140 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import type { RouterFeatures } from '@angular/router';
3
+ /**
4
+ * Configuration for experimental typed router features.
5
+ *
6
+ * Inspired by TanStack Router's type-safe navigation system where
7
+ * routes are registered globally and all navigation/hooks are typed
8
+ * against the route tree.
9
+ *
10
+ * @experimental
11
+ */
12
+ export interface TypedRouterOptions {
13
+ /**
14
+ * When true, logs warnings in development when navigating to
15
+ * routes with params that don't match the generated route table.
16
+ *
17
+ * Similar to TanStack Router's strict mode where `useParams()`
18
+ * without a `from` constraint returns a union of all possible params.
19
+ *
20
+ * @default false
21
+ */
22
+ strictRouteParams?: boolean;
23
+ }
24
+ /**
25
+ * Configuration for experimental loader caching.
26
+ *
27
+ * Inspired by TanStack Router's built-in data caching where route
28
+ * loaders automatically cache results and support stale-while-revalidate.
29
+ *
30
+ * @experimental
31
+ */
32
+ export interface LoaderCacheOptions {
33
+ /**
34
+ * Time in milliseconds before loader data is considered stale.
35
+ * While data is fresh, navigating back to the route uses cached
36
+ * data without re-invoking the server load function.
37
+ *
38
+ * Mirrors TanStack Router's `defaultStaleTime` option on `createRouter()`.
39
+ *
40
+ * @default 0 (always re-fetch)
41
+ */
42
+ defaultStaleTime?: number;
43
+ /**
44
+ * Time in milliseconds to retain unused loader data in cache
45
+ * after leaving a route. After this period the cached entry is
46
+ * garbage-collected.
47
+ *
48
+ * Mirrors TanStack Router's `defaultGcTime` (default 30 min).
49
+ *
50
+ * @default 300_000 (5 minutes)
51
+ */
52
+ defaultGcTime?: number;
53
+ /**
54
+ * Delay in milliseconds before showing a pending/loading indicator
55
+ * during route transitions. Prevents flash-of-loading-state for
56
+ * fast navigations.
57
+ *
58
+ * Mirrors TanStack Router's `defaultPendingMs`.
59
+ *
60
+ * @default 0 (show immediately)
61
+ */
62
+ defaultPendingMs?: number;
63
+ }
64
+ /** @experimental */
65
+ export declare const EXPERIMENTAL_TYPED_ROUTER: InjectionToken<TypedRouterOptions>;
66
+ /** @experimental */
67
+ export declare const EXPERIMENTAL_ROUTE_CONTEXT: InjectionToken<Record<string, unknown>>;
68
+ /** @experimental */
69
+ export declare const EXPERIMENTAL_LOADER_CACHE: InjectionToken<LoaderCacheOptions>;
70
+ /**
71
+ * Enables experimental typed router features.
72
+ *
73
+ * When active, `routePath()`, `injectNavigate()`, `injectParams()`,
74
+ * and `injectQuery()` will enforce route table constraints and
75
+ * optionally log warnings in strict mode.
76
+ *
77
+ * Inspired by TanStack Router's `Register` interface and strict type
78
+ * checking across the entire navigation surface.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * provideFileRouter(
83
+ * withTypedRouter({ strictRouteParams: true }),
84
+ * )
85
+ * ```
86
+ *
87
+ * @experimental
88
+ */
89
+ export declare function withTypedRouter(options?: TypedRouterOptions): RouterFeatures;
90
+ /**
91
+ * Provides root-level route context available to all route loaders
92
+ * and components via `injectRouteContext()`.
93
+ *
94
+ * Inspired by TanStack Router's `createRootRouteWithContext<T>()` where
95
+ * a typed context object is required at router creation and automatically
96
+ * available in every route's `beforeLoad` and `loader`.
97
+ *
98
+ * In Angular terms, this creates a DI token that server-side load
99
+ * functions and components can inject to access shared services
100
+ * without importing them individually.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * // app.config.ts
105
+ * provideFileRouter(
106
+ * withRouteContext({
107
+ * auth: inject(AuthService),
108
+ * db: inject(DatabaseService),
109
+ * }),
110
+ * )
111
+ *
112
+ * // In a component
113
+ * const ctx = injectRouteContext<{ auth: AuthService; db: DatabaseService }>();
114
+ * ```
115
+ *
116
+ * @experimental
117
+ */
118
+ export declare function withRouteContext<T extends Record<string, unknown>>(context: T): RouterFeatures;
119
+ /**
120
+ * Configures experimental loader caching behavior for server-loaded
121
+ * route data.
122
+ *
123
+ * Inspired by TanStack Router's built-in cache where `createRouter()`
124
+ * accepts `defaultStaleTime` and `defaultGcTime` to control when
125
+ * loaders re-execute and when cached data is discarded.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * provideFileRouter(
130
+ * withLoaderCaching({
131
+ * defaultStaleTime: 30_000, // 30s before re-fetch
132
+ * defaultGcTime: 300_000, // 5min cache retention
133
+ * defaultPendingMs: 200, // 200ms loading delay
134
+ * }),
135
+ * )
136
+ * ```
137
+ *
138
+ * @experimental
139
+ */
140
+ export declare function withLoaderCaching(options?: LoaderCacheOptions): RouterFeatures;
@@ -1,17 +1,24 @@
1
- import { InputSignal, OutputEmitterRef } from '@angular/core';
1
+ import { type InputSignal, type OutputEmitterRef, type WritableSignal } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
+ export type FormActionState = 'submitting' | 'error' | 'redirect' | 'success' | 'navigate';
3
4
  export declare class FormAction {
4
5
  action: InputSignal<string>;
5
6
  onSuccess: OutputEmitterRef<unknown>;
6
7
  onError: OutputEmitterRef<unknown>;
7
- state: OutputEmitterRef<'submitting' | 'error' | 'redirect' | 'success' | 'navigate'>;
8
+ state: OutputEmitterRef<FormActionState>;
8
9
  private router;
9
10
  private route;
10
- private path;
11
- submitted($event: any): void;
11
+ protected currentState: WritableSignal<FormActionState | 'idle'>;
12
+ /** Cached during construction (injection context) so inject() works. */
13
+ private _endpointUrl;
14
+ submitted($event: SubmitEvent): void;
12
15
  private _handleGet;
13
16
  private _handlePost;
14
- private _getPath;
17
+ private _getExplicitAction;
18
+ private _getGetPath;
19
+ private _getPostPath;
20
+ private _emitState;
21
+ private _navigateTo;
15
22
  private _isJSON;
16
23
  static ɵfac: i0.ɵɵFactoryDeclaration<FormAction, never>;
17
24
  static ɵdir: i0.ɵɵDirectiveDeclaration<FormAction, "form[action],form[method]", never, { "action": { "alias": "action"; "required": false; "isSignal": true; }; }, { "onSuccess": "onSuccess"; "onError": "onError"; "state": "state"; }, never, never, true, never>;
@@ -1,6 +1,9 @@
1
1
  import { Injector } from '@angular/core';
2
2
  import { Observable } from 'rxjs';
3
- import { PageServerLoad } from './route-types';
4
- export declare function injectLoad<T extends (pageServerLoad: PageServerLoad) => Promise<any>>(options?: {
3
+ import { LoadDataResult, PageServerLoad } from './route-types';
4
+ export declare function injectLoad<T extends (pageServerLoad: PageServerLoad) => Promise<unknown>>(options?: {
5
5
  injector?: Injector;
6
6
  }): Observable<Awaited<ReturnType<T>>>;
7
+ export declare function injectLoadData<T extends (pageServerLoad: PageServerLoad) => Promise<unknown>>(options?: {
8
+ injector?: Injector;
9
+ }): Observable<LoadDataResult<T>>;
@@ -0,0 +1,23 @@
1
+ import { type NavigationBehaviorOptions } from '@angular/router';
2
+ import type { AnalogRoutePath, RoutePathArgs } from './route-path';
3
+ type NavigateWithExtrasArgs<P extends AnalogRoutePath> = RoutePathArgs<P> extends [options?: infer Options] ? [extras: NavigationBehaviorOptions] | [options: Options | undefined, extras: NavigationBehaviorOptions] : [options: RoutePathArgs<P>[0], extras: NavigationBehaviorOptions];
4
+ type TypedNavigate = {
5
+ <P extends AnalogRoutePath>(path: P, ...args: RoutePathArgs<P>): Promise<boolean>;
6
+ <P extends AnalogRoutePath>(path: P, ...args: NavigateWithExtrasArgs<P>): Promise<boolean>;
7
+ };
8
+ /**
9
+ * Injects a typed navigate function.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const navigate = injectNavigate();
14
+ *
15
+ * navigate('/users/[id]', { params: { id: '42' } }); // ✅
16
+ * navigate('/users/[id]', { params: { id: 42 } }); // ❌ type error
17
+ *
18
+ * // With navigation extras
19
+ * navigate('/users/[id]', { params: { id: '42' } }, { replaceUrl: true });
20
+ * ```
21
+ */
22
+ export declare function injectNavigate(): TypedNavigate;
23
+ export {};
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Injects the root route context provided via `withRouteContext()`.
3
+ *
4
+ * Inspired by TanStack Router's context inheritance where
5
+ * `createRootRouteWithContext<T>()` makes a typed context available
6
+ * to every route's `beforeLoad` and `loader` callbacks.
7
+ *
8
+ * In Angular, this uses DI under the hood — `withRouteContext(ctx)`
9
+ * provides the value, and `injectRouteContext<T>()` retrieves it
10
+ * with the expected type.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // app.config.ts
15
+ * provideFileRouter(
16
+ * withRouteContext({
17
+ * auth: inject(AuthService),
18
+ * analytics: inject(AnalyticsService),
19
+ * }),
20
+ * )
21
+ *
22
+ * // any-page.page.ts
23
+ * const ctx = injectRouteContext<{
24
+ * auth: AuthService;
25
+ * analytics: AnalyticsService;
26
+ * }>();
27
+ * ctx.analytics.trackPageView();
28
+ * ```
29
+ *
30
+ * @experimental
31
+ */
32
+ export declare function injectRouteContext<T extends Record<string, unknown> = Record<string, unknown>>(): T;
@@ -0,0 +1,63 @@
1
+ import { Injector, Signal } from '@angular/core';
2
+ import type { AnalogRoutePath, RouteParamsOutput, RouteQueryOutput } from './route-path';
3
+ /**
4
+ * Injects typed route params as a signal, constrained by the route table.
5
+ *
6
+ * Inspired by TanStack Router's `useParams({ from: '/users/$userId' })`
7
+ * pattern where the `from` parameter narrows the return type to only
8
+ * the params defined for that route.
9
+ *
10
+ * The `from` parameter is used purely for TypeScript type inference —
11
+ * at runtime, params are read from the current `ActivatedRoute`. This
12
+ * means it works correctly when used inside a component rendered by
13
+ * the specified route.
14
+ *
15
+ * When `withTypedRouter({ strictRouteParams: true })` is configured,
16
+ * a dev-mode assertion checks that the expected params from `from`
17
+ * exist in the active route and warns on mismatch.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // In a component rendered at /users/[id]
22
+ * const params = injectParams('/users/[id]');
23
+ * // params() → { id: string }
24
+ *
25
+ * // With schema validation output types
26
+ * const params = injectParams('/products/[slug]');
27
+ * // params() → validated output type from routeParamsSchema
28
+ * ```
29
+ *
30
+ * @experimental
31
+ */
32
+ export declare function injectParams<P extends AnalogRoutePath>(_from: P, options?: {
33
+ injector?: Injector;
34
+ }): Signal<RouteParamsOutput<P>>;
35
+ /**
36
+ * Injects typed route query params as a signal, constrained by the
37
+ * route table.
38
+ *
39
+ * Inspired by TanStack Router's `useSearch({ from: '/issues' })` pattern
40
+ * where search params are validated and typed per-route via
41
+ * `validateSearch` schemas.
42
+ *
43
+ * In Analog, the typing comes from `routeQuerySchema` exports that are
44
+ * detected at build time and recorded in the generated route table.
45
+ *
46
+ * The `from` parameter is used purely for TypeScript type inference.
47
+ * When `withTypedRouter({ strictRouteParams: true })` is configured,
48
+ * a dev-mode assertion checks that the expected params from `from`
49
+ * exist in the active route and warns on mismatch.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * // In a component rendered at /issues
54
+ * // (where routeQuerySchema validates { page: number, status: string })
55
+ * const query = injectQuery('/issues');
56
+ * // query() → { page: number; status: string }
57
+ * ```
58
+ *
59
+ * @experimental
60
+ */
61
+ export declare function injectQuery<P extends AnalogRoutePath>(_from: P, options?: {
62
+ injector?: Injector;
63
+ }): Signal<RouteQueryOutput<P>>;
@@ -0,0 +1,32 @@
1
+ import { Router } from '@angular/router';
2
+ import type { Graph, Thing, WithContext } from 'schema-dts';
3
+ export type JsonLdObject = Record<string, unknown>;
4
+ export declare function isJsonLdObject(value: unknown): value is JsonLdObject;
5
+ export declare function normalizeJsonLd(value: unknown): JsonLdObject[];
6
+ export type JsonLd = JsonLdObject | JsonLdObject[];
7
+ /**
8
+ * Typed JSON-LD document based on `schema-dts`.
9
+ *
10
+ * Accepts single Schema.org nodes (`WithContext<Thing>`),
11
+ * `@graph`-based documents (`Graph`), or arrays of nodes.
12
+ *
13
+ * This is the canonical JSON-LD type for route authoring surfaces
14
+ * (`routeMeta.jsonLd`, `routeJsonLd`, generated manifest).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import type { WebPage, WithContext } from 'schema-dts';
19
+ *
20
+ * export const routeMeta = {
21
+ * jsonLd: {
22
+ * '@context': 'https://schema.org',
23
+ * '@type': 'WebPage',
24
+ * name: 'Products',
25
+ * } satisfies WithContext<WebPage>,
26
+ * };
27
+ * ```
28
+ */
29
+ export type AnalogJsonLdDocument = WithContext<Thing> | Graph | WithContext<Thing>[];
30
+ export declare const ROUTE_JSON_LD_KEY: unique symbol;
31
+ export declare function updateJsonLdOnRouteChange(router?: Router, document?: Document | null): void;
32
+ export declare function serializeJsonLd(entry: JsonLdObject): string | null;
@@ -1,3 +1,5 @@
1
+ import { Meta } from '@angular/platform-browser';
2
+ import { Router } from '@angular/router';
1
3
  export declare const ROUTE_META_TAGS_KEY: unique symbol;
2
4
  declare const CHARSET_KEY = "charset";
3
5
  declare const HTTP_EQUIV_KEY = "httpEquiv";
@@ -29,5 +31,5 @@ type MetaTagKey = typeof CHARSET_KEY | typeof HTTP_EQUIV_KEY | typeof NAME_KEY |
29
31
  type ExcludeRestMetaTagKeys<Key extends MetaTagKey> = {
30
32
  [K in Exclude<MetaTagKey, Key>]?: never;
31
33
  };
32
- export declare function updateMetaTagsOnRouteChange(): void;
34
+ export declare function updateMetaTagsOnRouteChange(router?: Router, metaService?: Meta): void;
33
35
  export {};
@@ -1,6 +1,7 @@
1
1
  import { Type } from '@angular/core';
2
2
  import { CanActivateChildFn, CanActivateFn, CanDeactivateFn, CanMatchFn, DeprecatedGuard, ResolveFn, Route } from '@angular/router';
3
3
  import { defineRouteMeta } from './define-route';
4
+ import { AnalogJsonLdDocument } from './json-ld';
4
5
  import { MetaTag } from './meta-tags';
5
6
  type OmittedRouteProps = 'path' | 'matcher' | 'component' | 'loadComponent' | 'children' | 'loadChildren' | 'canLoad' | 'outlet';
6
7
  export type RouteConfig = Omit<Route, OmittedRouteProps>;
@@ -14,6 +15,7 @@ export interface DefaultRouteMeta extends Omit<Route, OmittedRouteProps | keyof
14
15
  };
15
16
  title?: string | ResolveFn<string>;
16
17
  meta?: MetaTag[] | ResolveFn<MetaTag[]>;
18
+ jsonLd?: AnalogJsonLdDocument | ResolveFn<AnalogJsonLdDocument | undefined>;
17
19
  }
18
20
  export interface RedirectRouteMeta {
19
21
  redirectTo: string;
@@ -25,5 +27,6 @@ export type RouteMeta = (DefaultRouteMeta & {
25
27
  export type RouteExport = {
26
28
  default: Type<unknown>;
27
29
  routeMeta?: RouteMeta | ReturnType<typeof defineRouteMeta>;
30
+ routeJsonLd?: AnalogJsonLdDocument | ResolveFn<AnalogJsonLdDocument | undefined>;
28
31
  };
29
32
  export {};
@@ -0,0 +1,4 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+ import { RouterFeatures, Routes } from '@angular/router';
3
+ export declare function provideFileRouterWithRoutes(...features: RouterFeatures[]): EnvironmentProviders;
4
+ export declare function withExtraRoutes(routes: Routes): RouterFeatures;
@@ -1,5 +1,5 @@
1
1
  import { EnvironmentProviders } from '@angular/core';
2
- import { RouterFeatures, Routes } from '@angular/router';
2
+ import { RouterFeatures } from '@angular/router';
3
3
  /**
4
4
  * Sets up providers for the Angular router, and registers
5
5
  * file-based routes. Additional features can be provided
@@ -9,10 +9,4 @@ import { RouterFeatures, Routes } from '@angular/router';
9
9
  * @returns Providers and features to configure the router with routes
10
10
  */
11
11
  export declare function provideFileRouter(...features: RouterFeatures[]): EnvironmentProviders;
12
- /**
13
- * Provides extra custom routes in addition to the routes
14
- * discovered from the filesystem-based routing. These routes are
15
- * inserted before the filesystem-based routes, and take priority in
16
- * route matching.
17
- */
18
- export declare function withExtraRoutes(routes: Routes): RouterFeatures;
12
+ export { withExtraRoutes } from './provide-file-router-base';
@@ -0,0 +1,5 @@
1
+ import type { Route } from '@angular/router';
2
+ import type { RouteExport } from './models';
3
+ export type RouteModuleFactory = () => Promise<RouteExport>;
4
+ export type RouteModuleResolver<TFile> = (filename: string, fileLoader: () => Promise<TFile>) => RouteModuleFactory;
5
+ export declare function createRoutes<TFile>(files: Record<string, () => Promise<TFile>>, resolveModule: RouteModuleResolver<TFile>, debug?: boolean): Route[];
@@ -0,0 +1,18 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import type { RouteExport } from './models';
3
+ export type Files = Record<string, () => Promise<RouteExport>>;
4
+ /**
5
+ * This variable reference is replaced with a glob of all page routes.
6
+ */
7
+ export declare const ANALOG_ROUTE_FILES: {};
8
+ export interface ExtraRouteFileSource {
9
+ files: Record<string, () => Promise<unknown>>;
10
+ resolveModule: (filename: string, fileLoader: () => Promise<unknown>) => () => Promise<RouteExport>;
11
+ }
12
+ export declare const ANALOG_EXTRA_ROUTE_FILE_SOURCES: InjectionToken<ExtraRouteFileSource[]>;
13
+ /**
14
+ * Replaced at build time by the Vite router plugin with the number of
15
+ * discovered content route files. Used in dev mode to warn when content
16
+ * files exist but `withContentRoutes()` is not configured.
17
+ */
18
+ export declare const ANALOG_CONTENT_FILE_COUNT = 0;