@analogjs/router 3.0.0-alpha.7 → 3.0.0-alpha.70

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 (99) 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-i18n.mjs +156 -0
  5. package/fesm2022/analogjs-router-i18n.mjs.map +1 -0
  6. package/fesm2022/analogjs-router-server-actions.mjs +2 -27
  7. package/fesm2022/analogjs-router-server.mjs +734 -105
  8. package/fesm2022/analogjs-router-server.mjs.map +1 -0
  9. package/fesm2022/analogjs-router-tanstack-query-server.mjs +71 -0
  10. package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
  11. package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
  12. package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
  13. package/fesm2022/analogjs-router-tokens.mjs +7 -2
  14. package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
  15. package/fesm2022/analogjs-router.mjs +670 -170
  16. package/fesm2022/analogjs-router.mjs.map +1 -0
  17. package/fesm2022/debug.page.mjs +53 -31
  18. package/fesm2022/debug.page.mjs.map +1 -0
  19. package/fesm2022/provide-analog-query.mjs +72 -0
  20. package/fesm2022/provide-analog-query.mjs.map +1 -0
  21. package/fesm2022/route-files.mjs +361 -0
  22. package/fesm2022/route-files.mjs.map +1 -0
  23. package/fesm2022/routes.mjs +5 -278
  24. package/fesm2022/routes.mjs.map +1 -0
  25. package/fesm2022/src.mjs +335 -0
  26. package/fesm2022/src.mjs.map +1 -0
  27. package/i18n/package.json +4 -0
  28. package/package.json +52 -5
  29. package/tanstack-query/package.json +4 -0
  30. package/tanstack-query/server/package.json +4 -0
  31. package/types/content/src/index.d.ts +4 -0
  32. package/types/content/src/lib/debug/routes.d.ts +10 -0
  33. package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
  34. package/types/content/src/lib/routes.d.ts +8 -0
  35. package/types/content/src/lib/with-content-routes.d.ts +2 -0
  36. package/types/i18n/src/index.d.ts +1 -0
  37. package/types/i18n/src/provide-i18n.d.ts +92 -0
  38. package/types/server/actions/src/define-action.d.ts +54 -0
  39. package/types/server/actions/src/define-api-route.d.ts +57 -0
  40. package/types/server/actions/src/define-page-load.d.ts +55 -0
  41. package/types/server/actions/src/define-server-route.d.ts +68 -0
  42. package/types/server/actions/src/index.d.ts +9 -1
  43. package/types/server/actions/src/parse-request-data.d.ts +9 -0
  44. package/types/server/actions/src/validate.d.ts +8 -0
  45. package/types/server/src/defer-reconcile-runtime.d.ts +23 -0
  46. package/types/server/src/index.d.ts +9 -2
  47. package/types/server/src/provide-server-context.d.ts +15 -1
  48. package/types/server/src/render-stream.d.ts +40 -0
  49. package/types/server/src/render.d.ts +3 -3
  50. package/types/server/src/server-fn/app-injector.d.ts +30 -0
  51. package/types/server/src/server-fn/dispatch.d.ts +56 -0
  52. package/types/server/src/server-fn/event-handler.d.ts +22 -0
  53. package/types/server/src/server-fn/interceptors.d.ts +30 -0
  54. package/types/server/src/server-fn/node-context.d.ts +14 -0
  55. package/types/server/src/server-fn/registry.d.ts +7 -0
  56. package/types/server/src/server-fn/same-origin.d.ts +46 -0
  57. package/types/server/src/server-fn/server-fn.d.ts +21 -0
  58. package/types/server/src/server-fn/ssr-dispatcher.d.ts +17 -0
  59. package/types/server/src/utils/reset-component-def-tviews.d.ts +14 -0
  60. package/types/server/src/utils/stream-html.d.ts +13 -0
  61. package/types/server/src/utils/stream-request.d.ts +24 -0
  62. package/types/src/index.d.ts +20 -6
  63. package/types/src/lib/cache-key.d.ts +1 -1
  64. package/types/src/lib/cookie-interceptor.d.ts +1 -1
  65. package/types/src/lib/debug/debug.page.d.ts +4 -2
  66. package/types/src/lib/define-route.d.ts +6 -1
  67. package/types/src/lib/endpoints.d.ts +1 -1
  68. package/types/src/lib/experimental.d.ts +140 -0
  69. package/types/src/lib/form-action.directive.d.ts +12 -5
  70. package/types/src/lib/inject-load.d.ts +5 -2
  71. package/types/src/lib/inject-navigate.d.ts +23 -0
  72. package/types/src/lib/inject-route-context.d.ts +32 -0
  73. package/types/src/lib/inject-typed-params.d.ts +63 -0
  74. package/types/src/lib/json-ld.d.ts +32 -0
  75. package/types/src/lib/meta-tags.d.ts +3 -1
  76. package/types/src/lib/models.d.ts +3 -0
  77. package/types/src/lib/provide-file-router-base.d.ts +4 -0
  78. package/types/src/lib/provide-file-router.d.ts +2 -8
  79. package/types/src/lib/route-builder.d.ts +5 -0
  80. package/types/src/lib/route-files.d.ts +18 -0
  81. package/types/src/lib/route-path.d.ts +124 -0
  82. package/types/src/lib/route-types.d.ts +2 -1
  83. package/types/src/lib/routes.d.ts +2 -10
  84. package/types/src/lib/server-fn/dispatcher.d.ts +23 -0
  85. package/types/src/lib/server-fn/inject-server-fn.d.ts +44 -0
  86. package/types/src/lib/server-fn/server-fn-ref.d.ts +24 -0
  87. package/types/src/lib/server-fn/types.d.ts +55 -0
  88. package/types/src/lib/validation-errors.d.ts +7 -0
  89. package/types/tanstack-query/server/src/define-page-load-queries.d.ts +66 -0
  90. package/types/tanstack-query/server/src/index.d.ts +3 -0
  91. package/types/tanstack-query/src/constants.d.ts +9 -0
  92. package/types/tanstack-query/src/index.d.ts +2 -0
  93. package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
  94. package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
  95. package/types/tanstack-query/src/server-query.d.ts +16 -0
  96. package/types/tokens/src/index.d.ts +2 -0
  97. package/types/server/src/server-component-render.d.ts +0 -4
  98. package/types/server/src/tokens.d.ts +0 -7
  99. package/types/src/lib/server.component.d.ts +0 -33
