@solidjs/web 2.0.0-beta.22 → 2.0.0-beta.23

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 (42) hide show
  1. package/dist/dev.cjs +25 -1
  2. package/dist/dev.js +25 -2
  3. package/dist/server.cjs +79 -33
  4. package/dist/server.js +79 -34
  5. package/dist/web.cjs +25 -1
  6. package/dist/web.js +25 -2
  7. package/frames/dist/client.cjs +1442 -0
  8. package/frames/dist/client.js +1430 -0
  9. package/frames/dist/server.cjs +1705 -0
  10. package/frames/dist/server.js +1694 -0
  11. package/frames/package.json +30 -0
  12. package/package.json +78 -5
  13. package/serialization/dist/serialization.cjs +83 -0
  14. package/serialization/dist/serialization.js +82 -1
  15. package/serialization/types/index.d.ts +12 -0
  16. package/serialization/types-cjs/index.d.cts +12 -0
  17. package/server-functions/dist/client.cjs +82 -55
  18. package/server-functions/dist/client.js +83 -56
  19. package/server-functions/dist/server.cjs +20 -3
  20. package/server-functions/dist/server.js +20 -3
  21. package/types/client.d.ts +8 -0
  22. package/types/core.d.ts +2 -1
  23. package/types/frames/client.d.ts +53 -0
  24. package/types/frames/frame-client.d.ts +205 -0
  25. package/types/frames/frame-sink.d.ts +145 -0
  26. package/types/frames/frame-transport.d.ts +105 -0
  27. package/types/frames/serializer.d.ts +151 -0
  28. package/types/frames/server.d.ts +21 -0
  29. package/types/serializer.d.ts +12 -0
  30. package/types/server-functions/client.d.ts +24 -0
  31. package/types/server.d.ts +2 -0
  32. package/types-cjs/client.d.cts +8 -0
  33. package/types-cjs/core.d.cts +2 -1
  34. package/types-cjs/frames/client.d.cts +53 -0
  35. package/types-cjs/frames/frame-client.d.cts +205 -0
  36. package/types-cjs/frames/frame-sink.d.cts +145 -0
  37. package/types-cjs/frames/frame-transport.d.cts +105 -0
  38. package/types-cjs/frames/serializer.d.cts +151 -0
  39. package/types-cjs/frames/server.d.cts +21 -0
  40. package/types-cjs/serializer.d.cts +12 -0
  41. package/types-cjs/server-functions/client.d.cts +24 -0
  42. package/types-cjs/server.d.cts +2 -0
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@solidjs/web/frames",
3
+ "main": "./dist/server.cjs",
4
+ "module": "./dist/server.js",
5
+ "types": "../types/frames/server.d.ts",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": {
10
+ "browser": {
11
+ "import": {
12
+ "types": "../types/frames/client.d.ts",
13
+ "default": "./dist/client.js"
14
+ },
15
+ "require": {
16
+ "types": "../types-cjs/frames/client.d.cts",
17
+ "default": "./dist/client.cjs"
18
+ }
19
+ },
20
+ "import": {
21
+ "types": "../types/frames/server.d.ts",
22
+ "default": "./dist/server.js"
23
+ },
24
+ "require": {
25
+ "types": "../types-cjs/frames/server.d.cts",
26
+ "default": "./dist/server.cjs"
27
+ }
28
+ }
29
+ }
30
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@solidjs/web",
3
3
  "description": "Solid's web runtime: client rendering, hydration, SSR, and DOM-specific control flow (Portal, Dynamic).",
4
- "version": "2.0.0-beta.22",
4
+ "version": "2.0.0-beta.23",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -34,7 +34,9 @@
34
34
  "serialization/types-cjs",
35
35
  "serialization/package.json",
36
36
  "server-functions/dist",
37
- "server-functions/package.json"
37
+ "server-functions/package.json",
38
+ "frames/dist",
39
+ "frames/package.json"
38
40
  ],
39
41
  "exports": {
40
42
  ".": {
@@ -217,6 +219,76 @@
217
219
  "default": "./server-functions/dist/client.cjs"
218
220
  }
219
221
  },
