@analogjs/router 3.0.0-alpha.63 → 3.0.0-alpha.65

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 (30) hide show
  1. package/fesm2022/analogjs-router-server.mjs +684 -112
  2. package/fesm2022/analogjs-router-server.mjs.map +1 -1
  3. package/fesm2022/analogjs-router.mjs +133 -131
  4. package/fesm2022/analogjs-router.mjs.map +1 -1
  5. package/fesm2022/route-files.mjs.map +1 -1
  6. package/package.json +4 -4
  7. package/types/server/src/defer-reconcile-runtime.d.ts +23 -0
  8. package/types/server/src/index.d.ts +9 -2
  9. package/types/server/src/render-stream.d.ts +40 -0
  10. package/types/server/src/render.d.ts +2 -2
  11. package/types/server/src/server-fn/app-injector.d.ts +30 -0
  12. package/types/server/src/server-fn/dispatch.d.ts +56 -0
  13. package/types/server/src/server-fn/event-handler.d.ts +22 -0
  14. package/types/server/src/server-fn/interceptors.d.ts +30 -0
  15. package/types/server/src/server-fn/node-context.d.ts +14 -0
  16. package/types/server/src/server-fn/registry.d.ts +7 -0
  17. package/types/server/src/server-fn/same-origin.d.ts +46 -0
  18. package/types/server/src/server-fn/server-fn.d.ts +21 -0
  19. package/types/server/src/server-fn/ssr-dispatcher.d.ts +17 -0
  20. package/types/server/src/utils/reset-component-def-tviews.d.ts +14 -0
  21. package/types/server/src/utils/stream-html.d.ts +13 -0
  22. package/types/server/src/utils/stream-request.d.ts +24 -0
  23. package/types/src/index.d.ts +4 -1
  24. package/types/src/lib/server-fn/dispatcher.d.ts +23 -0
  25. package/types/src/lib/server-fn/inject-server-fn.d.ts +44 -0
  26. package/types/src/lib/server-fn/server-fn-ref.d.ts +24 -0
  27. package/types/src/lib/server-fn/types.d.ts +55 -0
  28. package/types/server/src/server-component-render.d.ts +0 -4
  29. package/types/server/src/tokens.d.ts +0 -7
  30. package/types/src/lib/server.component.d.ts +0 -33
@@ -7,6 +7,6 @@ import type { ServerContext } from '../../tokens/src/index.js';
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;
@@ -14,10 +14,13 @@ export { FormAction } from './lib/form-action.directive';
14
14
  export type { FormActionState } from './lib/form-action.directive';
15
15
  export { injectDebugRoutes } from './lib/debug/routes';
16
16
  export { withDebugRoutes } from './lib/debug';
17
- export { ServerOnly } from './lib/server.component';
18
17
  export type { AnalogJsonLdDocument } from './lib/json-ld';
19
18
  export { issuesToFieldErrors, issuesToFormErrors, issuePathToFieldName, } from './lib/validation-errors';
20
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';
21
24
  export type { AnalogRouteTable, AnalogRoutePath, RoutePathOptions, RoutePathArgs, RoutePathOptionsBase, RouteParamsOutput, RouteQueryOutput, RouteLinkResult, } from './lib/route-path';
22
25
  export { routePath } from './lib/route-path';
23
26
  export { injectNavigate } from './lib/inject-navigate';