@@ -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;
@@ -9,3 +9,17 @@ export declare function getBaseUrl(req: ServerRequest): string;
9
9
  export declare function getRequestProtocol(req: ServerRequest, opts?: {
10
10
  xForwardedProto?: boolean;
11
11
  }): string;
12
+ /**
13
+ * Detects the locale from the request URL path prefix or Accept-Language header.
14
+ * URL prefix takes priority (e.g. /fr/about -> 'fr').
15
+ */
16
+ export declare function detectLocale(req: ServerRequest): string | undefined;
17
+ /**
18
+ * Extracts a locale from the first URL path segment if it matches
19
+ * a BCP 47-like pattern (e.g. 'en', 'en-US', 'zh-Hans-CN').
20
+ */
21
+ export declare function extractLocaleFromUrl(url: string): string | undefined;
22
+ /**
23
+ * Parses the Accept-Language header and returns the most preferred language.
24
+ */
25
+ export declare function parseAcceptLanguage(header: string | undefined): string | undefined;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Progressive streaming SSR renderer — EXPERIMENTAL.
3
+ *
4
+ * Returns a `ReadableStream<Uint8Array>` that flushes bytes DURING the render,
5
+ * not after it:
6
+ * 1. the document head + a client reconcile runtime are flushed immediately,
7
+ * before the app has finished rendering, so the browser starts fetching
8
+ * assets right away;
9
+ * 2. each `@defer (hydrate …)` block's content is flushed the moment it
10
+ * resolves on the server — out of document order — while later blocks are
11
+ * still pending (proven: a slow block does not hold back an early one);
12
+ * 3. once the app is stable, the authoritative, fully hydration-annotated
13
+ * document is flushed as the tail. This is byte-identical to a buffered
14
+ * `renderApplication`, and is what Angular's incremental hydration runs
15
+ * against on the client.
16
+ *
17
+ * Unlike a buffered renderer, this drives the platform directly
18
+ * (`platformServer` + `bootstrapApplication` + `ɵrenderInternal`) so it can
19
+ * interleave flushes with rendering. Angular's hydration annotation is
20
+ * whole-document (the root's `ngh` index references every `@defer` container),
21
+ * so the authoritative hydration payload is necessarily the tail: RENDERING
22
+ * streams progressively, and hydration begins once the tail arrives.
23
+ *
24
+ * Depends on an upstream Angular per-block resolution hook exposed on two
25
+ * globals (see {@link SsrStreamingGlobals}). When the primitive is absent,
26
+ * `renderStream` degrades to a single buffered chunk so behaviour matches the
27
+ * classic `render()` path, which is unchanged and remains the default.
28
+ */
29
+ import { ApplicationConfig, Provider, Type } from '@angular/core';
30
+ import type { ServerContext } from '@analogjs/router/tokens';
31
+ /**
32
+ * Returns a function that renders a URL to a `ReadableStream<Uint8Array>`.
33
+ *
34
+ * Usage in main.server.ts:
35
+ * ```ts
36
+ * import { renderStream } from '@analogjs/router/server';
37
+ * export default renderStream(App, config);
38
+ * ```
39
+ */
40
+ export declare function renderStream(rootComponent: Type<unknown>, config: ApplicationConfig, platformProviders?: Provider[]): (url: string, document: string, serverContext: ServerContext) => Promise<ReadableStream<Uint8Array>>;
@@ -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.
@@ -7,6 +7,6 @@ import type { ServerContext } from '@analogjs/router/tokens';
7
7
  * @param rootComponent
8
8
  * @param config
9
9
  * @param platformProviders
10
- * @returns Promise<string | Reponse>
10
+ * @returns Promise<string>
11
11
  */
12
- export declare function render(rootComponent: Type<unknown>, config: ApplicationConfig, platformProviders?: Provider[]): (url: string, document: string, serverContext: ServerContext) => Promise<string | Response>;
12
+ export declare function render(rootComponent: Type<unknown>, config: ApplicationConfig, platformProviders?: Provider[]): (url: string, document: string, serverContext: ServerContext) => Promise<string>;
@@ -0,0 +1,30 @@
1
+ import { type ApplicationConfig, Injector, type StaticProvider } from '@angular/core';
2
+ /**
3
+ * Builds the parent injector the server-function dispatch endpoint runs handlers
4
+ * against, over HTTP.
5
+ *
6
+ * A plain `Injector.create({ providers })` resolves explicitly-listed providers
7
+ * but not tree-shakeable `providedIn: 'root'` services — those attach to a
8
+ * *bootstrapped* application's root injector, which `Injector.create` is not.
9
+ * So the in-process SSR leg (whose parent is the app's own bootstrapped
10
+ * injector) resolved `root` services while the HTTP leg did not — the same
11
+ * handler could work while rendering and fail when called from the browser.
12
+ *
13
+ * Bootstrapping a real application on the server platform closes that gap: the
14
+ * returned `appRef.injector` is a root environment injector, so both listed
15
+ * providers and `providedIn: 'root'` services resolve, matching SSR.
16
+ *
17
+ * The generated endpoint passes the app's own server `ApplicationConfig` (the
18
+ * one `main.server.ts` renders with), so a handler sees exactly the DI the app
19
+ * configured — services, tokens, and interceptors alike — with no second
20
+ * provider list to keep in sync. No root component is bootstrapped
21
+ * (`createApplication`, not `bootstrapApplication`), so nothing renders, no
22
+ * change detection runs, and the router registers but never navigates. It is a
23
+ * DI container with the app's providers, built once and reused for the process,
24
+ * with only `REQUEST`/`RESPONSE` rebuilt per call in the child.
25
+ *
26
+ * A bare provider array is also accepted (direct callers and tests without an
27
+ * app config); it is wrapped with `provideServerRendering` so the server tokens
28
+ * resolve the same way.
29
+ */
30
+ export declare function createServerFnAppInjector(configOrProviders?: ApplicationConfig | StaticProvider[]): Promise<Injector>;
@@ -0,0 +1,56 @@
1
+ import { Injector, type StaticProvider } from '@angular/core';
2
+ import type { H3Event } from 'nitro/h3';
3
+ export interface DispatchResult {
4
+ status: number;
5
+ body: unknown;
6
+ /**
7
+ * Headers from a returned `Response` (`fail`/`redirect`): Location, … The
8
+ * value is an array when the header legitimately repeats, which is why
9
+ * `Set-Cookie` is read separately below — collapsing several cookies into one
10
+ * comma-joined value corrupts them.
11
+ */
12
+ headers?: Record<string, string | string[]>;
13
+ }
14
+ export interface DispatchServerFnOptions {
15
+ /**
16
+ * The app's environment injector. The per-request injector is created as its
17
+ * child, so handlers resolve app services (and `providedIn: 'root'` services,
18
+ * when this is the app's bootstrapped injector) and registered interceptors
19
+ * without re-listing them per request.
20
+ */
21
+ parent?: Injector;
22
+ /** Extra per-request providers, for direct callers without an app injector. */
23
+ providers?: StaticProvider[];
24
+ /** Request HTTP method; enforced against the function's configured method. */
25
+ method?: string;
26
+ /**
27
+ * Origins permitted beyond same-origin, merged with any registered through DI
28
+ * (`provideServerFns(withAllowedOrigins([...]))`). The transport is
29
+ * same-origin by default (cross-origin browser calls are rejected with 403);
30
+ * `'*'` disables the check entirely. Only consulted for HTTP-transport calls
31
+ * (those that pass `method`).
32
+ */
33
+ allowedOrigins?: string[];
34
+ }
35
+ /**
36
+ * Server-side dispatch for a server function call.
37
+ *
38
+ * 1. reject cross-origin browser calls (403), unless allow-listed — HTTP
39
+ * transport only (in-process callers omit `method` and are exempt)
40
+ * 2. look up the function by id
41
+ * 3. enforce the configured HTTP method (405 on mismatch)
42
+ * 4. require a JSON body on input-bearing calls (415 otherwise)
43
+ * 5. validate `input` against the Standard-Schema (4xx on failure)
44
+ * 6. build a per-request injector (REQUEST/RESPONSE + app providers)
45
+ * 7. run the interceptor chain, then the handler, re-entering
46
+ * `runInInjectionContext` at every hop so `inject()` works even after an
47
+ * interceptor `await`s before calling `next`
48
+ * 8. a `Response` returned by an interceptor/handler (`fail`/`redirect`)
49
+ * short-circuits with its status AND headers
50
+ *
51
+ * `options.method` is the request's HTTP method; when provided it is enforced
52
+ * against the function's configured method AND it turns on the same-origin
53
+ * guard. Transports (the generated Nitro handler) always pass it; trusted
54
+ * in-process callers may omit it, which also exempts them from the origin guard.
55
+ */
56
+ export declare function dispatchServerFn(id: string, rawInput: unknown, event: Pick<H3Event, 'node'>, options?: DispatchServerFnOptions): Promise<DispatchResult>;
@@ -0,0 +1,22 @@
1
+ import type { Injector } from '@angular/core';
2
+ import { type EventHandler, type H3Event } from 'nitro/h3';
3
+ /**
4
+ * The h3 request/response layer for the server-function dispatch route.
5
+ *
6
+ * `createServerFnAppInjector` bootstraps the parent injector once; this wraps
7
+ * that in the `/_analog/fn/:id` handler the Nitro build registers. Kept as a
8
+ * runtime function (rather than inlined into the generated module) so the
9
+ * transport behaviour — body decoding, the malformed-body contract, and header
10
+ * propagation — is unit-tested directly instead of by matching generated source.
11
+ *
12
+ * `appInjector` may be a promise: the generated module bootstraps the app at
13
+ * import time and passes the pending injector, which is awaited on first request
14
+ * and resolved instantly thereafter.
15
+ */
16
+ export declare function createServerFnEventHandler(appInjector: Injector | Promise<Injector>): EventHandler;
17
+ /**
18
+ * Decode a server-function request, dispatch it, and write the result to the
19
+ * h3 response. Same-origin, method, content-type, validation, and interceptors
20
+ * are enforced inside `dispatchServerFn`; this owns only the h3 I/O around it.
21
+ */
22
+ export declare function handleServerFnRequest(event: H3Event, appInjector: Injector | Promise<Injector>): Promise<unknown>;
@@ -0,0 +1,30 @@
1
+ import { InjectionToken, type Provider } from '@angular/core';
2
+ import type { ServerFnContext } from '@analogjs/router';
3
+ /** Context threaded through the interceptor chain and handed to the handler. */
4
+ export interface ServerFnInterceptorContext {
5
+ readonly input: unknown;
6
+ readonly context: ServerFnContext;
7
+ /** Return a new context with additional typed fields merged in. */
8
+ with(patch: Partial<ServerFnContext> & Record<string, unknown>): ServerFnInterceptorContext;
9
+ }
10
+ export type ServerFnNext = (ctx: ServerFnInterceptorContext) => Promise<unknown>;
11
+ /** Functional interceptor, modeled on `HttpInterceptorFn`. */
12
+ export type ServerFnInterceptorFn = (ctx: ServerFnInterceptorContext, next: ServerFnNext) => Promise<unknown> | unknown;
13
+ export declare const SERVER_FN_INTERCEPTORS: InjectionToken<ServerFnInterceptorFn[]>;
14
+ export interface ServerFnsFeature {
15
+ providers: Provider[];
16
+ }
17
+ /** `withServerFnInterceptors([...])` — registers the chain (DI, ordered). */
18
+ export declare function withServerFnInterceptors(interceptors: ServerFnInterceptorFn[]): ServerFnsFeature;
19
+ /** `provideServerFns(withServerFnInterceptors(...))` — mirrors provideHttpClient. */
20
+ export declare function provideServerFns(...features: ServerFnsFeature[]): Provider[];
21
+ /**
22
+ * Run the interceptor chain, then the handler, threading the context.
23
+ *
24
+ * `runInCtx` re-establishes the DI injection context around each interceptor
25
+ * and the handler individually. This is what keeps `inject()` working in a
26
+ * handler even when an upstream interceptor `await`s before calling `next`
27
+ * (which would otherwise resume outside Angular's synchronous injection
28
+ * context). It defaults to a pass-through for non-DI callers/tests.
29
+ */
30
+ export declare function runInterceptors(interceptors: ServerFnInterceptorFn[], input: unknown, handler: (input: unknown, context: ServerFnContext) => Promise<unknown> | unknown, runInCtx?: <T>(fn: () => T) => T): Promise<unknown>;
@@ -0,0 +1,14 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { H3Event } from 'nitro/h3';
3
+ type NodeContext = NonNullable<H3Event['node']>;
4
+ type NodeRuntimeContext = NodeContext & {
5
+ req: IncomingMessage;
6
+ res: ServerResponse;
7
+ };
8
+ /**
9
+ * Dispatch provides the Node request and response through `REQUEST` and
10
+ * `RESPONSE`, which are typed as Node primitives, so server functions only run
11
+ * on a Node runtime. h3 leaves `node` undefined on other runtimes.
12
+ */
13
+ export declare function assertNodeContext(event: Pick<H3Event, 'node'>): NodeRuntimeContext;
14
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { ServerFnDef } from '@analogjs/router';
2
+ /**
3
+ * Server-side registry of server functions, keyed by id. A `.server.ts` module
4
+ * populates it as a side effect of `serverFn(...)` running at import time; the
5
+ * Nitro dispatch route imports those modules to fill it, then looks up by id.
6
+ */
7
+ export declare const serverFnRegistry: Map<string, ServerFnDef>;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Same-origin enforcement for the server-function HTTP transport.
3
+ *
4
+ * Server functions are same-origin RPC: a client proxy only ever calls the
5
+ * relative `/_analog/fn/:id` URL of its own app. A cross-origin page must not be
6
+ * able to invoke them against a logged-in user (a CSRF-shaped attack), so the
7
+ * transport rejects browser requests whose origin is not the app's own — out of
8
+ * the box, with no per-app configuration.
9
+ *
10
+ * The signals used (`Sec-Fetch-Site`, `Origin`) are added by the browser and
11
+ * cannot be forged by a cross-origin page's `fetch`. Non-browser callers (curl,
12
+ * server-to-server, SSR in-process) send neither, so they are unaffected: the
13
+ * guard blocks the cross-origin browser attack it is meant to, and nothing else.
14
+ */
15
+ import { InjectionToken } from '@angular/core';
16
+ import type { ServerFnsFeature } from './interceptors';
17
+ /** Node/h3 header bag shape (`IncomingHttpHeaders`). */
18
+ export type HeaderBag = Record<string, string | string[] | undefined>;
19
+ /**
20
+ * Origins permitted beyond the app's own, registered through DI:
21
+ * `provideServerFns(withAllowedOrigins([...]))`. Empty by default — the
22
+ * transport is same-origin unless an app opts out explicitly.
23
+ */
24
+ export declare const SERVER_FN_ALLOWED_ORIGINS: InjectionToken<string[]>;
25
+ /**
26
+ * `withAllowedOrigins([...])` — permit cross-origin browser calls from the
27
+ * listed origins, or pass `'*'` to disable the same-origin guard entirely.
28
+ * Server functions are frequently cookie-authenticated, so this is an explicit
29
+ * opt-out of CSRF protection: allow-list the exact origins you control.
30
+ */
31
+ export declare function withAllowedOrigins(origins: string[]): ServerFnsFeature;
32
+ /**
33
+ * Whether an HTTP request to a server function may proceed.
34
+ *
35
+ * Allowed when the request is same-origin, carries no browser-origin signal at
36
+ * all (a non-browser client, or a same-origin GET that omits `Origin`), or its
37
+ * `Origin` is listed in `allowedOrigins`. Passing `'*'` in `allowedOrigins`
38
+ * disables the check — the explicit opt-in to cross-origin access.
39
+ *
40
+ * `Sec-Fetch-Site` is the authoritative signal when present: `same-origin` and
41
+ * `none` (a direct navigation, not a cross-site fetch) pass; `same-site` and
42
+ * `cross-site` require an explicit `allowedOrigins` entry. When the header is
43
+ * absent (older browsers, some proxies) the `Origin` host is compared to the
44
+ * request host as a fallback.
45
+ */
46
+ export declare function isServerFnOriginAllowed(headers: HeaderBag, allowedOrigins?: readonly string[]): boolean;
@@ -0,0 +1,21 @@
1
+ import type { ServerFn, ServerFnConfig, ServerFnHandler, StandardSchemaV1 } from '@analogjs/router';
2
+ /**
3
+ * Define a server function. Authored in a `*.server.ts` module.
4
+ *
5
+ * Three call shapes, chosen for ergonomics — they all normalize to the same
6
+ * `(config, handler)` form and the build transform derives the route id for each:
7
+ *
8
+ * ```ts
9
+ * serverFn(() => inject(Svc).list()); // input-less GET
10
+ * serverFn(schema, (input) => …); // schema ⇒ POST + input
11
+ * serverFn({ method: 'POST' }, () => …); // explicit config
12
+ * ```
13
+ *
14
+ * On the server the function self-registers and its handler runs via
15
+ * `dispatchServerFn`. On the client the build transform replaces the body with a
16
+ * proxy that calls `/_analog/fn/<id>`; the reference still carries
17
+ * `id`/`url`/`method` so `injectServerFn`/`ServerFnClient` can dispatch.
18
+ */
19
+ export declare function serverFn<Out>(handler: ServerFnHandler<void, Out>): ServerFn<void, Out>;
20
+ export declare function serverFn<In, Out>(input: StandardSchemaV1<In>, handler: ServerFnHandler<In, Out>): ServerFn<In, Out>;
21
+ export declare function serverFn<In, Out>(config: ServerFnConfig<In>, handler: ServerFnHandler<In, Out>): ServerFn<In, Out>;
@@ -0,0 +1,17 @@
1
+ import type { ServerRequest, ServerResponse } from '@analogjs/router/tokens';
2
+ import type { ServerFnDispatcher } from '@analogjs/router';
3
+ /**
4
+ * The in-process transport used during SSR. `ServerFnClient` picks this up from
5
+ * DI and calls the handler directly instead of issuing an HTTP request back
6
+ * into the app — the render and the handler already share a process and a
7
+ * request, so the round-trip only adds latency (and would need an absolute URL).
8
+ *
9
+ * `method` is deliberately not passed to `dispatchServerFn`: this is a trusted
10
+ * in-process caller, so the HTTP-transport-only checks (same-origin, method
11
+ * enforcement, content type) do not apply. Validation and the interceptor chain
12
+ * still run, so an SSR call behaves like a browser call in every other respect.
13
+ *
14
+ * A non-2xx result is thrown as an `HttpErrorResponse` so the failure surfaces
15
+ * on `resource.error()` exactly as it does in the browser.
16
+ */
17
+ export declare function createServerFnDispatcher(req: ServerRequest, res: ServerResponse): ServerFnDispatcher;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Nulls `def.tView` on every component definition that Angular has
3
+ * compiled in this process. Angular caches the result of `consts()` on
4
+ * `def.tView` — that factory is where `$localize` tagged templates are
5
+ * evaluated — so without this reset the first rendered locale would be
6
+ * frozen into the cache for the process lifetime.
7
+ *
8
+ * The set on `globalThis.__ngComponentDefs` is populated by a Vite
9
+ * transform in `@analogjs/platform` that patches `@angular/core`'s
10
+ * `getComponentId()` to mirror every compiled component definition to
11
+ * a global Set, bypassing the `ngServerMode` guard that normally
12
+ * prevents registration on the server.
13
+ */
14
+ export declare function resetComponentDefTViews(): void;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Pure string helpers for slicing a fully rendered SSR document into the parts
3
+ * the streaming renderer flushes: the shell up to `<body>`, the authoritative
4
+ * `<body>` inner HTML for the tail, and the authoritative `<head>` inner HTML
5
+ * for the finalize-time head reconcile. Extracted from `render-stream` so they
6
+ * can be unit tested without driving the platform.
7
+ */
8
+ /** Byte offset just after the opening `<body>` tag, or 0 if none. */
9
+ export declare function afterBodyOpen(html: string): number;
10
+ /** Inner HTML of `<body>` from a fully rendered document string. */
11
+ export declare function bodyInner(html: string): string;
12
+ /** Inner HTML of `<head>` from a fully rendered document string. */
13
+ export declare function headInner(html: string): string;
@@ -0,0 +1,24 @@
1
+ import type { ServerContext } from '@analogjs/router/tokens';
2
+ /**
3
+ * Per-request decisions about whether the streaming renderer should fall back
4
+ * to a buffered render. Extracted from `render-stream` so they can be unit
5
+ * tested without driving the platform.
6
+ */
7
+ /**
8
+ * User agents that receive a fully buffered render (with a resolved `<head>`)
9
+ * instead of the streamed shell. Streaming flushes the head before the app has
10
+ * set a dynamic title/meta and reconciles it via a finalize script; a crawler
11
+ * that does not run that script would index the shell's static head. Mirrors
12
+ * Nuxt's bot bypass — streaming targets interactive clients, bots get the
13
+ * buffered path whose head is byte-identical to the classic `render()`.
14
+ */
15
+ export declare const SSR_BOT_RE: RegExp;
16
+ export declare function isLikelyBot(serverContext: ServerContext): boolean;
17
+ /**
18
+ * Whether streaming is disabled for this request by a `streaming: false` route
19
+ * rule. The platform plugin translates that rule into an `x-analog-no-streaming`
20
+ * response header (mirroring how `ssr: false` becomes `x-analog-no-ssr`); when
21
+ * present, `renderStream` produces the buffered `render()` output for this
22
+ * route instead of streaming.
23
+ */
24
+ export declare function streamingDisabledByRoute(serverContext: ServerContext): boolean;
@@ -1,16 +1,30 @@
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
- export { ServerOnly } from './lib/server.component';
17
+ export type { AnalogJsonLdDocument } from './lib/json-ld';
18
+ export { issuesToFieldErrors, issuesToFormErrors, issuePathToFieldName, } from './lib/validation-errors';
19
+ export type { ValidationFieldErrors } from './lib/validation-errors';
20
+ export { injectServerFn, injectServerFnMutation, provideServerFnClient, ServerFnClient, } from './lib/server-fn/inject-server-fn';
21
+ export { createServerFnRef, type ServerFnRefConfig, } from './lib/server-fn/server-fn-ref';
22
+ export { SERVER_FN_DISPATCHER, type ServerFnDispatcher, } from './lib/server-fn/dispatcher';
23
+ export type { ServerFn, ServerFnConfig, ServerFnContext, ServerFnDef, ServerFnHandler, ServerFnMethod, StandardSchemaV1, } from './lib/server-fn/types';
24
+ export type { AnalogRouteTable, AnalogRoutePath, RoutePathOptions, RoutePathArgs, RoutePathOptionsBase, RouteParamsOutput, RouteQueryOutput, RouteLinkResult, } from './lib/route-path';
25
+ export { routePath } from './lib/route-path';
26
+ export { injectNavigate } from './lib/inject-navigate';
27
+ export { withTypedRouter, withRouteContext, withLoaderCaching, EXPERIMENTAL_TYPED_ROUTER, EXPERIMENTAL_ROUTE_CONTEXT, EXPERIMENTAL_LOADER_CACHE, } from './lib/experimental';
28
+ export type { TypedRouterOptions, LoaderCacheOptions, } from './lib/experimental';
29
+ export { injectParams, injectQuery } from './lib/inject-typed-params';
30
+ 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;