222
+ "./frames": {
223
+ "worker": {
224
+ "import": {
225
+ "types": "./types/frames/server.d.ts",
226
+ "default": "./frames/dist/server.js"
227
+ },
228
+ "require": {
229
+ "types": "./types-cjs/frames/server.d.cts",
230
+ "default": "./frames/dist/server.cjs"
231
+ }
232
+ },
233
+ "browser": {
234
+ "import": {
235
+ "types": "./types/frames/client.d.ts",
236
+ "default": "./frames/dist/client.js"
237
+ },
238
+ "require": {
239
+ "types": "./types-cjs/frames/client.d.cts",
240
+ "default": "./frames/dist/client.cjs"
241
+ }
242
+ },
243
+ "deno": {
244
+ "import": {
245
+ "types": "./types/frames/server.d.ts",
246
+ "default": "./frames/dist/server.js"
247
+ },
248
+ "require": {
249
+ "types": "./types-cjs/frames/server.d.cts",
250
+ "default": "./frames/dist/server.cjs"
251
+ }
252
+ },
253
+ "node": {
254
+ "import": {
255
+ "types": "./types/frames/server.d.ts",
256
+ "default": "./frames/dist/server.js"
257
+ },
258
+ "require": {
259
+ "types": "./types-cjs/frames/server.d.cts",
260
+ "default": "./frames/dist/server.cjs"
261
+ }
262
+ },
263
+ "import": {
264
+ "types": "./types/frames/client.d.ts",
265
+ "default": "./frames/dist/client.js"
266
+ },
267
+ "require": {
268
+ "types": "./types-cjs/frames/client.d.cts",
269
+ "default": "./frames/dist/client.cjs"
270
+ }
271
+ },
272
+ "./frames/server": {
273
+ "import": {
274
+ "types": "./types/frames/server.d.ts",
275
+ "default": "./frames/dist/server.js"
276
+ },
277
+ "require": {
278
+ "types": "./types-cjs/frames/server.d.cts",
279
+ "default": "./frames/dist/server.cjs"
280
+ }
281
+ },
282
+ "./frames/client": {
283
+ "import": {
284
+ "types": "./types/frames/client.d.ts",
285
+ "default": "./frames/dist/client.js"
286
+ },
287
+ "require": {
288
+ "types": "./types-cjs/frames/client.d.cts",
289
+ "default": "./frames/dist/client.cjs"
290
+ }
291
+ },
220
292
  "./types/*": "./types/*"
221
293
  },
222
294
  "dependencies": {
@@ -224,17 +296,17 @@
224
296
  "seroval-plugins": "~1.5.4"
225
297
  },
226
298
  "peerDependencies": {
227
- "solid-js": "^2.0.0-beta.22"
299
+ "solid-js": "^2.0.0-beta.23"
228
300
  },
229
301
  "devDependencies": {
230
- "solid-js": "2.0.0-beta.22"
302
+ "solid-js": "2.0.0-beta.23"
231
303
  },
232
304
  "scripts": {
233
305
  "build": "npm-run-all -nl build:clean types:copy-jsx build:js",
234
306
  "build:clean": "rimraf dist/",
235
307
  "build:js": "rollup -c",
236
308
  "link": "symlink-dir . node_modules/@solidjs/web",
237
- "types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:copy-serialization types:copy-server-functions types:cjs",
309
+ "types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:copy-serialization types:copy-server-functions types:copy-frames types:cjs",
238
310
  "types:clean": "rimraf types/ types-cjs/ storage/types/ storage/types-cjs/ serialization/types/ serialization/types-cjs/",
239
311
  "types:copy-jsx": "ncp ../../node_modules/@dom-expressions/runtime/src/jsx.d.ts ./src/jsx.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/jsx-properties.d.ts ./src/jsx-properties.d.ts && dom-expressions-jsx-types --input ./src/jsx.d.ts --element \"SolidElement | Node | ArrayElement\" --import 'import type { Element as SolidElement } from \"solid-js\";'",
240
312
  "types:web": "tsc --project ./tsconfig.build.json",
@@ -242,6 +314,7 @@
242
314
  "types:web-storage": "tsc --project ./storage/tsconfig.build.json",
243
315
  "types:copy-serialization": "node -e \"fs.mkdirSync('./serialization/types', { recursive: true }); fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/serializer.d.ts', './serialization/types/index.d.ts');\"",
244
316
  "types:copy-server-functions": "node -e \"fs.mkdirSync('./types/server-functions', { recursive: true }); for (const f of ['shared', 'client', 'server']) fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/server-functions/' + f + '.d.ts', './types/server-functions/' + f + '.d.ts');\"",
317
+ "types:copy-frames": "node -e \"fs.mkdirSync('./types/frames', { recursive: true }); for (const f of ['frame-client', 'frame-transport', 'frame-sink', 'serializer']) fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/' + f + '.d.ts', './types/frames/' + f + '.d.ts'); for (const f of ['client', 'server']) fs.copyFileSync('./frames/types/' + f + '.d.ts', './types/frames/' + f + '.d.ts');\"",
245
318
  "types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs ./storage/types ./storage/types-cjs ./serialization/types ./serialization/types-cjs",
246
319
  "test": "vitest run && vitest run --config vite.config.server.mjs && vitest run --config vite.config.hydrate.mjs",
247
320
  "test:server": "vitest run --config vite.config.server.mjs",
@@ -73,10 +73,93 @@ function createJSONDeserializer(options) {
73
73
  });