@@ -0,0 +1,23 @@
1
+ import { InjectionToken, type Injector } from '@angular/core';
2
+ import type { ServerFn } from './types';
3
+ /**
4
+ * In-process transport for a server function call.
5
+ *
6
+ * Provided on the server by `provideServerContext`, so during SSR a server
7
+ * function runs in the same process — and the same request injector — as the
8
+ * render instead of making an HTTP request back into the app. Absent in the
9
+ * browser, where `ServerFnClient` falls back to `HttpClient`.
10
+ *
11
+ * `injector` is the **app environment injector** — `ServerFnClient` is
12
+ * `providedIn: 'root'`, and SSR bootstraps a fresh application per request, so
13
+ * its injector is both per-request and the right scope for a handler to resolve
14
+ * from. It is passed rather than captured from the token because
15
+ * `provideServerContext` is applied as *platform* providers, which sit above
16
+ * the app's `providedIn: 'root'` services.
17
+ *
18
+ * Deliberately not a component's node injector: a handler resolves app-level
19
+ * services, and making that depend on which component happened to call it would
20
+ * be surprising and unportable.
21
+ */
22
+ export type ServerFnDispatcher = <In, Out>(fn: ServerFn<In, Out>, input: In, injector: Injector) => Promise<Out>;
23
+ export declare const SERVER_FN_DISPATCHER: InjectionToken<ServerFnDispatcher>;
@@ -0,0 +1,44 @@
1
+ import { type ResourceRef, type StateKey } from '@angular/core';
2
+ import type { ServerFn } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Client transport for server functions. In the browser it goes through Angular
6
+ * `HttpClient`, so client `HttpInterceptorFn`s apply. During SSR the dispatcher
7
+ * token is provided, and the call short-circuits the HTTP round-trip: the
8
+ * handler runs in-process in the current request injector. Lives in the client
9
+ * entry (client-safe).
10
+ */
11
+ export declare class ServerFnClient {
12
+ private readonly http;
13
+ private readonly transferState;
14
+ private readonly injector;
15
+ private readonly dispatcher;
16
+ /** True while rendering on the server (the in-process dispatcher is provided). */
17
+ get isServer(): boolean;
18
+ call<In, Out>(fn: ServerFn<In, Out>, input: In): Promise<Out>;
19
+ /** Key a read's value for TransferState hydration (fn id + input). */
20
+ stateKey<Out>(fn: ServerFn<unknown, Out>, input: unknown): StateKey<Out>;
21
+ readSeed<Out>(fn: ServerFn<unknown, Out>, input: unknown): Out | undefined;
22
+ writeSeed<Out>(fn: ServerFn<unknown, Out>, input: unknown, value: Out): void;
23
+ static ɵfac: i0.ɵɵFactoryDeclaration<ServerFnClient, never>;
24
+ static ɵprov: i0.ɵɵInjectableDeclaration<ServerFnClient>;
25
+ }
26
+ /** No-op provider hook; ServerFnClient is `providedIn: 'root'`. */
27
+ export declare function provideServerFnClient(): readonly [];
28
+ /**
29
+ * Reactive read of a server function as an Angular `resource()`.
30
+ *
31
+ * `args` is optional: omit it for an input-less read (the resource loads once);
32
+ * provide it for an input-bearing read (returning `undefined` from `args` leaves
33
+ * the resource idle until inputs are ready, the standard resource pattern). For
34
+ * imperative calls (mutations, event handlers) use `injectServerFnMutation`.
35
+ */
36
+ export declare function injectServerFn<Out>(fn: ServerFn<void, Out>): ResourceRef<Out | undefined>;
37
+ export declare function injectServerFn<In, Out>(fn: ServerFn<In, Out>, args: () => In | undefined): ResourceRef<Out | undefined>;
38
+ /**
39
+ * Imperative binding of a server function: returns a callable that dispatches
40
+ * the call through `HttpClient` (so client interceptors apply) and resolves the
41
+ * result. Use for mutations and event-driven calls; use `injectServerFn` for
42
+ * reactive reads.
43
+ */
44
+ export declare function injectServerFnMutation<In, Out>(fn: ServerFn<In, Out>): (input: In) => Promise<Out>;
@@ -0,0 +1,24 @@
1
+ import type { ServerFn, ServerFnMethod } from './types';
2
+ export interface ServerFnRefConfig {
3
+ id?: string;
4
+ method?: ServerFnMethod;
5
+ /**
6
+ * Only its presence matters here: when `method` is omitted, a config with an
7
+ * `input` schema defaults to `POST`, otherwise `GET`. The schema itself is
8
+ * never used to build the ref — validation happens server-side.
9
+ */
10
+ input?: unknown;
11
+ }
12
+ /**
13
+ * Builds a server-function reference: the client-safe `{ __serverFn, id, url,
14
+ * method }` metadata that `injectServerFn`/`ServerFnClient` dispatch through.
15
+ *
16
+ * Shared by both sides so they produce identical refs: the server `serverFn`
17
+ * wraps this with registration + the handler, and the client build's scrub
18
+ * transform emits a call to this factory in place of the server module so the
19
+ * browser bundle carries only the ref, never the handler or its server imports.
20
+ *
21
+ * The returned value is callable-typed but throws if invoked directly — it is
22
+ * always dispatched via `injectServerFn`/`ServerFnClient`, never called.
23
+ */
24
+ export declare function createServerFnRef<In, Out>(config: ServerFnRefConfig): ServerFn<In, Out>;
@@ -0,0 +1,55 @@
1
+ /** Minimal Standard Schema shape (valibot/zod/arktype conform). */
2
+ export interface StandardSchemaV1<In = unknown> {
3
+ readonly '~standard': {
4
+ readonly version: 1;
5
+ readonly vendor: string;
6
+ validate: (value: unknown) => {
7
+ value: In;
8
+ issues?: undefined;
9
+ } | {
10
+ issues: ReadonlyArray<{
11
+ message: string;
12
+ }>;
13
+ } | Promise<{
14
+ value: In;
15
+ issues?: undefined;
16
+ } | {
17
+ issues: ReadonlyArray<{
18
+ message: string;
19
+ }>;
20
+ }>;
21
+ };
22
+ }
23
+ export type ServerFnMethod = 'GET' | 'POST';
24
+ export interface ServerFnConfig<In> {
25
+ /**
26
+ * Opaque route id `/_analog/fn/<id>`. **Build-injected, not author-supplied:**
27
+ * the Analog transform derives `hash(fileId + exportName)` and stamps it into
28
+ * both the server registration and the client proxy, so authors never choose a
29
+ * route. Absent at runtime means the transform did not run — `serverFn` throws.
30
+ */
31
+ id?: string;
32
+ /** Defaults to 'POST' when `input` is present, otherwise 'GET'. */
33
+ method?: ServerFnMethod;
34
+ input?: StandardSchemaV1<In>;
35
+ }
36
+ /**
37
+ * Interceptor-accumulated context, delivered to the handler as its second
38
+ * argument. Apps extend this by declaration merging.
39
+ */
40
+ export interface ServerFnContext {
41
+ }
42
+ /** A server function reference: callable type on both sides; real impl only on the server. */
43
+ export type ServerFn<In, Out> = ((input: In) => Promise<Out>) & {
44
+ readonly __serverFn: true;
45
+ readonly id: string;
46
+ readonly url: string;
47
+ readonly method: ServerFnMethod;
48
+ };
49
+ export type ServerFnHandler<In, Out> = (input: In, context: ServerFnContext) => Promise<Out> | Out;
50
+ export interface ServerFnDef {
51
+ id: string;
52
+ method: ServerFnMethod;
53
+ config: ServerFnConfig<unknown>;
54
+ handler: ServerFnHandler<unknown, unknown>;
55
+ }
@@ -1,4 +0,0 @@
1
- import { ApplicationConfig } from '@angular/core';
2
- import type { ServerContext } from '../../tokens/src/index.js';
3
- export declare function serverComponentRequest(serverContext: ServerContext): string | undefined;
4
- export declare function renderServerComponent(url: string, serverContext: ServerContext, config?: ApplicationConfig): Promise<Response>;
@@ -1,7 +0,0 @@
1
- import { InjectionToken, Provider } from '@angular/core';
2
- export declare const STATIC_PROPS: InjectionToken<Record<string, any>>;
3
- export declare function provideStaticProps<T = Record<string, any>>(props: T): Provider;
4
- export declare function injectStaticProps(): Record<string, any>;
5
- export declare function injectStaticOutputs<T>(): {
6
- set(data: T): void;
7
- };
@@ -1,33 +0,0 @@
1
- import { InputSignal, OutputEmitterRef, WritableSignal } from '@angular/core';
2
- import { SafeHtml } from '@angular/platform-browser';
3
- import * as i0 from "@angular/core";
4
- type ServerProps = Record<string, any>;
5
- type ServerOutputs = Record<string, any>;
6
- /**
7
- * @description
8
- * Component that defines the bridge between the client and server-only
9
- * components. The component passes the component ID and props to the server
10
- * and retrieves the rendered HTML and outputs from the server-only component.
11
- *
12
- * Status: experimental
13
- */
14
- export declare class ServerOnly {
15
- component: InputSignal<string>;
16
- props: InputSignal<ServerProps | undefined>;
17
- outputs: OutputEmitterRef<ServerOutputs>;
18
- private http;
19
- private sanitizer;
20
- protected content: WritableSignal<SafeHtml>;
21
- private route;
22
- private baseURL;
23
- private transferState;
24
- constructor();
25
- updateContent(content: {
26
- html: string;
27
- outputs: ServerOutputs;
28
- }): void;
29
- getComponentUrl(componentId: string): string;
30
- static ɵfac: i0.ɵɵFactoryDeclaration<ServerOnly, never>;
31
- static ɵcmp: i0.ɵɵComponentDeclaration<ServerOnly, "server-only,ServerOnly,Server", never, { "component": { "alias": "component"; "required": true; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, { "outputs": "outputs"; }, never, never, true, never>;
32
- }
33
- export {};