@solidjs/start 2.0.0-rc.1 → 2.0.0-rc.10
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/CHANGELOG.md +123 -0
- package/dist/config/app-root-alias.d.ts +7 -0
- package/dist/config/app-root-alias.js +58 -0
- package/dist/config/constants.d.ts +2 -0
- package/dist/config/constants.js +2 -0
- package/dist/config/env.js +2 -2
- package/dist/config/fs-routes/index.js +3 -3
- package/dist/config/fs-routes/tree-shake.d.ts +27 -0
- package/dist/config/fs-routes/tree-shake.js +51 -1
- package/dist/config/index.d.ts +154 -5
- package/dist/config/index.js +16 -8
- package/dist/config/lazy.js +7 -2
- package/dist/config/manifest.d.ts +3 -0
- package/dist/config/manifest.js +26 -4
- package/dist/directives/remove-unused-variables.js +15 -3
- package/dist/directives/xxhash32.js +5 -13
- package/dist/fns/client.js +14 -5
- package/dist/fns/error-handler.d.ts +34 -0
- package/dist/fns/error-handler.js +10 -0
- package/dist/fns/handler.d.ts +1 -1
- package/dist/fns/handler.js +45 -10
- package/dist/fns/plugins.d.ts +34 -0
- package/dist/fns/plugins.js +33 -0
- package/dist/fns/serialization.d.ts +15 -0
- package/dist/fns/serialization.js +36 -6
- package/dist/server/assets/render.jsx +1 -1
- package/dist/server/collect-styles.d.ts +3 -1
- package/dist/server/collect-styles.js +8 -5
- package/dist/server/handler.d.ts +3 -4
- package/dist/server/handler.js +16 -46
- package/dist/server/index.d.ts +2 -1
- package/dist/server/manifest/dev-client-manifest.js +1 -1
- package/dist/server/manifest/dev-ssr-manifest.js +1 -1
- package/dist/server/spa/StartServer.jsx +1 -1
- package/dist/server/spa/handler.d.ts +2 -3
- package/dist/server/spa/handler.js +2 -2
- package/dist/server/types.d.ts +12 -1
- package/dist/server/web-stream.d.ts +1 -1
- package/dist/server/web-stream.js +5 -2
- package/dist/shared/ErrorBoundary.jsx +3 -3
- package/dist/shared/clientOnly.js +3 -1
- package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.jsx +3 -3
- package/dist/shared/{dev-overlay/DevOverlayDialog.d.ts → dev-toolbar/error-viewer/index.d.ts} +3 -2
- package/dist/shared/{dev-overlay/DevOverlayDialog.jsx → dev-toolbar/error-viewer/index.jsx} +66 -77
- package/dist/shared/dev-toolbar/error-viewer/styles.css +224 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.css +4 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.jsx +37 -0
- package/dist/shared/dev-toolbar/functions/FormDataViewer.d.ts +5 -0
- package/dist/shared/dev-toolbar/functions/FormDataViewer.jsx +23 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.css +8 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.jsx +15 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.css +34 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.d.ts +11 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.jsx +70 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.css +5 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.d.ts +7 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.jsx +10 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.css +70 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.jsx +796 -0
- package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.d.ts +5 -0
- package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.jsx +22 -0
- package/dist/shared/dev-toolbar/functions/index.d.ts +13 -0
- package/dist/shared/dev-toolbar/functions/index.jsx +216 -0
- package/dist/shared/dev-toolbar/functions/styles.css +109 -0
- package/dist/shared/dev-toolbar/functions/tracker.d.ts +19 -0
- package/dist/shared/dev-toolbar/functions/tracker.js +29 -0
- package/dist/shared/{dev-overlay → dev-toolbar}/icons.d.ts +9 -0
- package/dist/shared/{dev-overlay → dev-toolbar}/icons.jsx +19 -1
- package/dist/shared/dev-toolbar/index.css +88 -0
- package/dist/shared/dev-toolbar/index.d.ts +6 -0
- package/dist/shared/dev-toolbar/index.jsx +179 -0
- package/dist/shared/ui/Badge.css +33 -0
- package/dist/shared/ui/Badge.d.ts +7 -0
- package/dist/shared/ui/Badge.jsx +7 -0
- package/dist/shared/ui/Button.css +32 -0
- package/dist/shared/ui/Button.d.ts +4 -0
- package/dist/shared/ui/Button.jsx +4 -0
- package/dist/shared/ui/Cascade.css +29 -0
- package/dist/shared/ui/Cascade.d.ts +4 -0
- package/dist/shared/ui/Cascade.jsx +4 -0
- package/dist/shared/ui/Dialog.css +25 -0
- package/dist/shared/ui/Dialog.d.ts +5 -0
- package/dist/shared/ui/Dialog.jsx +5 -0
- package/dist/shared/ui/IconButton.css +39 -0
- package/dist/shared/ui/IconButton.d.ts +4 -0
- package/dist/shared/ui/IconButton.jsx +4 -0
- package/dist/shared/ui/Placeholder.css +12 -0
- package/dist/shared/ui/Placeholder.d.ts +6 -0
- package/dist/shared/ui/Placeholder.jsx +4 -0
- package/dist/shared/ui/Section.css +18 -0
- package/dist/shared/ui/Section.d.ts +9 -0
- package/dist/shared/ui/Section.jsx +10 -0
- package/dist/shared/ui/Select.css +37 -0
- package/dist/shared/ui/Select.d.ts +4 -0
- package/dist/shared/ui/Select.jsx +4 -0
- package/dist/shared/ui/Table.css +22 -0
- package/dist/shared/ui/Table.d.ts +11 -0
- package/dist/shared/ui/Table.jsx +13 -0
- package/dist/shared/ui/Tabs.css +51 -0
- package/dist/shared/ui/Tabs.d.ts +6 -0
- package/dist/shared/ui/Tabs.jsx +6 -0
- package/dist/shared/ui/Text.css +73 -0
- package/dist/shared/ui/Text.d.ts +12 -0
- package/dist/shared/ui/Text.jsx +17 -0
- package/package.json +36 -29
- package/dist/shared/dev-overlay/index.d.ts +0 -5
- package/dist/shared/dev-overlay/index.jsx +0 -39
- package/dist/shared/dev-overlay/styles.css +0 -292
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.d.ts +0 -0
- /package/dist/shared/{dev-overlay/createStackFrame.d.ts → dev-toolbar/error-viewer/create-stack-frame.d.ts} +0 -0
- /package/dist/shared/{dev-overlay/createStackFrame.js → dev-toolbar/error-viewer/create-stack-frame.js} +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.d.ts +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.js +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.d.ts +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.js +0 -0
package/dist/config/manifest.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { version as viteVersion } from "vite";
|
|
3
|
+
import { createFilter, version as viteVersion } from "vite";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { findStylesInModuleGraph } from "../server/collect-styles.js";
|
|
6
6
|
import { VIRTUAL_MODULES } from "./constants.js";
|
|
7
7
|
import { wrapId } from "./vite-utils.js";
|
|
8
|
+
const DEFAULT_STYLE_EXCLUDE = /node_modules/;
|
|
9
|
+
export function createStyleFilter(options) {
|
|
10
|
+
return createFilter(options?.include || [], options?.exclude || DEFAULT_STYLE_EXCLUDE);
|
|
11
|
+
}
|
|
8
12
|
export function manifest(start) {
|
|
9
13
|
let devServer = undefined;
|
|
14
|
+
const styleFilter = createStyleFilter(start.css?.filter);
|
|
10
15
|
return {
|
|
11
16
|
name: "solid-start:manifest-plugin",
|
|
12
17
|
enforce: "pre",
|
|
@@ -28,6 +33,18 @@ export function manifest(start) {
|
|
|
28
33
|
return await this.resolve(start.middleware);
|
|
29
34
|
return `\0${VIRTUAL_MODULES.middleware}`;
|
|
30
35
|
}
|
|
36
|
+
if (id === VIRTUAL_MODULES.serovalPlugins) {
|
|
37
|
+
const plugins = start.serialization?.plugins;
|
|
38
|
+
if (plugins)
|
|
39
|
+
return await this.resolve(plugins);
|
|
40
|
+
return `\0${VIRTUAL_MODULES.serovalPlugins}`;
|
|
41
|
+
}
|
|
42
|
+
if (id === VIRTUAL_MODULES.serverFnErrorHandler) {
|
|
43
|
+
const onError = start.serverFunctions?.onError;
|
|
44
|
+
if (onError)
|
|
45
|
+
return await this.resolve(onError);
|
|
46
|
+
return `\0${VIRTUAL_MODULES.serverFnErrorHandler}`;
|
|
47
|
+
}
|
|
31
48
|
},
|
|
32
49
|
async load(id) {
|
|
33
50
|
if (id === `\0${VIRTUAL_MODULES.clientViteManifest}`) {
|
|
@@ -40,7 +57,7 @@ export function manifest(start) {
|
|
|
40
57
|
if (!entry)
|
|
41
58
|
throw new Error("No client entry found");
|
|
42
59
|
let rawManifest;
|
|
43
|
-
const viteMajor = parseInt(viteVersion.split(
|
|
60
|
+
const viteMajor = parseInt(viteVersion.split(".")[0], 10);
|
|
44
61
|
const manifestKey = Object.keys(globalThis.START_CLIENT_BUNDLE).find(k => k.endsWith("manifest.json"));
|
|
45
62
|
if (manifestKey && viteMajor < 8) {
|
|
46
63
|
const manifestAsset = globalThis.START_CLIENT_BUNDLE[manifestKey];
|
|
@@ -53,7 +70,8 @@ export function manifest(start) {
|
|
|
53
70
|
if (devServer?.environments?.client?.config?.build?.outDir) {
|
|
54
71
|
outDir = devServer.environments.client.config.build.outDir;
|
|
55
72
|
}
|
|
56
|
-
else if (this.environment?.config?.build?.outDir &&
|
|
73
|
+
else if (this.environment?.config?.build?.outDir &&
|
|
74
|
+
this.environment?.config?.consumer === "client") {
|
|
57
75
|
outDir = this.environment.config.build.outDir;
|
|
58
76
|
}
|
|
59
77
|
else if (globalThis.START_CLIENT_OUT_DIR) {
|
|
@@ -75,6 +93,10 @@ export function manifest(start) {
|
|
|
75
93
|
}
|
|
76
94
|
else if (id === `\0${VIRTUAL_MODULES.middleware}`)
|
|
77
95
|
return "export default {};";
|
|
96
|
+
else if (id === `\0${VIRTUAL_MODULES.serovalPlugins}`)
|
|
97
|
+
return "export default [];";
|
|
98
|
+
else if (id === `\0${VIRTUAL_MODULES.serverFnErrorHandler}`)
|
|
99
|
+
return "export default undefined;";
|
|
78
100
|
else if (id.startsWith("/@manifest")) {
|
|
79
101
|
if (this.environment.mode !== "dev")
|
|
80
102
|
throw new Error("@manifest queries are only allowed in dev");
|
|
@@ -91,7 +113,7 @@ export function manifest(start) {
|
|
|
91
113
|
// Client env does not have css dependencies in mod.transformResult
|
|
92
114
|
// Aalways use ssr env instead, to prevent hydration mismatches
|
|
93
115
|
const env = devServer.environments["ssr"];
|
|
94
|
-
const styles = await findStylesInModuleGraph(env, id);
|
|
116
|
+
const styles = await findStylesInModuleGraph(env, id, styleFilter);
|
|
95
117
|
const cssAssets = Object.entries(styles).map(([key, value]) => `{
|
|
96
118
|
tag: "style",
|
|
97
119
|
attrs: {
|
|
@@ -8,10 +8,22 @@ function isInvalidForRemoval(path) {
|
|
|
8
8
|
// This one is for destructured variables
|
|
9
9
|
let target = path;
|
|
10
10
|
if (isPathValid(path, t.isVariableDeclarator)) {
|
|
11
|
-
target = path.get(
|
|
11
|
+
target = path.get("id");
|
|
12
12
|
}
|
|
13
13
|
return isPathValid(target, t.isObjectPattern) || isPathValid(target, t.isArrayPattern);
|
|
14
14
|
}
|
|
15
|
+
function countValidImport(node) {
|
|
16
|
+
if (node.importKind === "type") {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
let count = 0;
|
|
20
|
+
for (const specifier of node.specifiers) {
|
|
21
|
+
if (specifier.type !== "ImportSpecifier" || specifier.importKind === "value") {
|
|
22
|
+
count += 1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return count;
|
|
26
|
+
}
|
|
15
27
|
export function removeUnusedVariables(program) {
|
|
16
28
|
// TODO(Alexis):
|
|
17
29
|
// This implementation is simple but slow
|
|
@@ -34,7 +46,7 @@ export function removeUnusedVariables(program) {
|
|
|
34
46
|
if (binding.references === 0 && !binding.path.removed) {
|
|
35
47
|
const parent = binding.path.parentPath;
|
|
36
48
|
if (isPathValid(parent, t.isImportDeclaration)) {
|
|
37
|
-
if (parent.node
|
|
49
|
+
if (countValidImport(parent.node) <= 1) {
|
|
38
50
|
parent.remove();
|
|
39
51
|
}
|
|
40
52
|
else {
|
|
@@ -42,7 +54,7 @@ export function removeUnusedVariables(program) {
|
|
|
42
54
|
}
|
|
43
55
|
dirty = true;
|
|
44
56
|
}
|
|
45
|
-
else if (!
|
|
57
|
+
else if (!isInvalidForRemoval(binding.path)) {
|
|
46
58
|
binding.path.remove();
|
|
47
59
|
dirty = true;
|
|
48
60
|
}
|
|
@@ -34,7 +34,7 @@ function toUtf8(text) {
|
|
|
34
34
|
* @param seed - optional seed (32-bit unsigned);
|
|
35
35
|
*/
|
|
36
36
|
export default function xxHash32(buffer, seed = 0) {
|
|
37
|
-
buffer = typeof buffer ===
|
|
37
|
+
buffer = typeof buffer === "string" ? toUtf8(buffer) : buffer;
|
|
38
38
|
const b = buffer;
|
|
39
39
|
/*
|
|
40
40
|
Step 1. Initialize internal accumulators
|
|
@@ -144,9 +144,7 @@ export default function xxHash32(buffer, seed = 0) {
|
|
|
144
144
|
const laneP = laneN0 * PRIME32_3 + ((laneN1 * PRIME32_3) << 16);
|
|
145
145
|
acc = (acc + laneP) & 0xffffffff;
|
|
146
146
|
acc = (acc << 17) | (acc >>> 15);
|
|
147
|
-
acc =
|
|
148
|
-
((acc & 0xffff) * PRIME32_4 + (((acc >>> 16) * PRIME32_4) << 16)) &
|
|
149
|
-
0xffffffff;
|
|
147
|
+
acc = ((acc & 0xffff) * PRIME32_4 + (((acc >>> 16) * PRIME32_4) << 16)) & 0xffffffff;
|
|
150
148
|
}
|
|
151
149
|
/*
|
|
152
150
|
```
|
|
@@ -162,9 +160,7 @@ export default function xxHash32(buffer, seed = 0) {
|
|
|
162
160
|
const lane = b[offset];
|
|
163
161
|
acc += lane * PRIME32_5;
|
|
164
162
|
acc = (acc << 11) | (acc >>> 21);
|
|
165
|
-
acc =
|
|
166
|
-
((acc & 0xffff) * PRIME32_1 + (((acc >>> 16) * PRIME32_1) << 16)) &
|
|
167
|
-
0xffffffff;
|
|
163
|
+
acc = ((acc & 0xffff) * PRIME32_1 + (((acc >>> 16) * PRIME32_1) << 16)) & 0xffffffff;
|
|
168
164
|
}
|
|
169
165
|
/*
|
|
170
166
|
Step 6. Final mix (avalanche)
|
|
@@ -180,13 +176,9 @@ export default function xxHash32(buffer, seed = 0) {
|
|
|
180
176
|
```
|
|
181
177
|
*/
|
|
182
178
|
acc ^= acc >>> 15;
|
|
183
|
-
acc =
|
|
184
|
-
(((acc & 0xffff) * PRIME32_2) & 0xffffffff) +
|
|
185
|
-
(((acc >>> 16) * PRIME32_2) << 16);
|
|
179
|
+
acc = (((acc & 0xffff) * PRIME32_2) & 0xffffffff) + (((acc >>> 16) * PRIME32_2) << 16);
|
|
186
180
|
acc ^= acc >>> 13;
|
|
187
|
-
acc =
|
|
188
|
-
(((acc & 0xffff) * PRIME32_3) & 0xffffffff) +
|
|
189
|
-
(((acc >>> 16) * PRIME32_3) << 16);
|
|
181
|
+
acc = (((acc & 0xffff) * PRIME32_3) & 0xffffffff) + (((acc >>> 16) * PRIME32_3) << 16);
|
|
190
182
|
acc ^= acc >>> 16;
|
|
191
183
|
// turn any negatives back into a positive number;
|
|
192
184
|
return acc < 0 ? acc + 4294967296 : acc;
|
package/dist/fns/client.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { pushRequest, pushResponse } from "../shared/dev-toolbar/functions/tracker.js";
|
|
1
2
|
import {
|
|
2
3
|
// serializeToJSONStream,
|
|
3
4
|
serializeToJSONString, } from "./serialization.js";
|
|
4
|
-
import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody
|
|
5
|
+
import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody } from "./shared.js";
|
|
5
6
|
let INSTANCE = 0;
|
|
6
|
-
function createRequest(base, id, instance, options) {
|
|
7
|
-
|
|
7
|
+
async function createRequest(base, id, instance, options) {
|
|
8
|
+
const request = new Request(base, {
|
|
8
9
|
method: "POST",
|
|
9
10
|
...options,
|
|
10
11
|
headers: {
|
|
@@ -13,6 +14,14 @@ function createRequest(base, id, instance, options) {
|
|
|
13
14
|
"X-Server-Instance": instance,
|
|
14
15
|
},
|
|
15
16
|
});
|
|
17
|
+
if (import.meta.env.DEV) {
|
|
18
|
+
pushRequest(id, instance, request.clone());
|
|
19
|
+
}
|
|
20
|
+
const response = await fetch(request);
|
|
21
|
+
if (import.meta.env.DEV) {
|
|
22
|
+
pushResponse(id, instance, response.clone());
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
16
25
|
}
|
|
17
26
|
async function initializeResponse(base, id, instance, options, args) {
|
|
18
27
|
// No args, skip serialization
|
|
@@ -63,8 +72,8 @@ async function fetchServerFunction(base, id, options, args) {
|
|
|
63
72
|
return response;
|
|
64
73
|
}
|
|
65
74
|
const result = await extractBody(instance, true, response.clone());
|
|
66
|
-
if (response.headers.has("X-Error")) {
|
|
67
|
-
throw result;
|
|
75
|
+
if (response.headers.has("X-Error") || response.status >= 500) {
|
|
76
|
+
throw result ?? new Error(`Server function call failed with status ${response.status}`);
|
|
68
77
|
}
|
|
69
78
|
return result;
|
|
70
79
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles whatever a server function threw, before it reaches the client. Use
|
|
3
|
+
* it to type the default export of the module named by the
|
|
4
|
+
* `serverFunctions.onError` option in `vite.config.ts`.
|
|
5
|
+
*
|
|
6
|
+
* The handler may be asynchronous. SolidStart awaits its return value before
|
|
7
|
+
* sending the error to the client. If the handler throws or rejects, SolidStart
|
|
8
|
+
* sends the original thrown value instead.
|
|
9
|
+
*
|
|
10
|
+
* @param thrown The value the server function threw. This is a `Response` when
|
|
11
|
+
* the server function threw control flow such as a `redirect()`.
|
|
12
|
+
* @returns `undefined` (or `null`) to send `thrown` unchanged, a `Response` to
|
|
13
|
+
* preserve control flow, any other replacement value, or a promise resolving
|
|
14
|
+
* to any of those values.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // src/server-fn-error.ts
|
|
19
|
+
* import type { ServerFunctionErrorHandler } from "@solidjs/start/server";
|
|
20
|
+
* import { captureException } from "./your-monitoring-client";
|
|
21
|
+
*
|
|
22
|
+
* const onServerFunctionError: ServerFunctionErrorHandler = thrown => {
|
|
23
|
+
* // redirect() throws a Response, so returning it preserves that control flow.
|
|
24
|
+
* if (thrown instanceof Response) return thrown;
|
|
25
|
+
*
|
|
26
|
+
* captureException(thrown); // or console.error, or any reporter
|
|
27
|
+
* return new Error("Something went wrong");
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* export default onServerFunctionError;
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export type ServerFunctionErrorHandler = (thrown: unknown) => unknown;
|
|
34
|
+
export declare function applyServerFunctionErrorHandler(thrown: unknown): Promise<unknown>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import onServerFunctionError from "solid-start:server-fn-error-handler";
|
|
2
|
+
export async function applyServerFunctionErrorHandler(thrown) {
|
|
3
|
+
try {
|
|
4
|
+
const replacement = await onServerFunctionError?.(thrown);
|
|
5
|
+
return replacement ?? thrown;
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return thrown;
|
|
9
|
+
}
|
|
10
|
+
}
|
package/dist/fns/handler.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ import { type H3Event } from "h3";
|
|
|
2
2
|
import "solid-start:server-fn-manifest";
|
|
3
3
|
import type { FetchEvent } from "../server/types.ts";
|
|
4
4
|
export declare function handleServerFunction(h3Event: H3Event): Promise<unknown>;
|
|
5
|
-
export declare function createSingleFlightHeaders(sourceEvent: FetchEvent): Headers;
|
|
5
|
+
export declare function createSingleFlightHeaders(sourceEvent: FetchEvent, result?: unknown): Headers;
|
package/dist/fns/handler.js
CHANGED
|
@@ -17,6 +17,7 @@ import { deserializeFromJSONString, serializeToJSONStream, serializeToJSStream,
|
|
|
17
17
|
import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody } from "./shared.js";
|
|
18
18
|
import "solid-start:server-fn-manifest";
|
|
19
19
|
import { getServerFunction, hasServerFunction } from "./registration.js";
|
|
20
|
+
import { applyServerFunctionErrorHandler } from "./error-handler.js";
|
|
20
21
|
import { getExpectedRedirectStatus } from "../server/util.js";
|
|
21
22
|
export async function handleServerFunction(h3Event) {
|
|
22
23
|
const event = getFetchEvent(h3Event);
|
|
@@ -109,7 +110,7 @@ export async function handleServerFunction(h3Event) {
|
|
|
109
110
|
}
|
|
110
111
|
// handle no JS success case
|
|
111
112
|
if (!instance)
|
|
112
|
-
return handleNoJS(result, request, parsed);
|
|
113
|
+
return await handleNoJS(result, request, parsed);
|
|
113
114
|
const body = getHeadersAndBody(result);
|
|
114
115
|
if (body) {
|
|
115
116
|
return new Response(body.body, {
|
|
@@ -121,10 +122,10 @@ export async function handleServerFunction(h3Event) {
|
|
|
121
122
|
h3Event.res.headers.set("content-type", "text/javascript");
|
|
122
123
|
return serializeToJSStream(instance, result);
|
|
123
124
|
}
|
|
124
|
-
h3Event.res.headers.set("content-type", "text/plain");
|
|
125
125
|
return serializeToJSONStream(result);
|
|
126
126
|
}
|
|
127
127
|
catch (x) {
|
|
128
|
+
x = await applyServerFunctionErrorHandler(x);
|
|
128
129
|
if (x instanceof Response) {
|
|
129
130
|
if (singleFlight && instance) {
|
|
130
131
|
x = await handleSingleFlight(event, x);
|
|
@@ -147,7 +148,7 @@ export async function handleServerFunction(h3Event) {
|
|
|
147
148
|
h3Event.res.headers.set("X-Error", toHeaderValue(error));
|
|
148
149
|
}
|
|
149
150
|
else {
|
|
150
|
-
x = handleNoJS(x, request, parsed, true);
|
|
151
|
+
x = await handleNoJS(x, request, parsed, true);
|
|
151
152
|
}
|
|
152
153
|
if (instance) {
|
|
153
154
|
const body = getHeadersAndBody(x);
|
|
@@ -166,7 +167,6 @@ export async function handleServerFunction(h3Event) {
|
|
|
166
167
|
h3Event.res.headers.set("content-type", "text/javascript");
|
|
167
168
|
return serializeToJSStream(instance, x);
|
|
168
169
|
}
|
|
169
|
-
h3Event.res.headers.set("content-type", "text/plain");
|
|
170
170
|
return serializeToJSONStream(x);
|
|
171
171
|
}
|
|
172
172
|
return x;
|
|
@@ -183,7 +183,20 @@ function toHeaderValue(value) {
|
|
|
183
183
|
return "true";
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
-
function
|
|
186
|
+
function getRefererLocation(request, url) {
|
|
187
|
+
const referer = request.headers.get("referer");
|
|
188
|
+
try {
|
|
189
|
+
if (referer)
|
|
190
|
+
return new URL(referer).toString();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// fall through to the app root below
|
|
194
|
+
}
|
|
195
|
+
// no usable referer (e.g. a no-referrer policy): the app root still beats
|
|
196
|
+
// leaving the browser sitting on the server function endpoint
|
|
197
|
+
return new URL(import.meta.env.BASE_URL, url.origin).toString();
|
|
198
|
+
}
|
|
199
|
+
async function handleNoJS(result, request, parsed, thrown) {
|
|
187
200
|
const url = new URL(request.url);
|
|
188
201
|
const isError = result instanceof Error;
|
|
189
202
|
let statusCode = 302;
|
|
@@ -194,10 +207,19 @@ function handleNoJS(result, request, parsed, thrown) {
|
|
|
194
207
|
headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.BASE_URL).toString());
|
|
195
208
|
statusCode = getExpectedRedirectStatus(result);
|
|
196
209
|
}
|
|
210
|
+
else {
|
|
211
|
+
// responses that carry a value rather than a destination (json(), reload())
|
|
212
|
+
// still have to send the browser back to the page the form came from
|
|
213
|
+
headers.set("Location", getRefererLocation(request, url));
|
|
214
|
+
}
|
|
215
|
+
// the body is dropped from the redirect, so don't advertise its type
|
|
216
|
+
headers.delete("Content-Type");
|
|
217
|
+
// mirror the JS path: the flash cookie carries the value, not the Response
|
|
218
|
+
result = result.customBody ? await result.customBody() : null;
|
|
197
219
|
}
|
|
198
220
|
else
|
|
199
221
|
headers = new Headers({
|
|
200
|
-
Location:
|
|
222
|
+
Location: getRefererLocation(request, url),
|
|
201
223
|
});
|
|
202
224
|
if (result) {
|
|
203
225
|
headers.append("Set-Cookie", `flash=${encodeURIComponent(JSON.stringify({
|
|
@@ -205,7 +227,9 @@ function handleNoJS(result, request, parsed, thrown) {
|
|
|
205
227
|
result: isError ? result.message : result,
|
|
206
228
|
thrown: thrown,
|
|
207
229
|
error: isError,
|
|
208
|
-
input:
|
|
230
|
+
input: parsed.length
|
|
231
|
+
? [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
|
|
232
|
+
: [],
|
|
209
233
|
}))}; Secure; HttpOnly;`);
|
|
210
234
|
}
|
|
211
235
|
return new Response(null, {
|
|
@@ -214,13 +238,19 @@ function handleNoJS(result, request, parsed, thrown) {
|
|
|
214
238
|
});
|
|
215
239
|
}
|
|
216
240
|
let App;
|
|
217
|
-
export function createSingleFlightHeaders(sourceEvent) {
|
|
241
|
+
export function createSingleFlightHeaders(sourceEvent, result) {
|
|
218
242
|
// cookie handling logic is pretty simplistic so this might be imperfect
|
|
219
243
|
// unclear if h3 internals are available on all platforms but we need a way to
|
|
220
244
|
// update request headers on the underlying H3 event.
|
|
221
245
|
const headers = new Headers(sourceEvent.request.headers);
|
|
222
246
|
const cookies = parseCookies(sourceEvent.nativeEvent);
|
|
223
247
|
const SetCookies = sourceEvent.response.headers.getSetCookie();
|
|
248
|
+
// cookies attached to the returned/thrown response (eg. `redirect(to, { headers })`)
|
|
249
|
+
// haven't been merged onto the event response yet, but a browser round trip would
|
|
250
|
+
// have sent them back with the next request, so apply them here too. They come after
|
|
251
|
+
// the ones on the event response, so they win on conflict.
|
|
252
|
+
if (result instanceof Response)
|
|
253
|
+
SetCookies.push(...result.headers.getSetCookie());
|
|
224
254
|
headers.delete("cookie");
|
|
225
255
|
// let useH3Internals = false;
|
|
226
256
|
// if (sourceEvent.nativeEvent.node?.req) {
|
|
@@ -230,7 +260,12 @@ export function createSingleFlightHeaders(sourceEvent) {
|
|
|
230
260
|
SetCookies.forEach(cookie => {
|
|
231
261
|
if (!cookie)
|
|
232
262
|
return;
|
|
233
|
-
|
|
263
|
+
// `parseSetCookie` returns undefined for forbidden cookie names and for
|
|
264
|
+
// cookies with an empty name and value.
|
|
265
|
+
const parsed = parseSetCookie(cookie);
|
|
266
|
+
if (!parsed)
|
|
267
|
+
return;
|
|
268
|
+
const { maxAge, expires, name, value } = parsed;
|
|
234
269
|
if (maxAge != null && maxAge <= 0) {
|
|
235
270
|
delete cookies[name];
|
|
236
271
|
return;
|
|
@@ -259,7 +294,7 @@ async function handleSingleFlight(sourceEvent, result) {
|
|
|
259
294
|
}
|
|
260
295
|
const event = { ...sourceEvent };
|
|
261
296
|
event.request = new Request(url, {
|
|
262
|
-
headers: createSingleFlightHeaders(sourceEvent),
|
|
297
|
+
headers: createSingleFlightHeaders(sourceEvent, result),
|
|
263
298
|
});
|
|
264
299
|
return await provideRequestEvent(event, async () => {
|
|
265
300
|
await createPageEvent(event);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports Seroval's plugin authoring API for use with the
|
|
3
|
+
* `serialization.plugins` option in `vite.config.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Importing from here rather than depending on `seroval` directly keeps plugin
|
|
6
|
+
* authors on the exact Seroval version SolidStart serializes with. A mismatched
|
|
7
|
+
* version would not fail the build: it would produce plugin nodes the other end
|
|
8
|
+
* of the wire can't interpret.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/solidjs/solid-start/issues/1474
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // src/seroval-plugins.ts
|
|
15
|
+
* import { createPlugin } from "@solidjs/start/serialization";
|
|
16
|
+
* import { ObjectId } from "mongodb";
|
|
17
|
+
*
|
|
18
|
+
* const ObjectIdPlugin = createPlugin<ObjectId, { hex: any }>({
|
|
19
|
+
* tag: "app/ObjectId",
|
|
20
|
+
* test: value => value instanceof ObjectId,
|
|
21
|
+
* parse: {
|
|
22
|
+
* sync: (value, ctx) => ({ hex: ctx.parse(value.toHexString()) }),
|
|
23
|
+
* async: async (value, ctx) => ({ hex: await ctx.parse(value.toHexString()) }),
|
|
24
|
+
* stream: (value, ctx) => ({ hex: ctx.parse(value.toHexString()) }),
|
|
25
|
+
* },
|
|
26
|
+
* serialize: (node, ctx) => `globalThis.ObjectId(${ctx.serialize(node.hex)})`,
|
|
27
|
+
* deserialize: (node, ctx) => new ObjectId(ctx.deserialize(node.hex) as string),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* export default [ObjectIdPlugin];
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export { createPlugin, OpaqueReference } from "seroval";
|
|
34
|
+
export type { AsyncParsePluginContext, DeserializePluginContext, Plugin, PluginData, PluginInfo, SerializePluginContext, SerovalNode, StreamParsePluginContext, SyncParsePluginContext, } from "seroval";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports Seroval's plugin authoring API for use with the
|
|
3
|
+
* `serialization.plugins` option in `vite.config.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Importing from here rather than depending on `seroval` directly keeps plugin
|
|
6
|
+
* authors on the exact Seroval version SolidStart serializes with. A mismatched
|
|
7
|
+
* version would not fail the build: it would produce plugin nodes the other end
|
|
8
|
+
* of the wire can't interpret.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/solidjs/solid-start/issues/1474
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // src/seroval-plugins.ts
|
|
15
|
+
* import { createPlugin } from "@solidjs/start/serialization";
|
|
16
|
+
* import { ObjectId } from "mongodb";
|
|
17
|
+
*
|
|
18
|
+
* const ObjectIdPlugin = createPlugin<ObjectId, { hex: any }>({
|
|
19
|
+
* tag: "app/ObjectId",
|
|
20
|
+
* test: value => value instanceof ObjectId,
|
|
21
|
+
* parse: {
|
|
22
|
+
* sync: (value, ctx) => ({ hex: ctx.parse(value.toHexString()) }),
|
|
23
|
+
* async: async (value, ctx) => ({ hex: await ctx.parse(value.toHexString()) }),
|
|
24
|
+
* stream: (value, ctx) => ({ hex: ctx.parse(value.toHexString()) }),
|
|
25
|
+
* },
|
|
26
|
+
* serialize: (node, ctx) => `globalThis.ObjectId(${ctx.serialize(node.hex)})`,
|
|
27
|
+
* deserialize: (node, ctx) => new ObjectId(ctx.deserialize(node.hex) as string),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* export default [ObjectIdPlugin];
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export { createPlugin, OpaqueReference } from "seroval";
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
export declare function serializeToJSStream(id: string, value: any): ReadableStream<any>;
|
|
2
2
|
export declare function serializeToJSONStream(value: any): ReadableStream<any>;
|
|
3
|
+
export declare class SerovalChunkReader {
|
|
4
|
+
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
5
|
+
buffer: Uint8Array;
|
|
6
|
+
done: boolean;
|
|
7
|
+
constructor(stream: ReadableStream<Uint8Array>);
|
|
8
|
+
readChunk(): Promise<void>;
|
|
9
|
+
next(): Promise<{
|
|
10
|
+
done: true;
|
|
11
|
+
value: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
done: false;
|
|
14
|
+
value: string;
|
|
15
|
+
}>;
|
|
16
|
+
drain(interpret: (chunk: string) => void): Promise<void>;
|
|
17
|
+
}
|
|
3
18
|
export declare function serializeToJSONString(value: any): Promise<string>;
|
|
4
19
|
export declare function deserializeFromJSONString(json: string): Promise<unknown>;
|
|
5
20
|
export declare function deserializeJSONStream(response: Response | Request): Promise<unknown>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { crossSerializeStream, deserialize, Feature, fromCrossJSON, getCrossReferenceHeader, toCrossJSONStream, } from "seroval";
|
|
2
2
|
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin, } from "seroval-plugins/web";
|
|
3
|
-
|
|
3
|
+
import userPlugins from "solid-start:seroval-plugins";
|
|
4
4
|
const DEFAULT_PLUGINS = [
|
|
5
5
|
AbortSignalPlugin,
|
|
6
6
|
CustomEventPlugin,
|
|
@@ -14,8 +14,37 @@ const DEFAULT_PLUGINS = [
|
|
|
14
14
|
URLSearchParamsPlugin,
|
|
15
15
|
URLPlugin,
|
|
16
16
|
];
|
|
17
|
+
/**
|
|
18
|
+
* Plugins from `serialization.plugins` are appended rather than prepended:
|
|
19
|
+
* seroval picks the first plugin whose `test()` passes, so the built-ins win
|
|
20
|
+
* and a loose user `test()` can't take over `Request`/`FormData`/`URL`.
|
|
21
|
+
*
|
|
22
|
+
* The same list has to be used on both ends of a server function, which is why
|
|
23
|
+
* this comes from a virtual module bundled into the client and the server
|
|
24
|
+
* rather than a runtime option.
|
|
25
|
+
*/
|
|
26
|
+
const PLUGINS = [...DEFAULT_PLUGINS, ...userPlugins];
|
|
17
27
|
const MAX_SERIALIZATION_DEPTH_LIMIT = 64;
|
|
18
28
|
const DISABLED_FEATURES = Feature.RegExp;
|
|
29
|
+
/**
|
|
30
|
+
* An error thrown by a server function is serialized and rethrown on the
|
|
31
|
+
* client, and seroval includes `Error.prototype.stack` by default. In
|
|
32
|
+
* production that leaks server file paths, internal function names and the
|
|
33
|
+
* shape of the deployment to anyone who can trigger a throw, so strip it.
|
|
34
|
+
* Development keeps the stack: that's where it's actually useful, and the
|
|
35
|
+
* paths it exposes are the developer's own.
|
|
36
|
+
*
|
|
37
|
+
* Only applied when writing; parsing leaves `DISABLED_FEATURES` alone so an
|
|
38
|
+
* incoming payload that does carry a stack still deserializes.
|
|
39
|
+
*/
|
|
40
|
+
const SERIALIZE_DISABLED_FEATURES = import.meta.env.PROD
|
|
41
|
+
? DISABLED_FEATURES | Feature.ErrorPrototypeStack
|
|
42
|
+
: DISABLED_FEATURES;
|
|
43
|
+
/**
|
|
44
|
+
* `crossSerializeStream` historically ran with every feature enabled, so only
|
|
45
|
+
* add the stack removal here rather than the full serialize set.
|
|
46
|
+
*/
|
|
47
|
+
const JS_SERIALIZE_DISABLED_FEATURES = import.meta.env.PROD ? Feature.ErrorPrototypeStack : 0;
|
|
19
48
|
/**
|
|
20
49
|
* Alexis:
|
|
21
50
|
*
|
|
@@ -47,7 +76,8 @@ export function serializeToJSStream(id, value) {
|
|
|
47
76
|
start(controller) {
|
|
48
77
|
crossSerializeStream(value, {
|
|
49
78
|
scopeId: id,
|
|
50
|
-
|
|
79
|
+
disabledFeatures: JS_SERIALIZE_DISABLED_FEATURES,
|
|
80
|
+
plugins: PLUGINS,
|
|
51
81
|
onSerialize(data, initial) {
|
|
52
82
|
controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
|
|
53
83
|
},
|
|
@@ -65,9 +95,9 @@ export function serializeToJSONStream(value) {
|
|
|
65
95
|
return new ReadableStream({
|
|
66
96
|
start(controller) {
|
|
67
97
|
toCrossJSONStream(value, {
|
|
68
|
-
disabledFeatures:
|
|
98
|
+
disabledFeatures: SERIALIZE_DISABLED_FEATURES,
|
|
69
99
|
depthLimit: MAX_SERIALIZATION_DEPTH_LIMIT,
|
|
70
|
-
plugins:
|
|
100
|
+
plugins: PLUGINS,
|
|
71
101
|
onParse(node) {
|
|
72
102
|
controller.enqueue(createChunk(JSON.stringify(node)));
|
|
73
103
|
},
|
|
@@ -81,7 +111,7 @@ export function serializeToJSONStream(value) {
|
|
|
81
111
|
},
|
|
82
112
|
});
|
|
83
113
|
}
|
|
84
|
-
class SerovalChunkReader {
|
|
114
|
+
export class SerovalChunkReader {
|
|
85
115
|
reader;
|
|
86
116
|
buffer;
|
|
87
117
|
done;
|
|
@@ -180,7 +210,7 @@ export async function deserializeJSONStream(response) {
|
|
|
180
210
|
refs,
|
|
181
211
|
disabledFeatures: DISABLED_FEATURES,
|
|
182
212
|
depthLimit: MAX_SERIALIZATION_DEPTH_LIMIT,
|
|
183
|
-
plugins:
|
|
213
|
+
plugins: PLUGINS,
|
|
184
214
|
});
|
|
185
215
|
return value;
|
|
186
216
|
}
|
|
@@ -9,6 +9,6 @@ const assetMap = {
|
|
|
9
9
|
noscript: (props) => (<noscript {...props.attrs}>{props.children}</noscript>),
|
|
10
10
|
};
|
|
11
11
|
export function renderAsset(asset, nonce) {
|
|
12
|
-
let { tag, attrs: { key, ...attrs } = { key: undefined }, children
|
|
12
|
+
let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset;
|
|
13
13
|
return assetMap[tag]({ attrs: { ...attrs, nonce }, key, children });
|
|
14
14
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { DevEnvironment } from "vite";
|
|
2
|
+
type StyleFilter = (id: string) => boolean;
|
|
2
3
|
export declare const isCssModulesFile: (file: string) => boolean;
|
|
3
|
-
export declare function findStylesInModuleGraph(vite: DevEnvironment, id: string): Promise<Record<string, any>>;
|
|
4
|
+
export declare function findStylesInModuleGraph(vite: DevEnvironment, id: string, filter: StyleFilter): Promise<Record<string, any>>;
|
|
5
|
+
export {};
|
|
@@ -8,13 +8,16 @@ async function getViteModuleNode(vite, file, importer) {
|
|
|
8
8
|
}
|
|
9
9
|
catch (err) { }
|
|
10
10
|
}
|
|
11
|
-
async function findModuleDependencies(vite, file, deps, crawledFiles = new Set(), importer) {
|
|
11
|
+
async function findModuleDependencies(vite, file, deps, filter, crawledFiles = new Set(), importer) {
|
|
12
12
|
crawledFiles.add(file);
|
|
13
13
|
const module = await getViteModuleNode(vite, file, importer);
|
|
14
14
|
if (!module?.id || deps.has(module))
|
|
15
15
|
return;
|
|
16
16
|
deps.add(module);
|
|
17
|
-
if (module.url.endsWith(".css")
|
|
17
|
+
if (module.url.endsWith(".css"))
|
|
18
|
+
return;
|
|
19
|
+
// Apply user-config file filters only to real files (virtual modules should always be included)
|
|
20
|
+
if (module.file && !module.id.startsWith("\0") && !filter(module.file))
|
|
18
21
|
return;
|
|
19
22
|
if (!module.transformResult) {
|
|
20
23
|
await vite.transformRequest(module.id).catch(() => { });
|
|
@@ -28,7 +31,7 @@ async function findModuleDependencies(vite, file, deps, crawledFiles = new Set()
|
|
|
28
31
|
if (crawledFiles.has(dep)) {
|
|
29
32
|
continue;
|
|
30
33
|
}
|
|
31
|
-
await findModuleDependencies(vite, dep, deps, crawledFiles, module.id);
|
|
34
|
+
await findModuleDependencies(vite, dep, deps, filter, crawledFiles, module.id);
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
// Vite doesn't expose these so we just copy the list for now
|
|
@@ -38,11 +41,11 @@ const cssFileRegExp = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
|
|
|
38
41
|
const cssModulesRegExp = new RegExp(`\\.module${cssFileRegExp.source}`);
|
|
39
42
|
const isCssFile = (file) => cssFileRegExp.test(file);
|
|
40
43
|
export const isCssModulesFile = (file) => cssModulesRegExp.test(file);
|
|
41
|
-
export async function findStylesInModuleGraph(vite, id) {
|
|
44
|
+
export async function findStylesInModuleGraph(vite, id, filter) {
|
|
42
45
|
const absolute = path.resolve(process.cwd(), id);
|
|
43
46
|
const dependencies = new Set();
|
|
44
47
|
try {
|
|
45
|
-
await findModuleDependencies(vite, absolute, dependencies);
|
|
48
|
+
await findModuleDependencies(vite, absolute, dependencies, filter);
|
|
46
49
|
}
|
|
47
50
|
catch (e) {
|
|
48
51
|
console.error(e);
|
package/dist/server/handler.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { H3 } from "h3/generic";
|
|
2
1
|
import type { JSX } from "solid-js";
|
|
3
|
-
import type { FetchEvent, HandlerOptions, PageEvent } from "./types.ts";
|
|
4
|
-
export declare function createBaseHandler(createPageEvent: (e: FetchEvent) => Promise<PageEvent>, fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>)):
|
|
5
|
-
export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>)):
|
|
2
|
+
import type { FetchEvent, HandlerOptions, PageEvent, StartHandler } from "./types.ts";
|
|
3
|
+
export declare function createBaseHandler(createPageEvent: (e: FetchEvent) => Promise<PageEvent>, fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): StartHandler;
|
|
4
|
+
export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): StartHandler;
|
|
6
5
|
export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
|