74
74
  };
75
75
  }
76
+ function createJSONSerializer({
77
+ onData,
78
+ onDone,
79
+ onError,
80
+ plugins,
81
+ disabledFeatures,
82
+ depthLimit
83
+ }) {
84
+ const resolved = resolveCodecOptions({
85
+ plugins,
86
+ disabledFeatures,
87
+ depthLimit
88
+ });
89
+ const refs = new Map();
90
+ const cancels = new Set();
91
+ let pendingWrites = 0;
92
+ let flushed = false;
93
+ let done = false;
94
+ const maybeDone = () => {
95
+ if (flushed && pendingWrites === 0 && !done) {
96
+ done = true;
97
+ onDone && onDone();
98
+ }
99
+ };
100
+ return {
101
+ write(key, value) {
102
+ if (flushed) return;
103
+ pendingWrites++;
104
+ let settled = false;
105
+ let cancel = null;
106
+ const stream = seroval.toCrossJSONStream(value, {
107
+ refs,
108
+ plugins: resolved.plugins,
109
+ disabledFeatures: resolved.disabledFeatures,
110
+ onParse(node, initial) {
111
+ onData({
112
+ key,
113
+ node,
114
+ initial
115
+ });
116
+ },
117
+ onError,
118
+ onDone() {
119
+ settled = true;
120
+ if (cancel) cancels.delete(cancel);
121
+ pendingWrites--;
122
+ maybeDone();
123
+ }
124
+ });
125
+ if (!settled) {
126
+ cancel = stream;
127
+ cancels.add(cancel);
128
+ }
129
+ },
130
+ flush() {
131
+ flushed = true;
132
+ maybeDone();
133
+ },
134
+ close() {
135
+ flushed = true;
136
+ for (const cancel of cancels) cancel();
137
+ cancels.clear();
138
+ }
139
+ };
140
+ }
141
+ function createJSONDataTable(options) {
142
+ const deserialize = createJSONDeserializer(options);
143
+ const table = new Map();
144
+ return {
145
+ apply(record) {
146
+ const value = deserialize(record.node);
147
+ if (record.initial) table.set(record.key, value);
148
+ },
149
+ get(key) {
150
+ return table.get(key);
151
+ },
152
+ resolve(ref) {
153
+ return table.get(ref.$ref);
154
+ }
155
+ };
156
+ }
76
157
 
77
158
  exports.DEFAULT_WEB_PLUGINS = DEFAULT_WEB_PLUGINS;
78
159
  exports.createHydrationSerializer = createHydrationSerializer;
160
+ exports.createJSONDataTable = createJSONDataTable;
79
161
  exports.createJSONDeserializer = createJSONDeserializer;
162
+ exports.createJSONSerializer = createJSONSerializer;
80
163
  exports.createSerializer = createSerializer;
81
164
  exports.getLocalHeaderScript = getLocalHeaderScript;
82
165
  exports.resolveSerializerPlugins = resolveSerializerPlugins;
@@ -71,5 +71,86 @@ function createJSONDeserializer(options) {
71
71
  });
72
72
  };
73
73
  }
