@solidjs/web 2.0.0-beta.20 → 2.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.cjs +7 -0
- package/dist/dev.js +7 -0
- package/dist/web.cjs +7 -0
- package/dist/web.js +7 -0
- package/package.json +3 -3
- package/server-functions/dist/client.cjs +114 -36
- package/server-functions/dist/client.js +109 -37
- package/server-functions/dist/server.cjs +95 -5
- package/server-functions/dist/server.js +90 -6
- package/types/server-functions/client.d.ts +93 -19
- package/types/server-functions/server.d.ts +134 -15
- package/types/server-functions/shared.d.ts +171 -0
- package/types-cjs/server-functions/client.d.cts +93 -19
- package/types-cjs/server-functions/server.d.cts +134 -15
- package/types-cjs/server-functions/shared.d.cts +171 -0
|
@@ -2,7 +2,24 @@ import { ResponseEnvelope } from "../response.js";
|
|
|
2
2
|
import { JSONCodecOptions } from "../serializer.js";
|
|
3
3
|
import { RequestEvent } from "../server.js";
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
FUNCTION_HEADER,
|
|
7
|
+
INSTANCE_HEADER,
|
|
8
|
+
SINGLE_FLIGHT_HEADER,
|
|
9
|
+
decodeResponse,
|
|
10
|
+
getServerFunctionMetadata,
|
|
11
|
+
isServerFunction,
|
|
12
|
+
subscribeFlightData,
|
|
13
|
+
withMeta
|
|
14
|
+
} from "./shared.js";
|
|
15
|
+
export type {
|
|
16
|
+
FlightDataConsumer,
|
|
17
|
+
FlightDataContext,
|
|
18
|
+
ServerFunction,
|
|
19
|
+
ServerFunctionMetadata,
|
|
20
|
+
SingleFlightPayload
|
|
21
|
+
} from "./shared.js";
|
|
22
|
+
import { ServerFunction } from "./shared.js";
|
|
6
23
|
|
|
7
24
|
/**
|
|
8
25
|
* The request event a server function call runs under: the base
|
|
@@ -13,6 +30,58 @@ export interface ServerFunctionEvent extends RequestEvent {
|
|
|
13
30
|
serverOnly?: boolean;
|
|
14
31
|
}
|
|
15
32
|
|
|
33
|
+
/**
|
|
34
|
+
* What a server function call resolved to, as seen by the single-flight
|
|
35
|
+
* hook — enough context for any data-production strategy without core
|
|
36
|
+
* assuming one.
|
|
37
|
+
*/
|
|
38
|
+
export interface ServerFunctionOutcome {
|
|
39
|
+
/** The build-stable id of the function that ran. */
|
|
40
|
+
id: string;
|
|
41
|
+
/**
|
|
42
|
+
* The value the caller will receive: the raw return for plain results,
|
|
43
|
+
* the unwrapped `value` for `ResponseEnvelope`s, `null` for body-less
|
|
44
|
+
* control-flow `Response`s (redirect/reload).
|
|
45
|
+
*/
|
|
46
|
+
value: unknown;
|
|
47
|
+
/**
|
|
48
|
+
* The `Response` carrying the result's HTTP metadata, when there is one
|
|
49
|
+
* (from a returned/thrown `Response` or a `ResponseEnvelope`). Read
|
|
50
|
+
* `Location` here for redirect-with-data — the data should describe the
|
|
51
|
+
* destination route — and `X-Revalidate` for the invalidated keys.
|
|
52
|
+
* Undefined for plain values.
|
|
53
|
+
*/
|
|
54
|
+
response: Response | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The original HTTP request, untouched: headers the client integration
|
|
57
|
+
* sent (referrer, custom route context) ride here for the hook to read —
|
|
58
|
+
* core assigns them no meaning.
|
|
59
|
+
*/
|
|
60
|
+
request: Request;
|
|
61
|
+
/** Whether the result was thrown rather than returned. */
|
|
62
|
+
thrown: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The single-flight server hook: given the request event and the function's
|
|
67
|
+
* outcome, optionally produce a data payload (possibly async) to fold into
|
|
68
|
+
* the response alongside the return value. Data production is a black box
|
|
69
|
+
* to the protocol — render data-only, run route preloads, query a cache,
|
|
70
|
+
* whatever the integration chooses; the payload just has to be
|
|
71
|
+
* codec-serializable. Return undefined to send the response unchanged
|
|
72
|
+
* (byte-identical to a call without the hook).
|
|
73
|
+
*
|
|
74
|
+
* Runs after `transformResult`, only for scripted calls that sent
|
|
75
|
+
* `SINGLE_FLIGHT_HEADER` on the request, on returned results and thrown
|
|
76
|
+
* `Response`/`ResponseEnvelope` control-flow signals alike (plain thrown
|
|
77
|
+
* errors never collect). The handler owns the enveloping: contributed data
|
|
78
|
+
* ships as `{ value, data }` under the single-flight response header.
|
|
79
|
+
*/
|
|
80
|
+
export type CollectFlightDataHook = (
|
|
81
|
+
event: ServerFunctionEvent,
|
|
82
|
+
outcome: ServerFunctionOutcome
|
|
83
|
+
) => unknown | Promise<unknown>;
|
|
84
|
+
|
|
16
85
|
/** Options for `configureServerFunctionsServer`. */
|
|
17
86
|
export interface ServerFunctionsServerConfig {
|
|
18
87
|
/**
|
|
@@ -23,6 +92,13 @@ export interface ServerFunctionsServerConfig {
|
|
|
23
92
|
* an established request scope parks on the global.
|
|
24
93
|
*/
|
|
25
94
|
provideEvent?: <T>(event: ServerFunctionEvent, fn: () => T) => T;
|
|
95
|
+
/**
|
|
96
|
+
* The single-flight hook: produces the data payload folded into
|
|
97
|
+
* responses of calls that opted in (see `CollectFlightDataHook`).
|
|
98
|
+
* Registered once by the integration that owns data production (a
|
|
99
|
+
* router); per-handler `collectFlightData` options override it.
|
|
100
|
+
*/
|
|
101
|
+
collectFlightData?: CollectFlightDataHook;
|
|
26
102
|
/**
|
|
27
103
|
* Endpoint the HTTP handler is mounted on, used for the `url` of SSR'd
|
|
28
104
|
* references (e.g. form actions) — must match the client configuration.
|
|
@@ -42,7 +118,8 @@ export interface ServerFunctionsServerConfig {
|
|
|
42
118
|
/**
|
|
43
119
|
* Configures the server runtime. Call once at server startup, before
|
|
44
120
|
* handling requests. Only needed when deviating from the defaults (custom
|
|
45
|
-
* endpoint, codec plugins,
|
|
121
|
+
* endpoint, codec plugins, an explicit event provider, or a single-flight
|
|
122
|
+
* hook).
|
|
46
123
|
*/
|
|
47
124
|
export function configureServerFunctionsServer(config?: ServerFunctionsServerConfig): void;
|
|
48
125
|
|
|
@@ -57,6 +134,12 @@ export function configureServerFunctionsServer(config?: ServerFunctionsServerCon
|
|
|
57
134
|
export interface ServerFunctionReference<T extends any[] = any[], R = any> {
|
|
58
135
|
id: string;
|
|
59
136
|
fn: (...args: T) => R;
|
|
137
|
+
/**
|
|
138
|
+
* The function's source name, emitted by development builds only —
|
|
139
|
+
* `createServerReference` seeds the metadata channel with it.
|
|
140
|
+
* @internal
|
|
141
|
+
*/
|
|
142
|
+
name?: string;
|
|
60
143
|
}
|
|
61
144
|
|
|
62
145
|
/**
|
|
@@ -82,12 +165,15 @@ export function getServerFunction<T extends any[], R>(id: string): (...args: T)
|
|
|
82
165
|
* Compiler ABI — emitted by compiled `"use server"` server output for
|
|
83
166
|
* every server function: registers `fn` for HTTP dispatch under its
|
|
84
167
|
* build-stable id and returns the reference the server-side
|
|
85
|
-
* `createServerReference` consumes.
|
|
168
|
+
* `createServerReference` consumes. Development builds pass the function's
|
|
169
|
+
* source name as the trailing argument (dev-only metadata; never emitted in
|
|
170
|
+
* production). Not meant for hand-written code.
|
|
86
171
|
* @internal
|
|
87
172
|
*/
|
|
88
173
|
export function registerServerReference<T extends any[], R>(
|
|
89
174
|
id: string,
|
|
90
|
-
fn: (...args: T) => R
|
|
175
|
+
fn: (...args: T) => R,
|
|
176
|
+
name?: string
|
|
91
177
|
): ServerFunctionReference<T, R>;
|
|
92
178
|
|
|
93
179
|
/**
|
|
@@ -102,6 +188,29 @@ export function createServerReference<T extends any[], R>(
|
|
|
102
188
|
reference: ServerFunctionReference<T, R>
|
|
103
189
|
): (...args: T) => R;
|
|
104
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Declares a server function callable over HTTP GET. The server half is
|
|
193
|
+
* identity-flavored — SSR calls stay in-process — but it brands the
|
|
194
|
+
* declaration on the reference's metadata channel
|
|
195
|
+
* (`getServerFunctionMetadata(fn)?.method === "GET"`) and records the
|
|
196
|
+
* declared method for the function's id so `handleServerFunctionRequest`
|
|
197
|
+
* enforces it: GET-declared functions accept GET requests (and only GET),
|
|
198
|
+
* everything else answers 405.
|
|
199
|
+
*
|
|
200
|
+
* Wrap the reference at its declaration; the compiler round-trips the call
|
|
201
|
+
* in both builds:
|
|
202
|
+
*
|
|
203
|
+
* ```ts
|
|
204
|
+
* export const getUser = GET(async (id: string) => {
|
|
205
|
+
* "use server";
|
|
206
|
+
* return db.users.find(id);
|
|
207
|
+
* });
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export function GET<A extends readonly any[], R>(
|
|
211
|
+
fn: (...args: A) => R
|
|
212
|
+
): ServerFunction<A, Awaited<R>>;
|
|
213
|
+
|
|
105
214
|
/** Identity of the currently executing server function. */
|
|
106
215
|
export interface ServerFunctionMeta {
|
|
107
216
|
id: string;
|
|
@@ -133,17 +242,26 @@ export interface HandleServerFunctionOptions {
|
|
|
133
242
|
provideEvent?<T>(event: ServerFunctionEvent, fn: () => T): T;
|
|
134
243
|
/**
|
|
135
244
|
* Observes or replaces the function's result before encoding — the
|
|
136
|
-
* extension point for
|
|
137
|
-
* returned and thrown results alike
|
|
138
|
-
* `context.instance` is null for no-JS
|
|
139
|
-
* unchanged to pass through, or a
|
|
140
|
-
* the core entry) to send HTTP
|
|
245
|
+
* extension point for response metadata policies (headers, statuses,
|
|
246
|
+
* substituted results). Runs for returned and thrown results alike
|
|
247
|
+
* (`context.thrown` distinguishes); `context.instance` is null for no-JS
|
|
248
|
+
* calls. Return the result unchanged to pass through, or a
|
|
249
|
+
* `ResponseEnvelope` (exposed through the core entry) to send HTTP
|
|
250
|
+
* metadata plus a structured payload. Runs before `collectFlightData`,
|
|
251
|
+
* so the flight hook sees the transformed outcome — use
|
|
252
|
+
* `collectFlightData`, not this, to fold data into the response.
|
|
141
253
|
*/
|
|
142
254
|
transformResult?(
|
|
143
255
|
event: ServerFunctionEvent,
|
|
144
256
|
result: unknown,
|
|
145
257
|
context: { instance: string | null; request: Request; thrown?: boolean }
|
|
146
258
|
): unknown | ResponseEnvelope | Promise<unknown | ResponseEnvelope>;
|
|
259
|
+
/**
|
|
260
|
+
* Overrides the configured single-flight hook for this handler — same
|
|
261
|
+
* contract as the `collectFlightData` config option (see
|
|
262
|
+
* `CollectFlightDataHook`).
|
|
263
|
+
*/
|
|
264
|
+
collectFlightData?: CollectFlightDataHook;
|
|
147
265
|
/**
|
|
148
266
|
* Builds the response for calls made without the client runtime (no
|
|
149
267
|
* instance header — no-JS form posts, direct HTTP) — the extension
|
|
@@ -164,12 +282,13 @@ export interface HandleServerFunctionOptions {
|
|
|
164
282
|
|
|
165
283
|
/**
|
|
166
284
|
* Web-standard HTTP handler for server function calls: resolves the
|
|
167
|
-
* function id from the request,
|
|
168
|
-
* a
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
285
|
+
* function id from the request, enforces the declared method (405 when the
|
|
286
|
+
* request method contradicts a `GET` declaration — or uses GET without
|
|
287
|
+
* one), decodes arguments, runs the function under a request-event scope,
|
|
288
|
+
* and encodes the result (forwarding redirect/revalidation metadata
|
|
289
|
+
* through headers). Mount it on the endpoint the client transport targets
|
|
290
|
+
* (default `/_server`); platform adapters (h3, express, ...) convert their
|
|
291
|
+
* request shape to a web `Request` around it.
|
|
173
292
|
*
|
|
174
293
|
* @example
|
|
175
294
|
* ```ts
|
|
@@ -38,6 +38,177 @@ export const FUNCTION_HEADER: string;
|
|
|
38
38
|
*/
|
|
39
39
|
export const INSTANCE_HEADER: string;
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Header driving the single-flight protocol on both legs
|
|
43
|
+
* (`"X-Single-Flight"`). On the request it opts the call into data
|
|
44
|
+
* collection — the transport sends it automatically on non-GET calls while
|
|
45
|
+
* a flight-data consumer is subscribed (subscribing IS the opt-in). On the
|
|
46
|
+
* response it marks a body carrying the standardized `SingleFlightPayload`.
|
|
47
|
+
* How the data is produced (a data-only render, running route preloads,
|
|
48
|
+
* anything else) and what it means is entirely the integration's business —
|
|
49
|
+
* the protocol only standardizes the wire shape and the delivery.
|
|
50
|
+
*/
|
|
51
|
+
export const SINGLE_FLIGHT_HEADER: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The standardized body of a single-flight response (a response tagged with
|
|
55
|
+
* `SINGLE_FLIGHT_HEADER`): the function's return `value` plus the
|
|
56
|
+
* integration-produced `data` payload, folded into one round trip by the
|
|
57
|
+
* HTTP handler. Integrations decoding passthrough responses themselves (no
|
|
58
|
+
* registered consumer) see this shape from `decodeResponse`. The top level
|
|
59
|
+
* is reserved for the protocol — integration payload lives entirely under
|
|
60
|
+
* `data`, which can be any codec-serializable value.
|
|
61
|
+
*/
|
|
62
|
+
export interface SingleFlightPayload<T = unknown, D = unknown> {
|
|
63
|
+
/** The server function's return (or thrown) value. */
|
|
64
|
+
value: T;
|
|
65
|
+
/** The integration-produced data payload. */
|
|
66
|
+
data: D;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Envelope context delivered alongside single-flight data: the transport
|
|
71
|
+
* response, whose headers carry the integration metadata (`Location` for
|
|
72
|
+
* redirect-with-data, `X-Revalidate` keys) and status. The body is already
|
|
73
|
+
* consumed — read `data` and `value` from the delivery, not from here.
|
|
74
|
+
*/
|
|
75
|
+
export interface FlightDataContext {
|
|
76
|
+
/** The HTTP response the data arrived on (metadata only). */
|
|
77
|
+
response: Response;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Consumer receiving single-flight data on the client: `data` is the
|
|
82
|
+
* integration-produced payload (opaque to the protocol), `context` carries
|
|
83
|
+
* the envelope metadata. Async consumers are awaited before the function
|
|
84
|
+
* value is returned to the caller, so caches are seeded first.
|
|
85
|
+
*/
|
|
86
|
+
export type FlightDataConsumer<D = unknown> = (
|
|
87
|
+
data: D,
|
|
88
|
+
context: FlightDataContext
|
|
89
|
+
) => void | Promise<void>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Registers the consumer the client transport delivers single-flight data
|
|
93
|
+
* to. Subscribing is the single-flight opt-in: while a consumer is
|
|
94
|
+
* registered the transport sends the request-leg `SINGLE_FLIGHT_HEADER` on
|
|
95
|
+
* non-GET calls (GET reads stay plain and cacheable), asking the server's
|
|
96
|
+
* collection hook to fold data into the response. When a single-flight
|
|
97
|
+
* response arrives, the transport decodes the standardized
|
|
98
|
+
* `{ value, data }` payload, delivers `data` (with the response as
|
|
99
|
+
* envelope context — redirect location, revalidation keys), and returns
|
|
100
|
+
* `value` to the caller as if the call were plain. What to do with the
|
|
101
|
+
* data (seed caches, navigate, ...) is entirely the consumer's business.
|
|
102
|
+
* One active consumer at a time — a later registration replaces the
|
|
103
|
+
* current one; returns an unsubscribe function. With no consumer
|
|
104
|
+
* registered, no header is sent and the server does no collection work;
|
|
105
|
+
* responses an integration opted in manually still pass through to the
|
|
106
|
+
* caller whole, exactly like other integration responses.
|
|
107
|
+
*/
|
|
108
|
+
export function subscribeFlightData<D = unknown>(consumer: FlightDataConsumer<D>): () => void;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The currently registered single-flight consumer.
|
|
112
|
+
*
|
|
113
|
+
* Transport building block; not meant for hand-written code.
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
export function getFlightDataConsumer(): FlightDataConsumer | undefined;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The public contract of a server function reference — what a `"use
|
|
120
|
+
* server"` import is at runtime on either side: an async callable plus its
|
|
121
|
+
* build-stable identity.
|
|
122
|
+
*/
|
|
123
|
+
export interface ServerFunction<A extends readonly any[] = any[], T = any> {
|
|
124
|
+
(...args: A): Promise<T>;
|
|
125
|
+
/** The build-stable function id (stable across the client and server builds). */
|
|
126
|
+
readonly id: string;
|
|
127
|
+
/** URL invoking this function directly over HTTP (form `action`s, raw fetches). */
|
|
128
|
+
readonly url: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Declaration-static metadata attached to a server function reference
|
|
133
|
+
* through declaration wrappers (`GET`, `withMeta`). Read it with
|
|
134
|
+
* `getServerFunctionMetadata`; routers and integrations detect capability
|
|
135
|
+
* from here instead of property sniffing, and `prepareRequest` receives it
|
|
136
|
+
* as `context.meta`. Write through `withMeta` — later writes shallow-merge
|
|
137
|
+
* over earlier ones.
|
|
138
|
+
*/
|
|
139
|
+
export interface ServerFunctionMetadata {
|
|
140
|
+
/** The declared HTTP method. Undeclared references call over POST. */
|
|
141
|
+
readonly method?: "GET" | "POST";
|
|
142
|
+
/**
|
|
143
|
+
* A human-readable label for the function, seeded by development builds
|
|
144
|
+
* from the compiled function's source name (dev tooling — inspectors,
|
|
145
|
+
* logs). Dev-only: production builds emit no name. Not unique and not an
|
|
146
|
+
* identity key — use `id` for identity. Seeded as a default: an explicit
|
|
147
|
+
* `withMeta` write wins.
|
|
148
|
+
*/
|
|
149
|
+
readonly name?: string;
|
|
150
|
+
/** User-declared transport metadata attached with `withMeta`. */
|
|
151
|
+
readonly [key: string]: unknown;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Reads a server function reference's declaration metadata — e.g.
|
|
156
|
+
* `getServerFunctionMetadata(fn)?.method === "GET"` detects a `GET(fn)`
|
|
157
|
+
* declaration. Returns undefined when `fn` is not a server function
|
|
158
|
+
* reference; plain references carry an empty metadata object. Works on
|
|
159
|
+
* client proxies and server-side references alike, across duplicated
|
|
160
|
+
* module instances (registered-symbol brand).
|
|
161
|
+
*/
|
|
162
|
+
export function getServerFunctionMetadata(fn: unknown): ServerFunctionMetadata | undefined;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Whether `fn` is a server function reference (a client proxy or a
|
|
166
|
+
* server-side registered callable). Detection is structural — a
|
|
167
|
+
* registered-symbol metadata brand — so it holds across duplicated module
|
|
168
|
+
* instances and both sides of the directive boundary.
|
|
169
|
+
*/
|
|
170
|
+
export function isServerFunction(fn: unknown): fn is ServerFunction;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Attaches user-declared transport metadata to a server function reference
|
|
174
|
+
* (client proxy or server-registered callable) and returns the reference.
|
|
175
|
+
* Writes ride the same channel `GET` uses: later writes shallow-merge over
|
|
176
|
+
* earlier ones, and `getServerFunctionMetadata(fn)` reads the merged bag —
|
|
177
|
+
* so `withMeta` composes with `GET` in either order
|
|
178
|
+
* (`GET(withMeta(fn, meta))` ≡ `withMeta(GET(fn), meta)`).
|
|
179
|
+
*
|
|
180
|
+
* The pattern is declare-on-function, react-in-hook: metadata declared
|
|
181
|
+
* here reaches `prepareRequest` as `context.meta`, letting session-dynamic
|
|
182
|
+
* transport policy key on declarations instead of comparing function ids:
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* export const chargeCard = withMeta(async (amount: number) => {
|
|
186
|
+
* "use server";
|
|
187
|
+
* // ...
|
|
188
|
+
* }, { requiresAuth: true });
|
|
189
|
+
*
|
|
190
|
+
* configureServerFunctionsClient({
|
|
191
|
+
* prepareRequest(init, { meta }) {
|
|
192
|
+
* if (meta?.requiresAuth) {
|
|
193
|
+
* return {
|
|
194
|
+
* ...init,
|
|
195
|
+
* headers: { ...init.headers, Authorization: `Bearer ${session.token()}` }
|
|
196
|
+
* };
|
|
197
|
+
* }
|
|
198
|
+
* return init;
|
|
199
|
+
* }
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function withMeta<F extends (...args: any[]) => any>(fn: F, meta: ServerFunctionMetadata): F;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* The registered symbol branding server function references with their
|
|
207
|
+
* declaration metadata. Use the typed accessors instead.
|
|
208
|
+
* @internal
|
|
209
|
+
*/
|
|
210
|
+
export const SERVER_FUNCTION_METADATA: unique symbol;
|
|
211
|
+
|
|
41
212
|
/**
|
|
42
213
|
* Header carrying the body format tag (a `BodyFormat` value) —
|
|
43
214
|
* `"X-Server-Function-Format"`.
|
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
import { JSONCodecOptions } from "../serializer.cjs";
|
|
2
|
+
import { ServerFunction, ServerFunctionMetadata } from "./shared.cjs";
|
|
2
3
|
|
|
3
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
FUNCTION_HEADER,
|
|
6
|
+
INSTANCE_HEADER,
|
|
7
|
+
SINGLE_FLIGHT_HEADER,
|
|
8
|
+
decodeResponse,
|
|
9
|
+
getServerFunctionMetadata,
|
|
10
|
+
isServerFunction,
|
|
11
|
+
subscribeFlightData,
|
|
12
|
+
withMeta
|
|
13
|
+
} from "./shared.cjs";
|
|
14
|
+
export type {
|
|
15
|
+
FlightDataConsumer,
|
|
16
|
+
FlightDataContext,
|
|
17
|
+
ServerFunction,
|
|
18
|
+
ServerFunctionMetadata,
|
|
19
|
+
SingleFlightPayload
|
|
20
|
+
} from "./shared.cjs";
|
|
21
|
+
|
|
22
|
+
/** The context `prepareRequest` receives alongside the outgoing RequestInit. */
|
|
23
|
+
export interface PrepareRequestContext {
|
|
24
|
+
/** The build-stable id of the function being called. */
|
|
25
|
+
id: string;
|
|
26
|
+
/**
|
|
27
|
+
* The reference's declaration metadata (e.g. `method: "GET"` for
|
|
28
|
+
* `GET(fn)` references). Plain references carry an empty object.
|
|
29
|
+
*/
|
|
30
|
+
meta: ServerFunctionMetadata | undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Client-side session-dynamic transport hook: runs before every
|
|
35
|
+
* server-function fetch. Return (or mutate and return) the RequestInit the
|
|
36
|
+
* transport will use — the hook sees the final init, transport headers
|
|
37
|
+
* included. The motivating case is dynamic credentials that rotate during
|
|
38
|
+
* a session and apply uniformly to every call (OAuth bearer tokens); it is
|
|
39
|
+
* the client-side symmetric of the server handler hooks. Single hook, not
|
|
40
|
+
* a chain — compose by wrapping functions in userland.
|
|
41
|
+
*/
|
|
42
|
+
export type PrepareRequestHook = (
|
|
43
|
+
init: RequestInit,
|
|
44
|
+
context: PrepareRequestContext
|
|
45
|
+
) => RequestInit | Promise<RequestInit>;
|
|
4
46
|
|
|
5
47
|
/** Options for `configureServerFunctionsClient`. */
|
|
6
48
|
export interface ServerFunctionsClientConfig {
|
|
@@ -18,40 +60,72 @@ export interface ServerFunctionsClientConfig {
|
|
|
18
60
|
* `decodeResponse` sees them too.
|
|
19
61
|
*/
|
|
20
62
|
codec?: JSONCodecOptions;
|
|
63
|
+
/**
|
|
64
|
+
* Runs before every server-function fetch. Return (or mutate and return)
|
|
65
|
+
* the RequestInit the transport will use; `context.meta` is the
|
|
66
|
+
* reference's declaration metadata (e.g. method). For session-dynamic
|
|
67
|
+
* cross-cutting concerns — bearer tokens, tracing headers:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* configureServerFunctionsClient({
|
|
71
|
+
* prepareRequest(init) {
|
|
72
|
+
* return {
|
|
73
|
+
* ...init,
|
|
74
|
+
* headers: { ...init.headers, Authorization: `Bearer ${session.token()}` }
|
|
75
|
+
* };
|
|
76
|
+
* }
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
prepareRequest?: PrepareRequestHook;
|
|
21
81
|
}
|
|
22
82
|
|
|
23
83
|
/**
|
|
24
84
|
* Configures the client transport. Call once, before any server function is
|
|
25
85
|
* invoked — typically in the client entry, next to `hydrate()`. Only needed
|
|
26
|
-
* when deviating from the defaults (custom endpoint
|
|
86
|
+
* when deviating from the defaults (custom endpoint, codec plugins, or a
|
|
87
|
+
* `prepareRequest` hook).
|
|
27
88
|
*/
|
|
28
89
|
export function configureServerFunctionsClient(config?: ServerFunctionsClientConfig): void;
|
|
29
90
|
|
|
30
91
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
92
|
+
* Declares a server function callable over HTTP GET: calls to the returned
|
|
93
|
+
* reference go out as GET requests with the arguments codec-encoded in the
|
|
94
|
+
* query string — cacheable by HTTP infrastructure. Cache headers flow
|
|
95
|
+
* through the handler's header forwarding
|
|
96
|
+
* (`respond(data, { headers: { "cache-control": "max-age=60" } })`).
|
|
97
|
+
*
|
|
98
|
+
* The declaration rides the metadata channel
|
|
99
|
+
* (`getServerFunctionMetadata(fn)?.method === "GET"`) for routers and
|
|
100
|
+
* integrations to detect, and the server enforces it: GET-declared
|
|
101
|
+
* functions accept GET requests (and only GET), everything else answers
|
|
102
|
+
* 405. Server-side the wrapper is identity-flavored — SSR calls stay
|
|
103
|
+
* in-process.
|
|
104
|
+
*
|
|
105
|
+
* Wrap the reference at its declaration; the compiler round-trips the call
|
|
106
|
+
* in both builds:
|
|
107
|
+
*
|
|
108
|
+
* ```ts
|
|
109
|
+
* export const getUser = GET(async (id: string) => {
|
|
110
|
+
* "use server";
|
|
111
|
+
* return db.users.find(id);
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
34
114
|
*/
|
|
35
|
-
export
|
|
36
|
-
(...args:
|
|
37
|
-
|
|
38
|
-
url: string;
|
|
39
|
-
/**
|
|
40
|
-
* Variant issuing GET requests with the arguments encoded in the query
|
|
41
|
-
* string — cacheable by HTTP infrastructure.
|
|
42
|
-
*/
|
|
43
|
-
GET: ServerFunctionCallable;
|
|
44
|
-
/** Variant applying a custom RequestInit to every call (headers etc.). */
|
|
45
|
-
withOptions(options: RequestInit): ServerFunctionCallable;
|
|
46
|
-
}
|
|
115
|
+
export function GET<A extends readonly any[], R>(
|
|
116
|
+
fn: (...args: A) => R
|
|
117
|
+
): ServerFunction<A, Awaited<R>>;
|
|
47
118
|
|
|
48
119
|
/**
|
|
49
120
|
* Compiler ABI — emitted by compiled `"use server"` client output where a
|
|
50
121
|
* server function was referenced; produces the fetch-backed callable for
|
|
51
|
-
* the function's build-stable id.
|
|
122
|
+
* the function's build-stable id. Development builds pass the function's
|
|
123
|
+
* source name as the trailing argument (dev-only metadata seeded on the
|
|
124
|
+
* metadata channel; never emitted in production). Not meant for
|
|
125
|
+
* hand-written code.
|
|
52
126
|
* @internal
|
|
53
127
|
*/
|
|
54
|
-
export function createServerReference(id: string):
|
|
128
|
+
export function createServerReference(id: string, name?: string): ServerFunction;
|
|
55
129
|
|
|
56
130
|
/**
|
|
57
131
|
* Compiler ABI — only ever referenced by server-mode compiler output;
|