@solidjs/web 2.0.0-beta.32 → 2.0.0-beta.33
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 +51 -15
- package/dist/dev.js +47 -16
- package/dist/server.cjs +710 -71
- package/dist/server.js +707 -74
- package/dist/web.cjs +51 -15
- package/dist/web.js +47 -16
- package/frames/dist/client.cjs +181 -64
- package/frames/dist/client.dev.cjs +185 -64
- package/frames/dist/client.dev.js +183 -62
- package/frames/dist/client.js +179 -62
- package/frames/dist/server.cjs +969 -133
- package/frames/dist/server.js +971 -135
- package/package.json +17 -6
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +110 -0
- package/serialization/dist/decode.js +104 -0
- package/serialization/dist/serialization.cjs +98 -43
- package/serialization/dist/serialization.js +99 -44
- package/serialization/types/index.d.ts +18 -160
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +18 -160
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +101 -105
- package/server-functions/dist/client.js +101 -105
- package/server-functions/dist/server.cjs +131 -107
- package/server-functions/dist/server.dev.cjs +131 -107
- package/server-functions/dist/server.dev.js +132 -108
- package/server-functions/dist/server.js +132 -108
- package/types/client.d.ts +23 -1
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +1 -1
- package/types/frames/frame-client.d.ts +26 -0
- package/types/frames/frame-transport.d.ts +1 -1
- package/types/frames/serializer.d.ts +18 -160
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +18 -160
- package/types/server-functions/client.d.ts +1 -1
- package/types/server-functions/server.d.ts +1 -1
- package/types/server-functions/shared.d.ts +57 -1
- package/types/server.d.ts +21 -1
- package/types-cjs/client.d.cts +23 -1
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +1 -1
- package/types-cjs/frames/frame-client.d.cts +26 -0
- package/types-cjs/frames/frame-transport.d.cts +1 -1
- package/types-cjs/frames/serializer.d.cts +18 -160
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +18 -160
- package/types-cjs/server-functions/client.d.cts +1 -1
- package/types-cjs/server-functions/server.d.cts +1 -1
- package/types-cjs/server-functions/shared.d.cts +57 -1
- package/types-cjs/server.d.cts +21 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { fromCrossJSON, Feature, toCrossJSONStream } from 'seroval';
|
|
2
|
-
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
3
1
|
import { sharedConfig } from 'solid-js';
|
|
4
2
|
|
|
5
3
|
const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
|
|
@@ -12,51 +10,70 @@ function isSafeError(value) {
|
|
|
12
10
|
}
|
|
13
11
|
const REVALIDATE_HEADER = "X-Revalidate";
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
|
|
20
|
-
function resolveSerializerPlugins(customPlugins) {
|
|
21
|
-
return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
|
|
22
|
-
}
|
|
23
|
-
const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
|
|
24
|
-
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
25
|
-
function resolveCodecOptions({
|
|
26
|
-
plugins,
|
|
27
|
-
disabledFeatures,
|
|
28
|
-
depthLimit
|
|
29
|
-
} = {}) {
|
|
30
|
-
return {
|
|
31
|
-
plugins: resolveSerializerPlugins(plugins),
|
|
32
|
-
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
33
|
-
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
34
|
-
};
|
|
13
|
+
const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
|
|
14
|
+
function getServerFunctionMetadata(fn) {
|
|
15
|
+
if (typeof fn !== "function") return undefined;
|
|
16
|
+
return fn[SERVER_FUNCTION_METADATA] || undefined;
|
|
35
17
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
onDone,
|
|
39
|
-
onError,
|
|
40
|
-
...codecOptions
|
|
41
|
-
}) {
|
|
42
|
-
const resolved = resolveCodecOptions(codecOptions);
|
|
43
|
-
return toCrossJSONStream(value, {
|
|
44
|
-
onParse,
|
|
45
|
-
onDone,
|
|
46
|
-
onError,
|
|
47
|
-
...resolved,
|
|
48
|
-
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
|
|
49
|
-
});
|
|
18
|
+
function isServerFunction(fn) {
|
|
19
|
+
return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
|
|
50
20
|
}
|
|
51
|
-
function
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
21
|
+
function withMeta(fn, meta) {
|
|
22
|
+
const metadata = getServerFunctionMetadata(fn);
|
|
23
|
+
if (!metadata) {
|
|
24
|
+
throw new Error("withMeta expects a server function reference");
|
|
25
|
+
}
|
|
26
|
+
Object.assign(metadata, meta);
|
|
27
|
+
return fn;
|
|
28
|
+
}
|
|
29
|
+
const SERVER_FUNCTION_RPC = Symbol.for("solid.ServerFunctionRPC");
|
|
30
|
+
function provideServerFunctionRPC(rpc) {
|
|
31
|
+
globalThis[SERVER_FUNCTION_RPC] || (globalThis[SERVER_FUNCTION_RPC] = rpc);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parseCookieHeader(header) {
|
|
35
|
+
const cookies = {};
|
|
36
|
+
if (!header) return cookies;
|
|
37
|
+
for (const part of header.split(";")) {
|
|
38
|
+
const eq = part.indexOf("=");
|
|
39
|
+
if (eq < 0) continue;
|
|
40
|
+
const name = decodeSafe(part.slice(0, eq).trim());
|
|
41
|
+
let value = part.slice(eq + 1).trim();
|
|
42
|
+
if (value.length > 1 && value[0] === '"' && value[value.length - 1] === '"') {
|
|
43
|
+
value = value.slice(1, -1);
|
|
44
|
+
}
|
|
45
|
+
cookies[name] = decodeSafe(value);
|
|
46
|
+
}
|
|
47
|
+
return cookies;
|
|
48
|
+
}
|
|
49
|
+
function decodeSafe(text) {
|
|
50
|
+
try {
|
|
51
|
+
return decodeURIComponent(text);
|
|
52
|
+
} catch {
|
|
53
|
+
return text;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function serializeCookie(name, value, options = {}) {
|
|
57
|
+
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
58
|
+
cookie += `; Path=${options.path === undefined ? "/" : options.path}`;
|
|
59
|
+
if (options.domain) cookie += `; Domain=${options.domain}`;
|
|
60
|
+
if (options.maxAge !== undefined) cookie += `; Max-Age=${Math.trunc(options.maxAge)}`;
|
|
61
|
+
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
62
|
+
if (options.httpOnly) cookie += "; HttpOnly";
|
|
63
|
+
if (options.secure) cookie += "; Secure";
|
|
64
|
+
if (options.sameSite) {
|
|
65
|
+
const sameSite = options.sameSite.toLowerCase();
|
|
66
|
+
cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
|
|
67
|
+
}
|
|
68
|
+
return cookie;
|
|
69
|
+
}
|
|
70
|
+
const FLASH_COOKIE = "flash";
|
|
71
|
+
const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
|
|
72
|
+
function hasFlashCookie(cookieHeader) {
|
|
73
|
+
return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
|
|
74
|
+
}
|
|
75
|
+
function clearFlashCookie() {
|
|
76
|
+
return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
const codecConfig = {
|
|
@@ -72,22 +89,6 @@ function subscribeFlightData(consumer) {
|
|
|
72
89
|
return () => {
|
|
73
90
|
};
|
|
74
91
|
}
|
|
75
|
-
const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
|
|
76
|
-
function getServerFunctionMetadata(fn) {
|
|
77
|
-
if (typeof fn !== "function") return undefined;
|
|
78
|
-
return fn[SERVER_FUNCTION_METADATA] || undefined;
|
|
79
|
-
}
|
|
80
|
-
function isServerFunction(fn) {
|
|
81
|
-
return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
|
|
82
|
-
}
|
|
83
|
-
function withMeta(fn, meta) {
|
|
84
|
-
const metadata = getServerFunctionMetadata(fn);
|
|
85
|
-
if (!metadata) {
|
|
86
|
-
throw new Error("withMeta expects a server function reference");
|
|
87
|
-
}
|
|
88
|
-
Object.assign(metadata, meta);
|
|
89
|
-
return fn;
|
|
90
|
-
}
|
|
91
92
|
const FUNCTION_HEADER = "X-Server-Function-Id";
|
|
92
93
|
const ERROR_HEADER = "X-Server-Function-Error";
|
|
93
94
|
const ERROR_HEADER_MARKER = "=?1?";
|
|
@@ -118,14 +119,6 @@ const INSTANCE_HEADER = "X-Server-Function-Instance";
|
|
|
118
119
|
const BODY_FORMAT_HEADER = "X-Server-Function-Format";
|
|
119
120
|
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
120
121
|
const FILE_FORM_KEY = "__server_function_file__";
|
|
121
|
-
const FLASH_COOKIE = "flash";
|
|
122
|
-
const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
|
|
123
|
-
function hasFlashCookie(cookieHeader) {
|
|
124
|
-
return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
|
|
125
|
-
}
|
|
126
|
-
function clearFlashCookie() {
|
|
127
|
-
return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
|
|
128
|
-
}
|
|
129
122
|
const BodyFormat = {
|
|
130
123
|
Serialized: "0",
|
|
131
124
|
String: "1",
|
|
@@ -137,6 +130,38 @@ const BodyFormat = {
|
|
|
137
130
|
Uint8Array: "7",
|
|
138
131
|
Json: "8"
|
|
139
132
|
};
|
|
133
|
+
const JSON_SAFE_DEPTH_LIMIT = 10000;
|
|
134
|
+
const EXIT = {};
|
|
135
|
+
function isJSONSafe(value) {
|
|
136
|
+
const stack = [value];
|
|
137
|
+
const ancestors = new Set();
|
|
138
|
+
while (stack.length) {
|
|
139
|
+
const v = stack.pop();
|
|
140
|
+
if (v === EXIT) {
|
|
141
|
+
ancestors.delete(stack.pop());
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (v === null) continue;
|
|
145
|
+
const t = typeof v;
|
|
146
|
+
if (t === "string" || t === "boolean") continue;
|
|
147
|
+
if (t === "number") {
|
|
148
|
+
if (!Number.isFinite(v)) return false;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (t !== "object") return false;
|
|
152
|
+
if (ancestors.has(v) || ancestors.size >= JSON_SAFE_DEPTH_LIMIT) return false;
|
|
153
|
+
ancestors.add(v);
|
|
154
|
+
stack.push(v, EXIT);
|
|
155
|
+
if (Array.isArray(v)) {
|
|
156
|
+
for (let i = 0; i < v.length; i++) stack.push(v[i]);
|
|
157
|
+
} else {
|
|
158
|
+
const proto = Object.getPrototypeOf(v);
|
|
159
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
160
|
+
for (const k in v) stack.push(v[k]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
140
165
|
function getHeadersAndBody(body) {
|
|
141
166
|
switch (true) {
|
|
142
167
|
case typeof body === "string":
|
|
@@ -296,7 +321,10 @@ class ChunkReader {
|
|
|
296
321
|
}
|
|
297
322
|
function serializeStream(value, codecOptions) {
|
|
298
323
|
return new ReadableStream({
|
|
299
|
-
start(controller) {
|
|
324
|
+
async start(controller) {
|
|
325
|
+
const {
|
|
326
|
+
serializeJSON
|
|
327
|
+
} = await import('@solidjs/web/serialization');
|
|
300
328
|
serializeJSON(value, {
|
|
301
329
|
...codecOptions,
|
|
302
330
|
onParse(node) {
|
|
@@ -319,6 +347,9 @@ async function deserializeStream(source, codecOptions) {
|
|
|
319
347
|
const reader = new ChunkReader(source.body);
|
|
320
348
|
const result = await reader.next();
|
|
321
349
|
if (!result.done) {
|
|
350
|
+
const {
|
|
351
|
+
createJSONDeserializer
|
|
352
|
+
} = await import('@solidjs/web/serialization/decode');
|
|
322
353
|
const deserializeChunk = createJSONDeserializer(codecOptions);
|
|
323
354
|
function interpretChunk(chunk) {
|
|
324
355
|
return deserializeChunk(JSON.parse(chunk));
|
|
@@ -348,43 +379,6 @@ async function decodeResponsePayload(response, codecOptions) {
|
|
|
348
379
|
};
|
|
349
380
|
}
|
|
350
381
|
|
|
351
|
-
function parseCookieHeader(header) {
|
|
352
|
-
const cookies = {};
|
|
353
|
-
if (!header) return cookies;
|
|
354
|
-
for (const part of header.split(";")) {
|
|
355
|
-
const eq = part.indexOf("=");
|
|
356
|
-
if (eq < 0) continue;
|
|
357
|
-
const name = decodeSafe(part.slice(0, eq).trim());
|
|
358
|
-
let value = part.slice(eq + 1).trim();
|
|
359
|
-
if (value.length > 1 && value[0] === '"' && value[value.length - 1] === '"') {
|
|
360
|
-
value = value.slice(1, -1);
|
|
361
|
-
}
|
|
362
|
-
cookies[name] = decodeSafe(value);
|
|
363
|
-
}
|
|
364
|
-
return cookies;
|
|
365
|
-
}
|
|
366
|
-
function decodeSafe(text) {
|
|
367
|
-
try {
|
|
368
|
-
return decodeURIComponent(text);
|
|
369
|
-
} catch {
|
|
370
|
-
return text;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
function serializeCookie(name, value, options = {}) {
|
|
374
|
-
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
375
|
-
cookie += `; Path=${options.path === undefined ? "/" : options.path}`;
|
|
376
|
-
if (options.domain) cookie += `; Domain=${options.domain}`;
|
|
377
|
-
if (options.maxAge !== undefined) cookie += `; Max-Age=${Math.trunc(options.maxAge)}`;
|
|
378
|
-
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
379
|
-
if (options.httpOnly) cookie += "; HttpOnly";
|
|
380
|
-
if (options.secure) cookie += "; Secure";
|
|
381
|
-
if (options.sameSite) {
|
|
382
|
-
const sameSite = options.sameSite.toLowerCase();
|
|
383
|
-
cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
|
|
384
|
-
}
|
|
385
|
-
return cookie;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
382
|
const RequestContext = Symbol.for("solid.RequestContext");
|
|
389
383
|
function getRequestEvent() {
|
|
390
384
|
return globalThis[RequestContext] ? globalThis[RequestContext].getStore() || sharedConfig.context && sharedConfig.context.event || console.warn("RequestEvent is missing. This is most likely due to accessing `getRequestEvent` non-managed async scope in a partially polyfilled environment. Try moving it above all `await` calls.") : undefined;
|
|
@@ -548,7 +542,17 @@ function provideEvent(event, fn) {
|
|
|
548
542
|
const REGISTRATIONS = new Map();
|
|
549
543
|
const METHODS = new Map();
|
|
550
544
|
const INVOCATIONS = new WeakMap();
|
|
545
|
+
let rpcProvided = false;
|
|
546
|
+
function provideRPC() {
|
|
547
|
+
if (rpcProvided) return;
|
|
548
|
+
rpcProvided = true;
|
|
549
|
+
provideServerFunctionRPC({
|
|
550
|
+
GET,
|
|
551
|
+
decodeResponse
|
|
552
|
+
});
|
|
553
|
+
}
|
|
551
554
|
function registerServerFunction(id, callback) {
|
|
555
|
+
provideRPC();
|
|
552
556
|
REGISTRATIONS.set(id, callback);
|
|
553
557
|
return callback;
|
|
554
558
|
}
|
|
@@ -573,6 +577,7 @@ function createServerReference({
|
|
|
573
577
|
name
|
|
574
578
|
}) {
|
|
575
579
|
if (typeof fn !== "function") throw new Error("Export from a 'use server' module must be a function");
|
|
580
|
+
provideRPC();
|
|
576
581
|
const metadata = name === undefined ? {} : {
|
|
577
582
|
name
|
|
578
583
|
};
|
|
@@ -684,7 +689,9 @@ async function foldFlightData(hook, event, headers, outcome, context = {}) {
|
|
|
684
689
|
return transformed;
|
|
685
690
|
}
|
|
686
691
|
}
|
|
687
|
-
return {
|
|
692
|
+
return outcome.value === undefined ? {
|
|
693
|
+
data
|
|
694
|
+
} : {
|
|
688
695
|
value: outcome.value,
|
|
689
696
|
data
|
|
690
697
|
};
|
|
@@ -816,6 +823,23 @@ function encodeResult(value, headers, status, codec) {
|
|
|
816
823
|
headers
|
|
817
824
|
});
|
|
818
825
|
}
|
|
826
|
+
if (value === undefined) {
|
|
827
|
+
return new Response(null, {
|
|
828
|
+
status,
|
|
829
|
+
headers
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
try {
|
|
833
|
+
if (isJSONSafe(value)) {
|
|
834
|
+
headers.set(BODY_FORMAT_HEADER, BodyFormat.Json);
|
|
835
|
+
headers.set("Content-Type", "application/json");
|
|
836
|
+
return new Response(JSON.stringify(value), {
|
|
837
|
+
status,
|
|
838
|
+
headers
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
} catch {
|
|
842
|
+
}
|
|
819
843
|
const response = serializedResponse(value, headers, codec);
|
|
820
844
|
return status === 200 ? response : new Response(response.body, {
|
|
821
845
|
status,
|
package/types/client.d.ts
CHANGED
|
@@ -289,7 +289,7 @@ export interface ResponseStub {
|
|
|
289
289
|
* share ONE interface identity and a single augmentation reaches every
|
|
290
290
|
* `locals`, whichever entry typed the event.
|
|
291
291
|
*/
|
|
292
|
-
export
|
|
292
|
+
export { RequestEventLocals } from "./server.js";
|
|
293
293
|
export interface RequestEvent {
|
|
294
294
|
request: Request;
|
|
295
295
|
locals: RequestEventLocals;
|
|
@@ -311,5 +311,27 @@ export function getRequestEvent(): RequestEvent | undefined;
|
|
|
311
311
|
*/
|
|
312
312
|
export { parseCookieHeader, serializeCookie } from "./cookies.js";
|
|
313
313
|
export type { CookieOptions } from "./cookies.js";
|
|
314
|
+
/**
|
|
315
|
+
* The flash cookie's isomorphic half (name/detection/clearing — cookie
|
|
316
|
+
* utilities living beside the cookie codec) and the codec-free
|
|
317
|
+
* server-function layer (reference detection + the late-bound RPC seam).
|
|
318
|
+
* On the core entries so integrations consuming them eagerly (routers)
|
|
319
|
+
* never import the server-functions entry — whose client half is the
|
|
320
|
+
* transport + codec — from their eager graph. Declared through
|
|
321
|
+
* server-functions/shared.d.ts, the declaration home published-types
|
|
322
|
+
* layouts ship.
|
|
323
|
+
*/
|
|
324
|
+
export {
|
|
325
|
+
clearFlashCookie,
|
|
326
|
+
getServerFunctionMetadata,
|
|
327
|
+
getServerFunctionRPC,
|
|
328
|
+
hasFlashCookie,
|
|
329
|
+
isServerFunction
|
|
330
|
+
} from "./server-functions/shared.js";
|
|
331
|
+
export type {
|
|
332
|
+
ServerFunction,
|
|
333
|
+
ServerFunctionMetadata,
|
|
334
|
+
ServerFunctionRPC
|
|
335
|
+
} from "./server-functions/shared.js";
|
|
314
336
|
/** Hydration-walk primitive; not for hand-written code. @internal */
|
|
315
337
|
export function runHydrationEvents(): void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Cookie wire format: the platform-gap primitives, and ALL of core's
|
|
2
|
+
// cookie surface — core owns the exchange (the request's headers in, the
|
|
3
|
+
// response stub's headers out) and the codec, nothing ambient. Blessed
|
|
4
|
+
// patterns:
|
|
5
|
+
//
|
|
6
|
+
// parseCookieHeader(event.request.headers.get("cookie"))
|
|
7
|
+
// event.response.headers.append("set-cookie", serializeCookie(name, value, options))
|
|
8
|
+
//
|
|
9
|
+
// Dependency-free and isomorphic (exported from both entries — real
|
|
10
|
+
// implementation, never a stub); integrity/confidentiality layers
|
|
11
|
+
// (sessions) belong to the caller, on top of these primitives.
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Attributes for a `Set-Cookie` header, mirroring RFC 6265. `path`
|
|
15
|
+
* defaults to `/`; nothing else is defaulted.
|
|
16
|
+
*/
|
|
17
|
+
export interface CookieOptions {
|
|
18
|
+
/** Cookie `Path` attribute. Defaults to `/`. */
|
|
19
|
+
path?: string;
|
|
20
|
+
/** Cookie `Domain` attribute. Emitted only when provided. */
|
|
21
|
+
domain?: string;
|
|
22
|
+
/** Cookie `Max-Age` attribute, in seconds (truncated to an integer). */
|
|
23
|
+
maxAge?: number;
|
|
24
|
+
/** Cookie `Expires` attribute. */
|
|
25
|
+
expires?: Date;
|
|
26
|
+
/** Emit the `HttpOnly` attribute. */
|
|
27
|
+
httpOnly?: boolean;
|
|
28
|
+
/** Emit the `Secure` attribute. */
|
|
29
|
+
secure?: boolean;
|
|
30
|
+
/** Cookie `SameSite` attribute, any case. */
|
|
31
|
+
sameSite?: "lax" | "strict" | "none" | "Lax" | "Strict" | "None";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Parses a `Cookie` request header into a name → value map. Names and
|
|
36
|
+
* values are `decodeURIComponent`-decoded (falling back to the raw text
|
|
37
|
+
* when decoding throws); a quoted value keeps its content. `null`/empty
|
|
38
|
+
* input parses to an empty map.
|
|
39
|
+
*
|
|
40
|
+
* The read half of the platform gap — the blessed request-cookie read is
|
|
41
|
+
* `parseCookieHeader(event.request.headers.get("cookie"))`.
|
|
42
|
+
*/
|
|
43
|
+
export function parseCookieHeader(header: string | null | undefined): Record<string, string>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Serializes a cookie to a `Set-Cookie` header value. The name and value
|
|
47
|
+
* are `encodeURIComponent`-encoded (the parser decodes symmetrically);
|
|
48
|
+
* `path` defaults to `/` and every other attribute is emitted exactly
|
|
49
|
+
* when the caller asked for it.
|
|
50
|
+
*
|
|
51
|
+
* The write half of the platform gap — the blessed response-cookie write
|
|
52
|
+
* is `event.response.headers.append("set-cookie", serializeCookie(name,
|
|
53
|
+
* value, options))`, which every head materialization path carries to the
|
|
54
|
+
* wire entry-by-entry.
|
|
55
|
+
*/
|
|
56
|
+
export function serializeCookie(name: string, value: string, options?: CookieOptions): string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Name of the cookie carrying the outcome of a server function call made
|
|
60
|
+
* without the client runtime (`"flash"`). A no-JS form post has no way to
|
|
61
|
+
* receive a value — the browser follows the redirect and renders the next
|
|
62
|
+
* page — so the handler stashes the outcome here for the render after it
|
|
63
|
+
* to pick up, which is how a form submitted without JavaScript still shows
|
|
64
|
+
* its result.
|
|
65
|
+
*
|
|
66
|
+
* The name, detection and clearing are cookie utilities and isomorphic
|
|
67
|
+
* (integrations read the cookie from code that also ships to the browser);
|
|
68
|
+
* the codec that fills and decodes it is server-only and lives behind the
|
|
69
|
+
* server-functions server entry.
|
|
70
|
+
*/
|
|
71
|
+
export const FLASH_COOKIE: string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether a Cookie header carries a flash cookie, readable or not. Cheap
|
|
75
|
+
* enough to call on every render so the clear can be queued before the
|
|
76
|
+
* response headers flush.
|
|
77
|
+
*/
|
|
78
|
+
export function hasFlashCookie(cookieHeader: string | null): boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The `Set-Cookie` value clearing the flash cookie. The outcome is
|
|
82
|
+
* one-shot: append this as soon as the cookie is detected, whether or not
|
|
83
|
+
* it decodes, so a stale outcome cannot resurface on a later request.
|
|
84
|
+
*/
|
|
85
|
+
export function clearFlashCookie(): string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The raw encoded flash payload out of a Cookie header, if present — the
|
|
89
|
+
* codec's own accessor.
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export function matchFlashCookie(cookieHeader: string | null): string | undefined;
|
package/types/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getOwner, runWithOwner, createComponent, createRoot as root, sharedConfig, untrack, merge as mergeProps, flatten, ssrHandleError, ssrScope, NoHydration, Hydration, runInServerComponentScope } from "solid-js";
|
|
1
|
+
export { getOwner, runWithOwner, createComponent, createRoot as root, sharedConfig, untrack, merge as mergeProps, flatten, ssrHandleError, ssrScope, NoHydration, Hydration, runInServerComponentScope, creationStamp, inServerComponentScope } from "solid-js";
|
|
2
2
|
export declare const effect: (fn: any, effectFn: any, options?: any) => void;
|
|
3
3
|
export declare const memo: (fn: any) => import("solid-js").SourceAccessor<any>;
|
|
4
4
|
export declare const runWithHydrationScope: (id: any, fn: any) => unknown;
|
|
@@ -186,6 +186,10 @@ export interface FrameHost {
|
|
|
186
186
|
serialize(value: unknown): { $ref: string };
|
|
187
187
|
/** `frameId` is the resolving frame's id — route to its stream's table. */
|
|
188
188
|
resolve(ref: { $ref: string }, frameId?: string): unknown;
|
|
189
|
+
/** See FrameHostOptions.revive. */
|
|
190
|
+
revive?(value: unknown): unknown;
|
|
191
|
+
/** See FrameHostOptions.isContainer. */
|
|
192
|
+
isContainer?(value: unknown): boolean;
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
/**
|
|
@@ -219,6 +223,28 @@ export interface FrameHostOptions {
|
|
|
219
223
|
* `applyData: c => table.apply(c)` (see `createJSONDataTable`).
|
|
220
224
|
*/
|
|
221
225
|
applyData?(chunk: Extract<FrameChunk, { type: "data" }>): void;
|
|
226
|
+
/**
|
|
227
|
+
* A lazily-loaded deserializer's load, awaited by the transport before it
|
|
228
|
+
* delivers a `data` chunk — `applyData`/`resolve` can assume the codec is
|
|
229
|
+
* resident once data has arrived. Keeps codec weight out of the eager
|
|
230
|
+
* client graph for responses that never carry serialized data.
|
|
231
|
+
*/
|
|
232
|
+
prepareData?(): Promise<unknown>;
|
|
233
|
+
/**
|
|
234
|
+
* Revive protocol markers inside LITERAL slot args (values that are
|
|
235
|
+
* neither `{$ref}` nor `{$frame}`) at arg-resolution time. Document-face
|
|
236
|
+
* container traces ride this way — inline in the record, revived by the
|
|
237
|
+
* integration (`reviveContainerTraces`) into live local containers.
|
|
238
|
+
*/
|
|
239
|
+
revive?(value: unknown): unknown;
|
|
240
|
+
/**
|
|
241
|
+
* Whether a resolved arg value is a LIVE CONTAINER (a materialized trace —
|
|
242
|
+
* see `isMaterializedContainer`). The record-dedupe compare must know: a
|
|
243
|
+
* pending container's property reads throw not-ready, so async probes and
|
|
244
|
+
* serialization compares would detonate it. Containers compare by
|
|
245
|
+
* identity only.
|
|
246
|
+
*/
|
|
247
|
+
isContainer?(value: unknown): boolean;
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
/** @experimental */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// shapes and the wire format may change between prereleases (RFC 11).
|
|
4
4
|
// Every export in this module is @experimental.
|
|
5
5
|
import { FrameChunk, FrameHost } from "./frame-client.js";
|
|
6
|
-
import { JSONCodecOptions } from "./serializer.js";
|
|
6
|
+
import { JSONCodecOptions } from "./serializer-decode.js";
|
|
7
7
|
|
|
8
8
|
// Structural mirror of server-functions/shared.js's FlightDataConsumer:
|
|
9
9
|
// this file may only reference siblings that ship with it when integrations
|