74
+ function createJSONSerializer({
75
+ onData,
76
+ onDone,
77
+ onError,
78
+ plugins,
79
+ disabledFeatures,
80
+ depthLimit
81
+ }) {
82
+ const resolved = resolveCodecOptions({
83
+ plugins,
84
+ disabledFeatures,
85
+ depthLimit
86
+ });
87
+ const refs = new Map();
88
+ const cancels = new Set();
89
+ let pendingWrites = 0;
90
+ let flushed = false;
91
+ let done = false;
92
+ const maybeDone = () => {
93
+ if (flushed && pendingWrites === 0 && !done) {
94
+ done = true;
95
+ onDone && onDone();
96
+ }
97
+ };
98
+ return {
99
+ write(key, value) {
100
+ if (flushed) return;
101
+ pendingWrites++;
102
+ let settled = false;
103
+ let cancel = null;
104
+ const stream = toCrossJSONStream(value, {
105
+ refs,
106
+ plugins: resolved.plugins,
107
+ disabledFeatures: resolved.disabledFeatures,
108
+ onParse(node, initial) {
109
+ onData({
110
+ key,
111
+ node,
112
+ initial
113
+ });
114
+ },
115
+ onError,
116
+ onDone() {
117
+ settled = true;
118
+ if (cancel) cancels.delete(cancel);
119
+ pendingWrites--;
120
+ maybeDone();
121
+ }
122
+ });
123
+ if (!settled) {
124
+ cancel = stream;
125
+ cancels.add(cancel);
126
+ }
127
+ },
128
+ flush() {
129
+ flushed = true;
130
+ maybeDone();
131
+ },
132
+ close() {
133
+ flushed = true;
134
+ for (const cancel of cancels) cancel();
135
+ cancels.clear();
136
+ }
137
+ };
138
+ }
139
+ function createJSONDataTable(options) {
140
+ const deserialize = createJSONDeserializer(options);
141
+ const table = new Map();
142
+ return {
143
+ apply(record) {
144
+ const value = deserialize(record.node);
145
+ if (record.initial) table.set(record.key, value);
146
+ },
147
+ get(key) {
148
+ return table.get(key);
149
+ },
150
+ resolve(ref) {
151
+ return table.get(ref.$ref);
152
+ }
153
+ };
154
+ }
74
155
 
75
- export { DEFAULT_WEB_PLUGINS, createHydrationSerializer, createJSONDeserializer, createSerializer, getLocalHeaderScript, resolveSerializerPlugins, serializeJSON };
156
+ export { DEFAULT_WEB_PLUGINS, createHydrationSerializer, createJSONDataTable, createJSONDeserializer, createJSONSerializer, createSerializer, getLocalHeaderScript, resolveSerializerPlugins, serializeJSON };
@@ -137,3 +137,15 @@ export function serializeJSON(value: unknown, options: JSONSerializeOptions): ()
137
137
  * settles the async values referenced inside it.
138
138
  */
139
139
  export function createJSONDeserializer(options?: JSONCodecOptions): <T>(node: SerovalNode) => T;
140
+
141
+ /**
142
+ * A resident, response-scoped decode table over the keyed JSON codec: apply
143
+ * each frame `data` chunk with `apply`, resolve `{ $ref }` slot args with
144
+ * `resolve`. The frames client host wires one per response
145
+ * (`applyData: c => table.apply(c)`).
146
+ */
147
+ export interface JSONDataTable {
148
+ apply(chunk: { key?: string; node?: unknown; initial?: boolean }): void;
149
+ resolve<T = unknown>(ref: { $ref: string }): T;
150
+ }
151
+ export function createJSONDataTable(options?: JSONCodecOptions): JSONDataTable;
@@ -137,3 +137,15 @@ export function serializeJSON(value: unknown, options: JSONSerializeOptions): ()
137
137
  * settles the async values referenced inside it.
138
138
  */
139
139
  export function createJSONDeserializer(options?: JSONCodecOptions): <T>(node: SerovalNode) => T;
140
+
141
+ /**
142
+ * A resident, response-scoped decode table over the keyed JSON codec: apply
143
+ * each frame `data` chunk with `apply`, resolve `{ $ref }` slot args with
144
+ * `resolve`. The frames client host wires one per response
145
+ * (`applyData: c => table.apply(c)`).
146
+ */
147
+ export interface JSONDataTable {
148
+ apply(chunk: { key?: string; node?: unknown; initial?: boolean }): void;
149
+ resolve<T = unknown>(ref: { $ref: string }): T;
150
+ }
151
+ export function createJSONDataTable(options?: JSONCodecOptions): JSONDataTable;
@@ -23,19 +23,6 @@ function resolveCodecOptions({
23
23
  depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
24
24
  };
25
25
  }
26
- function serializeJSON(value, {
27
- onParse,
28
- onDone,
29
- onError,
30
- ...codecOptions
31
- }) {
32
- return seroval.toCrossJSONStream(value, {
33
- onParse,
34
- onDone,
35
- onError,
36
- ...resolveCodecOptions(codecOptions)
37
- });
38
- }
39
26
  function createJSONDeserializer(options) {
40
27
  const refs = new Map();
41
28
  const resolved = resolveCodecOptions(options);
@@ -53,9 +40,6 @@ const codecConfig = {
53
40
  function configureServerFunctionsCodec(codec) {
54
41
  codecConfig.codec = codec;
55
42
  }
56
- function getServerFunctionsCodec() {
57
- return codecConfig.codec;
58
- }
59
43
  const flightConfig = {
60
44
  consumer: undefined
61
45
  };
@@ -122,7 +106,8 @@ const BodyFormat = {
122
106
  Blob: "4",
123
107
  File: "5",
124
108
  ArrayBuffer: "6",
125
- Uint8Array: "7"
109
+ Uint8Array: "7",
110
+ Json: "8"
126
111
  };
127
112
  function getHeadersAndBody(body) {
128
113
  switch (true) {
@@ -192,6 +177,8 @@ async function extractBody(source, codecOptions) {
192
177
  switch (true) {
193
178
  case format === BodyFormat.Serialized:
194
179
  return await deserializeStream(clone, codecOptions);
180
+ case format === BodyFormat.Json:
181
+ return JSON.parse(await clone.text());
195
182
  case format === BodyFormat.String:
196
183
  return await clone.text();
197
184
  case format === BodyFormat.File:
@@ -214,17 +201,6 @@ async function extractBody(source, codecOptions) {
214
201
  }
215
202
  return undefined;
216
203
  }
217
- function createChunk(data) {
218
- const encodeData = new TextEncoder().encode(data);
219
- const bytes = encodeData.length;
220
- const baseHex = bytes.toString(16);
221
- const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex;
222
- const head = new TextEncoder().encode(`;0x${totalHex};`);
223
- const chunk = new Uint8Array(12 + bytes);
224
- chunk.set(head);
225
- chunk.set(encodeData, 12);
226
- return chunk;
227
- }
228
204
  class ChunkReader {
229
205
  constructor(stream) {
230
206
  this.reader = stream.getReader();
@@ -281,28 +257,6 @@ class ChunkReader {
281
257
  }
282
258
  }
283
259
  }
284
- function serializeStream(value, codecOptions) {
285
- return new ReadableStream({
286
- start(controller) {
287
- serializeJSON(value, {
288
- ...codecOptions,
289
- onParse(node) {
290
- controller.enqueue(createChunk(JSON.stringify(node)));
291
- },
292
- onDone() {
293
- controller.close();
294
- },
295
- onError(error) {
296
- controller.error(error);
297
- }
298
- });
299
- }
300
- });
301
- }
302
- async function serializeString(value, codecOptions) {
303
- const response = new Response(serializeStream(value, codecOptions));
304
- return await response.text();
305
- }
306
260
  async function deserializeStream(source, codecOptions) {
307
261
  if (!source.body) {
308
262
  throw new Error("missing body");
@@ -326,16 +280,43 @@ async function decodeResponse(response, codecOptions) {
326
280
 
327
281
  const config = {
328
282
  endpoint: "/_server",
329
- prepareRequest: undefined
283
+ prepareRequest: undefined,
284
+ responseHandler: undefined,
285
+ serializeArgs: undefined
330
286
  };
287
+ function isJSONSafe(value) {
288
+ if (value === null) return true;
289
+ const t = typeof value;
290
+ if (t === "string" || t === "boolean") return true;
291
+ if (t === "number") return Number.isFinite(value);
292
+ if (t !== "object") return false;
293
+ if (Array.isArray(value)) {
294
+ for (const v of value) if (!isJSONSafe(v)) return false;
295
+ return true;
296
+ }
297
+ const proto = Object.getPrototypeOf(value);
298
+ if (proto !== Object.prototype && proto !== null) return false;
299
+ for (const k in value) if (!isJSONSafe(value[k])) return false;
300
+ return true;
301
+ }
302
+ function serializeArguments(args) {
303
+ if (!config.serializeArgs) {
304
+ throw new Error("Server function arguments are sent as JSON by default and these " + "arguments are not JSON-serializable. Call enableRichArguments() " + "(from the server-functions rich-args entry) once at startup to " + "send Dates, Maps, Sets, typed arrays, etc. through the codec — or " + "pass a single Blob/FormData/File argument, which has a native " + "HTTP encoding.");
305
+ }
306
+ return config.serializeArgs(args);
307
+ }
331
308
  function configureServerFunctionsClient({
332
309
  endpoint,
333
310
  codec,
334
- prepareRequest
311
+ prepareRequest,
312
+ responseHandler,
313
+ serializeArgs
335
314
  } = {}) {
336
315
  if (endpoint !== undefined) config.endpoint = endpoint;
337
316
  if (codec !== undefined) configureServerFunctionsCodec(codec);
338
317
  if (prepareRequest !== undefined) config.prepareRequest = prepareRequest;
318
+ if (responseHandler !== undefined) config.responseHandler = responseHandler;
319
+ if (serializeArgs !== undefined) config.serializeArgs = serializeArgs;
339
320
  }
340
321
  let INSTANCE = 0;
341
322
  async function createRequest(base, id, instance, options, meta) {
@@ -377,9 +358,20 @@ async function initializeResponse(base, id, instance, options, args, meta) {
377
358
  }, meta);
378
359
  }
379
360
  }
361
+ if (isJSONSafe(args)) {
362
+ return createRequest(base, id, instance, {
363
+ ...options,
364
+ body: JSON.stringify(args),
365
+ headers: {
366
+ ...options.headers,
367
+ "Content-Type": "application/json",
368
+ [BODY_FORMAT_HEADER]: BodyFormat.Json
369
+ }
370
+ }, meta);
371
+ }
380
372
  return createRequest(base, id, instance, {
381
373
  ...options,
382
- body: await serializeString(args, getServerFunctionsCodec()),
374
+ body: await serializeArguments(args),
383
375
  headers: {
384
376
  ...options.headers,
385
377
  "Content-Type": "text/plain",
@@ -389,7 +381,21 @@ async function initializeResponse(base, id, instance, options, args, meta) {
389
381
  }
390
382
  async function fetchServerFunction(base, id, options, args, meta) {
391
383
  const instance = `server-function:${INSTANCE++}`;
384
+ const handler = config.responseHandler;
385
+ const context = handler && handler.capture ? handler.capture({
386
+ id,
387
+ meta
388
+ }) : undefined;
392
389
  const response = await initializeResponse(base, id, instance, options, args, meta);
390
+ if (handler) {
391
+ const handled = handler.handle(response, {
392
+ id,
393
+ meta,
394
+ args,
395
+ context
396
+ });
397
+ if (handled !== undefined) return handled;
398
+ }
393
399
  if (response.headers.has(SINGLE_FLIGHT_HEADER)) {
394
400
  const consumer = getFlightDataConsumer();
395
401
  if (consumer) {
@@ -416,7 +422,18 @@ function createServerReference(id, name, base) {
416
422
  const metadata = name === undefined ? {} : {
417
423
  name
418
424
  };
419
- const fn = (...args) => fetchServerFunction(base || config.endpoint, id, {}, args, metadata);
425
+ const fn = (...args) => {
426
+ const handler = config.responseHandler;
427
+ if (handler && handler.intercept) {
428
+ const hit = handler.intercept({
429
+ id,
430
+ meta: metadata,
431
+ args
432
+ });
433
+ if (hit !== undefined) return hit;
434
+ }
435
+ return fetchServerFunction(base || config.endpoint, id, {}, args, metadata);
436
+ };
420
437
  fn[SERVER_FUNCTION_METADATA] = metadata;
421
438
  return new Proxy(fn, {
422
439
  get(target, prop) {
@@ -437,9 +454,19 @@ function GET(fn) {
437
454
  ...getServerFunctionMetadata(fn)
438
455
  };
439
456
  const wrapped = async (...args) => {
457
+ const handler = config.responseHandler;
458
+ if (handler && handler.intercept) {
459
+ const hit = handler.intercept({
460
+ id,
461
+ meta: metadata,
462
+ args
463
+ });
464
+ if (hit !== undefined) return hit;
465
+ }
440
466
  let base = `${config.endpoint}?id=${encodeURIComponent(id)}`;
441
467
  if (args.length) {
442
- base += `&args=${encodeURIComponent(await serializeString(args, getServerFunctionsCodec()))}`;
468
+ const encoded = isJSONSafe(args) ? JSON.stringify(args) : await serializeArguments(args);
469
+ base += `&args=${encodeURIComponent(encoded)}`;
443
470
  }
444
471
  return fetchServerFunction(base, id, {
445
472
  method: "GET"