@solidjs/start 1.2.0 → 2.0.0-alpha.0
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/README.md +88 -8
- package/dist/client/StartClient.d.ts +0 -1
- package/dist/client/StartClient.jsx +2 -4
- package/dist/client/index.d.ts +2 -3
- package/dist/client/index.jsx +2 -4
- package/dist/client/mount.js +10 -2
- package/dist/client/spa/index.d.ts +1 -2
- package/dist/client/spa/index.jsx +1 -2
- package/dist/config/constants.d.ts +16 -0
- package/dist/config/constants.js +16 -0
- package/dist/config/dev-server.d.ts +2 -0
- package/dist/config/dev-server.js +108 -0
- package/dist/config/fs-router.d.ts +37 -0
- package/dist/config/fs-router.js +153 -0
- package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
- package/dist/config/fs-routes/fs-watcher.js +49 -0
- package/dist/config/fs-routes/index.d.ts +7 -0
- package/dist/config/fs-routes/index.js +109 -0
- package/dist/config/fs-routes/router.d.ts +37 -0
- package/dist/config/fs-routes/router.js +136 -0
- package/dist/config/fs-routes/tree-shake.d.ts +2 -0
- package/dist/config/fs-routes/tree-shake.js +357 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +217 -0
- package/dist/config/lazy.d.ts +3 -0
- package/dist/config/lazy.js +82 -0
- package/dist/config/manifest.d.ts +3 -0
- package/dist/config/manifest.js +74 -0
- package/dist/config/utils.d.ts +4 -0
- package/dist/config/utils.js +6 -0
- package/dist/config/vite-utils.d.ts +16 -0
- package/dist/config/vite-utils.js +81 -0
- package/dist/http/index.d.ts +84 -0
- package/dist/http/index.js +131 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.jsx +5 -5
- package/dist/middleware/index.d.ts +6 -6
- package/dist/middleware/index.js +39 -0
- package/dist/{router/FileRoutes.js → router.jsx} +5 -6
- package/dist/server/StartServer.d.ts +3 -3
- package/dist/server/StartServer.jsx +9 -63
- package/dist/server/assets/index.d.ts +2 -0
- package/dist/server/assets/index.js +52 -0
- package/dist/server/assets/render.d.ts +19 -0
- package/dist/server/{renderAsset.jsx → assets/render.jsx} +1 -1
- package/dist/server/collect-styles.d.ts +3 -0
- package/dist/server/collect-styles.js +69 -0
- package/dist/server/fetchEvent.d.ts +4 -3
- package/dist/server/fetchEvent.js +12 -74
- package/dist/server/fetchEvent.spec.js +18 -197
- package/dist/server/handler.d.ts +6 -12
- package/dist/server/handler.js +180 -97
- package/dist/server/index.d.ts +8 -6
- package/dist/server/index.jsx +14 -6
- package/dist/server/manifest/client-manifest.d.ts +9 -0
- package/dist/server/manifest/client-manifest.js +6 -0
- package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
- package/dist/server/manifest/dev-client-manifest.js +24 -0
- package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
- package/dist/server/manifest/dev-ssr-manifest.js +23 -0
- package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
- package/dist/server/manifest/prod-client-manifest.js +26 -0
- package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
- package/dist/server/manifest/prod-ssr-manifest.js +90 -0
- package/dist/server/manifest/ssr-manifest.d.ts +4 -0
- package/dist/server/manifest/ssr-manifest.js +6 -0
- package/dist/{router → server}/routes.d.ts +5 -10
- package/dist/{router → server}/routes.js +35 -36
- package/dist/{runtime → server}/server-fns-runtime.d.ts +1 -1
- package/dist/{runtime → server}/server-fns-runtime.js +7 -6
- package/dist/server/server-functions-handler.d.ts +2 -0
- package/dist/{runtime/server-handler.js → server/server-functions-handler.js} +65 -100
- package/dist/server/server-runtime.d.ts +3 -0
- package/dist/{runtime → server}/server-runtime.js +9 -16
- package/dist/server/spa/StartServer.d.ts +1 -1
- package/dist/server/spa/StartServer.jsx +7 -9
- package/dist/server/spa/handler.d.ts +3 -3
- package/dist/server/spa/handler.js +9 -11
- package/dist/server/spa/index.d.ts +4 -3
- package/dist/server/spa/index.jsx +4 -3
- package/dist/server/types.d.ts +7 -9
- package/dist/server/util.d.ts +2 -0
- package/dist/server/util.js +8 -0
- package/dist/shared/ErrorBoundary.jsx +2 -2
- package/dist/shared/HttpHeader.jsx +4 -2
- package/dist/shared/{HttpStatusCode.jsx → HttpStatusCode.js} +3 -1
- package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +2 -2
- package/dist/shared/dev-overlay/DevOverlayDialog.jsx +75 -66
- package/dist/shared/dev-overlay/createStackFrame.js +3 -3
- package/dist/shared/dev-overlay/index.jsx +5 -8
- package/dist/shared/lazy.d.ts +3 -0
- package/dist/shared/lazy.js +40 -0
- package/dist/shared/serverFunction.d.ts +1 -1
- package/package.json +45 -67
- package/scripts/build.js +15 -0
- package/scripts/validate-imports.js +316 -0
- package/src/client/StartClient.tsx +34 -0
- package/src/client/index.tsx +2 -0
- package/src/client/mount.ts +114 -0
- package/src/client/spa/index.tsx +9 -0
- package/src/config/constants.ts +19 -0
- package/src/config/dev-server.ts +149 -0
- package/src/config/fs-router.ts +177 -0
- package/src/config/fs-routes/fs-watcher.ts +81 -0
- package/src/config/fs-routes/index.ts +138 -0
- package/src/config/fs-routes/router.ts +169 -0
- package/src/config/fs-routes/tree-shake.ts +392 -0
- package/src/config/index.ts +236 -0
- package/src/config/lazy.ts +100 -0
- package/src/config/manifest.ts +84 -0
- package/src/config/utils.ts +5 -0
- package/src/config/vite-utils.ts +113 -0
- package/src/env.d.ts +35 -0
- package/src/http/index.ts +253 -0
- package/src/index.tsx +19 -0
- package/src/internal.d.ts +14 -0
- package/src/middleware/index.ts +82 -0
- package/src/router.tsx +36 -0
- package/src/server/StartServer.tsx +62 -0
- package/src/server/assets/index.ts +70 -0
- package/src/server/assets/render.tsx +42 -0
- package/src/server/collect-styles.ts +94 -0
- package/src/server/fetchEvent.spec.ts +89 -0
- package/src/server/fetchEvent.ts +36 -0
- package/src/server/handler.ts +250 -0
- package/src/server/index.tsx +16 -0
- package/src/server/manifest/client-manifest.ts +8 -0
- package/src/server/manifest/dev-client-manifest.ts +19 -0
- package/src/server/manifest/dev-ssr-manifest.ts +21 -0
- package/src/server/manifest/prod-client-manifest.ts +18 -0
- package/src/server/manifest/prod-ssr-manifest.ts +125 -0
- package/src/server/manifest/ssr-manifest.ts +8 -0
- package/src/server/routes.ts +138 -0
- package/src/server/server-fns-runtime.ts +31 -0
- package/src/server/server-functions-handler.ts +364 -0
- package/src/server/server-runtime.ts +240 -0
- package/src/server/spa/StartServer.tsx +40 -0
- package/src/server/spa/handler.ts +29 -0
- package/src/server/spa/index.tsx +5 -0
- package/src/server/types.ts +82 -0
- package/src/server/util.ts +12 -0
- package/src/shared/ErrorBoundary.tsx +52 -0
- package/src/shared/GET.ts +8 -0
- package/src/shared/HttpHeader.tsx +42 -0
- package/src/shared/HttpStatusCode.ts +27 -0
- package/src/shared/clientOnly.ts +44 -0
- package/src/shared/dev-overlay/CodeView.tsx +95 -0
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +316 -0
- package/src/shared/dev-overlay/createStackFrame.ts +77 -0
- package/src/shared/dev-overlay/download.ts +6 -0
- package/src/shared/dev-overlay/env.d.ts +4 -0
- package/src/shared/dev-overlay/get-source-map.ts +35 -0
- package/src/shared/dev-overlay/icons.tsx +288 -0
- package/src/shared/dev-overlay/index.tsx +63 -0
- package/src/shared/dev-overlay/styles.css +292 -0
- package/src/shared/lazy.ts +51 -0
- package/src/shared/serverFunction.ts +10 -0
- package/src/virtual.d.ts +27 -0
- package/tsconfig.json +23 -0
- package/vitest.config.ts +9 -0
- package/config/fs-router.js +0 -142
- package/config/index.d.ts +0 -40
- package/config/index.js +0 -304
- package/config/server-components.js +0 -106
- package/dist/client/islands.d.ts +0 -7
- package/dist/client/islands.jsx +0 -10
- package/dist/middleware/index.jsx +0 -35
- package/dist/router/index.d.ts +0 -1
- package/dist/router/index.jsx +0 -2
- package/dist/router/lazyRoute.d.ts +0 -6
- package/dist/router/lazyRoute.js +0 -53
- package/dist/runtime/server-handler.d.ts +0 -2
- package/dist/runtime/server-runtime.d.ts +0 -3
- package/dist/server/islands/index.d.ts +0 -19
- package/dist/server/islands/index.jsx +0 -62
- package/dist/server/islands/utils.d.ts +0 -1
- package/dist/server/islands/utils.jsx +0 -85
- package/dist/server/pageEvent.d.ts +0 -2
- package/dist/server/pageEvent.js +0 -56
- package/dist/server/renderAsset.d.ts +0 -2
- package/env.d.ts +0 -26
- /package/dist/{router/FileRoutes.d.ts → router.d.ts} +0 -0
- /package/dist/shared/{clientOnly.jsx → clientOnly.js} +0 -0
- /package/dist/shared/{serverFunction.jsx → serverFunction.js} +0 -0
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import { getServerFnById } from "solidstart:server-fn-manifest";
|
|
2
2
|
import { parseSetCookie } from "cookie-es";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
|
|
3
|
+
import { parseCookies } from "h3";
|
|
4
|
+
import { crossSerializeStream, fromJSON, getCrossReferenceHeader, } from "seroval";
|
|
5
|
+
import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin, } from "seroval-plugins/web";
|
|
6
6
|
import { sharedConfig } from "solid-js";
|
|
7
7
|
import { renderToString } from "solid-js/web";
|
|
8
8
|
import { provideRequestEvent } from "solid-js/web/storage";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import { getExpectedRedirectStatus } from "../server/handler";
|
|
13
|
-
import { createPageEvent } from "../server/pageEvent";
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
import serverFnManifest from "solidstart:server-fn-manifest";
|
|
9
|
+
import { getFetchEvent, mergeResponseHeaders } from "./fetchEvent.js";
|
|
10
|
+
import { createPageEvent } from "./handler.js";
|
|
11
|
+
import { getExpectedRedirectStatus } from "./util.js";
|
|
16
12
|
function createChunk(data) {
|
|
17
13
|
const encodeData = new TextEncoder().encode(data);
|
|
18
14
|
const bytes = encodeData.length;
|
|
@@ -39,7 +35,7 @@ function serializeToStream(id, value) {
|
|
|
39
35
|
RequestPlugin,
|
|
40
36
|
ResponsePlugin,
|
|
41
37
|
URLSearchParamsPlugin,
|
|
42
|
-
URLPlugin
|
|
38
|
+
URLPlugin,
|
|
43
39
|
],
|
|
44
40
|
onSerialize(data, initial) {
|
|
45
41
|
controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
|
|
@@ -49,52 +45,32 @@ function serializeToStream(id, value) {
|
|
|
49
45
|
},
|
|
50
46
|
onError(error) {
|
|
51
47
|
controller.error(error);
|
|
52
|
-
}
|
|
48
|
+
},
|
|
53
49
|
});
|
|
54
|
-
}
|
|
50
|
+
},
|
|
55
51
|
});
|
|
56
52
|
}
|
|
57
|
-
async function handleServerFunction(h3Event) {
|
|
53
|
+
export async function handleServerFunction(h3Event) {
|
|
58
54
|
const event = getFetchEvent(h3Event);
|
|
59
55
|
const request = event.request;
|
|
60
56
|
const serverReference = request.headers.get("X-Server-Id");
|
|
61
57
|
const instance = request.headers.get("X-Server-Instance");
|
|
62
58
|
const singleFlight = request.headers.has("X-Single-Flight");
|
|
63
59
|
const url = new URL(request.url);
|
|
64
|
-
let functionId
|
|
60
|
+
let functionId;
|
|
65
61
|
if (serverReference) {
|
|
66
|
-
invariant(typeof serverReference === "string", "Invalid server function");
|
|
67
|
-
[functionId
|
|
62
|
+
// invariant(typeof serverReference === "string", "Invalid server function");
|
|
63
|
+
[functionId] = serverReference.split("#");
|
|
68
64
|
}
|
|
69
65
|
else {
|
|
70
66
|
functionId = url.searchParams.get("id");
|
|
71
|
-
|
|
72
|
-
if (!functionId || !name) {
|
|
67
|
+
if (!functionId) {
|
|
73
68
|
return process.env.NODE_ENV === "development"
|
|
74
69
|
? new Response("Server function not found", { status: 404 })
|
|
75
70
|
: new Response(null, { status: 404 });
|
|
76
71
|
}
|
|
77
72
|
}
|
|
78
|
-
const
|
|
79
|
-
let fnModule;
|
|
80
|
-
if (!serverFnInfo) {
|
|
81
|
-
return process.env.NODE_ENV === "development"
|
|
82
|
-
? new Response("Server function not found", { status: 404 })
|
|
83
|
-
: new Response(null, { status: 404 });
|
|
84
|
-
}
|
|
85
|
-
if (process.env.NODE_ENV === "development") {
|
|
86
|
-
// In dev, we use Vinxi to get the "server" server-side router
|
|
87
|
-
// Then we use that router's devServer.ssrLoadModule to get the serverFn
|
|
88
|
-
// This code comes from:
|
|
89
|
-
// https://github.com/TanStack/router/blob/266f5cc863cd1a99809d1af2669e58b6b6db9a67/packages/start-server-functions-handler/src/index.tsx#L83-L87
|
|
90
|
-
fnModule = await globalThis.app
|
|
91
|
-
.getRouter("server-fns")
|
|
92
|
-
.internals.devServer.ssrLoadModule(serverFnInfo.extractedFilename);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
fnModule = await serverFnInfo.importer();
|
|
96
|
-
}
|
|
97
|
-
const serverFunction = fnModule[serverFnInfo.functionName];
|
|
73
|
+
const serverFunction = await getServerFnById(functionId);
|
|
98
74
|
let parsed = [];
|
|
99
75
|
// grab bound arguments from url when no JS
|
|
100
76
|
if (!instance || h3Event.method === "GET") {
|
|
@@ -113,41 +89,22 @@ async function handleServerFunction(h3Event) {
|
|
|
113
89
|
RequestPlugin,
|
|
114
90
|
ResponsePlugin,
|
|
115
91
|
URLSearchParamsPlugin,
|
|
116
|
-
URLPlugin
|
|
117
|
-
]
|
|
92
|
+
URLPlugin,
|
|
93
|
+
],
|
|
118
94
|
})
|
|
119
|
-
: json).forEach((arg) =>
|
|
95
|
+
: json).forEach((arg) => {
|
|
96
|
+
parsed.push(arg);
|
|
97
|
+
});
|
|
120
98
|
}
|
|
121
99
|
}
|
|
122
100
|
if (h3Event.method === "POST") {
|
|
123
101
|
const contentType = request.headers.get("content-type");
|
|
124
|
-
const h3Request = h3Event.node.req;
|
|
125
|
-
// This should never be the case in "proper" Nitro presets since node.req has to be IncomingMessage,
|
|
126
|
-
// But the new azure-functions preset for some reason uses a ReadableStream in node.req (#1521)
|
|
127
|
-
const isReadableStream = h3Request instanceof ReadableStream;
|
|
128
|
-
const hasReadableStream = h3Request.body instanceof ReadableStream;
|
|
129
|
-
const isH3EventBodyStreamLocked = (isReadableStream && h3Request.locked) ||
|
|
130
|
-
(hasReadableStream && h3Request.body.locked);
|
|
131
|
-
const requestBody = isReadableStream ? h3Request : h3Request.body;
|
|
132
102
|
if (contentType?.startsWith("multipart/form-data") ||
|
|
133
103
|
contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
134
|
-
|
|
135
|
-
// (issue only in edge runtimes and netlify preset)
|
|
136
|
-
parsed.push(await (isH3EventBodyStreamLocked
|
|
137
|
-
? request
|
|
138
|
-
: new Request(request, { ...request, body: requestBody })).formData());
|
|
139
|
-
// what should work when #1721 is fixed
|
|
140
|
-
// parsed.push(await request.formData);
|
|
104
|
+
parsed.push(await event.request.formData());
|
|
141
105
|
}
|
|
142
106
|
else if (contentType?.startsWith("application/json")) {
|
|
143
|
-
|
|
144
|
-
// (issue only in edge runtimes and netlify preset)
|
|
145
|
-
const tmpReq = isH3EventBodyStreamLocked
|
|
146
|
-
? request
|
|
147
|
-
: new Request(request, { ...request, body: requestBody });
|
|
148
|
-
// what should work when #1721 is fixed
|
|
149
|
-
// just use request.json() here
|
|
150
|
-
parsed = fromJSON(await tmpReq.json(), {
|
|
107
|
+
parsed = fromJSON(await event.request.json(), {
|
|
151
108
|
plugins: [
|
|
152
109
|
CustomEventPlugin,
|
|
153
110
|
DOMExceptionPlugin,
|
|
@@ -158,17 +115,17 @@ async function handleServerFunction(h3Event) {
|
|
|
158
115
|
RequestPlugin,
|
|
159
116
|
ResponsePlugin,
|
|
160
117
|
URLSearchParamsPlugin,
|
|
161
|
-
URLPlugin
|
|
162
|
-
]
|
|
118
|
+
URLPlugin,
|
|
119
|
+
],
|
|
163
120
|
});
|
|
164
121
|
}
|
|
165
122
|
}
|
|
166
123
|
try {
|
|
167
124
|
let result = await provideRequestEvent(event, async () => {
|
|
168
|
-
/* @ts-
|
|
125
|
+
/* @ts-expect-error */
|
|
169
126
|
sharedConfig.context = { event };
|
|
170
127
|
event.locals.serverFunctionMeta = {
|
|
171
|
-
id: functionId
|
|
128
|
+
id: functionId
|
|
172
129
|
};
|
|
173
130
|
return serverFunction(...parsed);
|
|
174
131
|
});
|
|
@@ -185,7 +142,7 @@ async function handleServerFunction(h3Event) {
|
|
|
185
142
|
mergeResponseHeaders(h3Event, result.headers);
|
|
186
143
|
// forward non-redirect statuses
|
|
187
144
|
if (result.status && (result.status < 300 || result.status >= 400))
|
|
188
|
-
|
|
145
|
+
h3Event.res.status = result.status;
|
|
189
146
|
if (result.customBody) {
|
|
190
147
|
result = await result.customBody();
|
|
191
148
|
}
|
|
@@ -196,7 +153,7 @@ async function handleServerFunction(h3Event) {
|
|
|
196
153
|
// handle no JS success case
|
|
197
154
|
if (!instance)
|
|
198
155
|
return handleNoJS(result, request, parsed);
|
|
199
|
-
|
|
156
|
+
h3Event.res.headers.set("content-type", "text/javascript");
|
|
200
157
|
return serializeToStream(instance, result);
|
|
201
158
|
}
|
|
202
159
|
catch (x) {
|
|
@@ -208,24 +165,25 @@ async function handleServerFunction(h3Event) {
|
|
|
208
165
|
if (x.headers)
|
|
209
166
|
mergeResponseHeaders(h3Event, x.headers);
|
|
210
167
|
// forward non-redirect statuses
|
|
211
|
-
if (x.status &&
|
|
212
|
-
|
|
168
|
+
if (x.status &&
|
|
169
|
+
(!instance || x.status < 300 || x.status >= 400))
|
|
170
|
+
h3Event.res.status = x.status;
|
|
213
171
|
if (x.customBody) {
|
|
214
172
|
x = x.customBody();
|
|
215
173
|
}
|
|
216
|
-
else if (x.body
|
|
174
|
+
else if (x.body === undefined)
|
|
217
175
|
x = null;
|
|
218
|
-
|
|
176
|
+
h3Event.res.headers.set("X-Error", "true");
|
|
219
177
|
}
|
|
220
178
|
else if (instance) {
|
|
221
179
|
const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
|
|
222
|
-
|
|
180
|
+
h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
|
|
223
181
|
}
|
|
224
182
|
else {
|
|
225
183
|
x = handleNoJS(x, request, parsed, true);
|
|
226
184
|
}
|
|
227
185
|
if (instance) {
|
|
228
|
-
|
|
186
|
+
h3Event.res.headers.set("content-type", "text/javascript");
|
|
229
187
|
return serializeToStream(instance, x);
|
|
230
188
|
}
|
|
231
189
|
return x;
|
|
@@ -239,24 +197,29 @@ function handleNoJS(result, request, parsed, thrown) {
|
|
|
239
197
|
if (result instanceof Response) {
|
|
240
198
|
headers = new Headers(result.headers);
|
|
241
199
|
if (result.headers.has("Location")) {
|
|
242
|
-
headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.
|
|
200
|
+
headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.BASE_URL).toString());
|
|
243
201
|
statusCode = getExpectedRedirectStatus(result);
|
|
244
202
|
}
|
|
245
203
|
}
|
|
246
204
|
else
|
|
247
|
-
headers = new Headers({
|
|
205
|
+
headers = new Headers({
|
|
206
|
+
Location: new URL(request.headers.get("referer")).toString(),
|
|
207
|
+
});
|
|
248
208
|
if (result) {
|
|
249
209
|
headers.append("Set-Cookie", `flash=${encodeURIComponent(JSON.stringify({
|
|
250
210
|
url: url.pathname + url.search,
|
|
251
211
|
result: isError ? result.message : result,
|
|
252
212
|
thrown: thrown,
|
|
253
213
|
error: isError,
|
|
254
|
-
input: [
|
|
214
|
+
input: [
|
|
215
|
+
...parsed.slice(0, -1),
|
|
216
|
+
[...parsed[parsed.length - 1].entries()],
|
|
217
|
+
],
|
|
255
218
|
}))}; Secure; HttpOnly;`);
|
|
256
219
|
}
|
|
257
220
|
return new Response(null, {
|
|
258
221
|
status: statusCode,
|
|
259
|
-
headers
|
|
222
|
+
headers,
|
|
260
223
|
});
|
|
261
224
|
}
|
|
262
225
|
let App;
|
|
@@ -264,16 +227,16 @@ function createSingleFlightHeaders(sourceEvent) {
|
|
|
264
227
|
// cookie handling logic is pretty simplistic so this might be imperfect
|
|
265
228
|
// unclear if h3 internals are available on all platforms but we need a way to
|
|
266
229
|
// update request headers on the underlying H3 event.
|
|
267
|
-
const headers =
|
|
230
|
+
const headers = sourceEvent.request.headers;
|
|
268
231
|
const cookies = parseCookies(sourceEvent.nativeEvent);
|
|
269
232
|
const SetCookies = sourceEvent.response.headers.getSetCookie();
|
|
270
233
|
headers.delete("cookie");
|
|
271
|
-
let useH3Internals = false;
|
|
272
|
-
if (sourceEvent.nativeEvent.node?.req) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
SetCookies.forEach(cookie => {
|
|
234
|
+
// let useH3Internals = false;
|
|
235
|
+
// if (sourceEvent.nativeEvent.node?.req) {
|
|
236
|
+
// useH3Internals = true;
|
|
237
|
+
// sourceEvent.nativeEvent.node.req.headers.cookie = "";
|
|
238
|
+
// }
|
|
239
|
+
SetCookies.forEach((cookie) => {
|
|
277
240
|
if (!cookie)
|
|
278
241
|
return;
|
|
279
242
|
const { maxAge, expires, name, value } = parseSetCookie(cookie);
|
|
@@ -289,7 +252,8 @@ function createSingleFlightHeaders(sourceEvent) {
|
|
|
289
252
|
});
|
|
290
253
|
Object.entries(cookies).forEach(([key, value]) => {
|
|
291
254
|
headers.append("cookie", `${key}=${value}`);
|
|
292
|
-
useH3Internals &&
|
|
255
|
+
// useH3Internals &&
|
|
256
|
+
// (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
|
|
293
257
|
});
|
|
294
258
|
return headers;
|
|
295
259
|
}
|
|
@@ -300,21 +264,23 @@ async function handleSingleFlight(sourceEvent, result) {
|
|
|
300
264
|
if (result.headers.has("X-Revalidate"))
|
|
301
265
|
revalidate = result.headers.get("X-Revalidate").split(",");
|
|
302
266
|
if (result.headers.has("Location"))
|
|
303
|
-
url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin +
|
|
267
|
+
url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin +
|
|
268
|
+
import.meta.env.BASE_URL).toString();
|
|
304
269
|
}
|
|
305
|
-
const event =
|
|
306
|
-
event.request = new Request(url, {
|
|
270
|
+
const event = { ...sourceEvent };
|
|
271
|
+
event.request = new Request(url, {
|
|
272
|
+
headers: createSingleFlightHeaders(sourceEvent),
|
|
273
|
+
});
|
|
307
274
|
return await provideRequestEvent(event, async () => {
|
|
308
275
|
await createPageEvent(event);
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
/* @ts-ignore */
|
|
276
|
+
App || (App = (await import("solid-start:app")).default);
|
|
277
|
+
/* @ts-expect-error */
|
|
312
278
|
event.router.dataOnly = revalidate || true;
|
|
313
|
-
/* @ts-
|
|
279
|
+
/* @ts-expect-error */
|
|
314
280
|
event.router.previousUrl = sourceEvent.request.headers.get("referer");
|
|
315
281
|
try {
|
|
316
282
|
renderToString(() => {
|
|
317
|
-
/* @ts-
|
|
283
|
+
/* @ts-expect-error */
|
|
318
284
|
sharedConfig.context.event = event;
|
|
319
285
|
App();
|
|
320
286
|
});
|
|
@@ -322,7 +288,7 @@ async function handleSingleFlight(sourceEvent, result) {
|
|
|
322
288
|
catch (e) {
|
|
323
289
|
console.log(e);
|
|
324
290
|
}
|
|
325
|
-
/* @ts-
|
|
291
|
+
/* @ts-expect-error */
|
|
326
292
|
const body = event.router.data;
|
|
327
293
|
if (!body)
|
|
328
294
|
return result;
|
|
@@ -347,4 +313,3 @@ async function handleSingleFlight(sourceEvent, result) {
|
|
|
347
313
|
return result;
|
|
348
314
|
});
|
|
349
315
|
}
|
|
350
|
-
export default eventHandler(handleServerFunction);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { deserialize, toJSONAsync } from "seroval";
|
|
2
2
|
import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
|
|
3
|
-
import { createIslandReference } from "../server/islands/index";
|
|
4
3
|
class SerovalChunkReader {
|
|
5
4
|
reader;
|
|
6
5
|
buffer;
|
|
@@ -44,9 +43,6 @@ class SerovalChunkReader {
|
|
|
44
43
|
// deserialize the data
|
|
45
44
|
const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
|
|
46
45
|
const bytes = Number.parseInt(head, 16); // ;0x00000000;
|
|
47
|
-
if (Number.isNaN(bytes)) {
|
|
48
|
-
throw new Error(`Malformed server function stream header: ${head}`);
|
|
49
|
-
}
|
|
50
46
|
// Check if the buffer has enough bytes to be parsed
|
|
51
47
|
while (bytes > this.buffer.length - 12) {
|
|
52
48
|
// If it's not enough, and the reader is done
|
|
@@ -160,18 +156,21 @@ async function fetchServerFunction(base, id, options, args) {
|
|
|
160
156
|
}
|
|
161
157
|
return result;
|
|
162
158
|
}
|
|
163
|
-
export function createServerReference(
|
|
164
|
-
|
|
159
|
+
export function createServerReference(id) {
|
|
160
|
+
let baseURL = import.meta.env.BASE_URL ?? "/";
|
|
161
|
+
if (!baseURL.endsWith("/"))
|
|
162
|
+
baseURL += "/";
|
|
163
|
+
const fn = (...args) => fetchServerFunction(`${baseURL}_server`, id, {}, args);
|
|
165
164
|
return new Proxy(fn, {
|
|
166
165
|
get(target, prop, receiver) {
|
|
167
166
|
if (prop === "url") {
|
|
168
|
-
return `${baseURL}
|
|
167
|
+
return `${baseURL}_server?id=${encodeURIComponent(id)}`;
|
|
169
168
|
}
|
|
170
169
|
if (prop === "GET") {
|
|
171
170
|
return receiver.withOptions({ method: "GET" });
|
|
172
171
|
}
|
|
173
172
|
if (prop === "withOptions") {
|
|
174
|
-
const url = `${baseURL}
|
|
173
|
+
const url = `${baseURL}_server?id=${encodeURIComponent(id)}`;
|
|
175
174
|
return (options) => {
|
|
176
175
|
const fn = async (...args) => {
|
|
177
176
|
const encodeArgs = options.method && options.method.toUpperCase() === "GET";
|
|
@@ -180,7 +179,7 @@ export function createServerReference(fn, id, name) {
|
|
|
180
179
|
(args.length
|
|
181
180
|
? `&args=${encodeURIComponent(JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))))}`
|
|
182
181
|
: "")
|
|
183
|
-
: `${baseURL}
|
|
182
|
+
: `${baseURL}_server`, id, options, encodeArgs ? [] : args);
|
|
184
183
|
};
|
|
185
184
|
fn.url = url;
|
|
186
185
|
return fn;
|
|
@@ -188,14 +187,8 @@ export function createServerReference(fn, id, name) {
|
|
|
188
187
|
}
|
|
189
188
|
return target[prop];
|
|
190
189
|
},
|
|
191
|
-
apply(target, thisArg, args) {
|
|
192
|
-
return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, {}, args);
|
|
193
|
-
}
|
|
194
190
|
});
|
|
195
191
|
}
|
|
196
|
-
export function createClientReference(Component, id
|
|
197
|
-
if (typeof Component === "function") {
|
|
198
|
-
return createIslandReference(Component, id, name);
|
|
199
|
-
}
|
|
192
|
+
export function createClientReference(Component, id) {
|
|
200
193
|
return Component;
|
|
201
194
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NoHydration, getRequestEvent, ssr } from "solid-js/web";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { getSsrManifest } from "../manifest/ssr-manifest.js";
|
|
3
|
+
import { TopErrorBoundary } from "../../shared/ErrorBoundary.jsx";
|
|
4
|
+
import { useAssets } from "../assets/index.js";
|
|
4
5
|
const docType = ssr("<!DOCTYPE html>");
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -10,16 +11,13 @@ export function StartServer(props) {
|
|
|
10
11
|
const context = getRequestEvent();
|
|
11
12
|
// @ts-ignore
|
|
12
13
|
const nonce = context.nonce;
|
|
14
|
+
useAssets(context.assets, nonce);
|
|
13
15
|
return (<NoHydration>
|
|
14
16
|
{docType}
|
|
15
17
|
<TopErrorBoundary>
|
|
16
|
-
<props.document
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</>) : (<>
|
|
20
|
-
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
|
|
21
|
-
<script type="module" src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
|
|
22
|
-
</>)}/>
|
|
18
|
+
<props.document scripts={<>
|
|
19
|
+
<script type="module" src={getSsrManifest("client").path(import.meta.env.START_CLIENT_ENTRY)}/>
|
|
20
|
+
</>}/>
|
|
23
21
|
</TopErrorBoundary>
|
|
24
22
|
</NoHydration>);
|
|
25
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { HandlerOptions, PageEvent } from "../types.ts";
|
|
2
3
|
/**
|
|
3
4
|
*
|
|
4
5
|
* Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
|
|
5
6
|
*/
|
|
6
|
-
export declare function createHandler(fn: (context: PageEvent) =>
|
|
7
|
-
export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
|
|
7
|
+
export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions)): import("h3").H3;
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import { createBaseHandler } from "../handler";
|
|
1
|
+
import { createBaseHandler } from "../handler.js";
|
|
2
|
+
import { getSsrManifest } from "../manifest/ssr-manifest.js";
|
|
2
3
|
/**
|
|
3
4
|
*
|
|
4
5
|
* Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
|
|
5
6
|
*/
|
|
6
|
-
export function createHandler(fn, options
|
|
7
|
-
return createBaseHandler(
|
|
7
|
+
export function createHandler(fn, options) {
|
|
8
|
+
return createBaseHandler(createPageEvent, fn, options);
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
const
|
|
10
|
+
async function createPageEvent(ctx) {
|
|
11
|
+
const manifest = getSsrManifest("ssr");
|
|
11
12
|
const pageEvent = Object.assign(ctx, {
|
|
12
|
-
manifest: await
|
|
13
|
-
assets:
|
|
13
|
+
manifest: "json" in manifest ? await manifest.json() : {},
|
|
14
|
+
assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
|
|
14
15
|
routes: [],
|
|
15
16
|
complete: false,
|
|
16
|
-
|
|
17
|
-
// mutation: false,
|
|
18
|
-
// $type: FETCH_EVENT,
|
|
19
|
-
$islands: new Set()
|
|
17
|
+
$islands: new Set(),
|
|
20
18
|
});
|
|
21
19
|
return pageEvent;
|
|
22
20
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
1
|
+
export { default as lazy } from "../../shared/lazy.ts";
|
|
2
|
+
export * from "../types.ts";
|
|
3
|
+
export { StartServer } from "./StartServer.tsx";
|
|
4
|
+
export { createHandler } from "./handler.ts";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// @refresh skip
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export {
|
|
2
|
+
export { default as lazy } from "../../shared/lazy.js";
|
|
3
|
+
export * from "../types.js";
|
|
4
|
+
export { StartServer } from "./StartServer.jsx";
|
|
5
|
+
export { createHandler } from "./handler.js";
|
package/dist/server/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { H3Event } from "h3";
|
|
1
2
|
import type { JSX } from "solid-js";
|
|
2
|
-
import { RequestEvent } from "solid-js/web";
|
|
3
|
-
import { HTTPEvent } from "vinxi/http";
|
|
3
|
+
import type { RequestEvent } from "solid-js/web";
|
|
4
4
|
export type DocumentComponentProps = {
|
|
5
|
-
assets
|
|
5
|
+
assets?: JSX.Element;
|
|
6
6
|
scripts: JSX.Element;
|
|
7
7
|
children?: JSX.Element;
|
|
8
8
|
};
|
|
@@ -50,23 +50,21 @@ export interface FetchEvent {
|
|
|
50
50
|
response: ResponseStub;
|
|
51
51
|
clientAddress?: string;
|
|
52
52
|
locals: App.RequestEventLocals;
|
|
53
|
-
nativeEvent:
|
|
53
|
+
nativeEvent: H3Event;
|
|
54
54
|
}
|
|
55
55
|
export interface PageEvent extends RequestEvent {
|
|
56
|
-
|
|
57
|
-
assets: any;
|
|
56
|
+
assets: any[];
|
|
58
57
|
routes: any[];
|
|
59
58
|
$islands: Set<string>;
|
|
60
59
|
complete: boolean;
|
|
60
|
+
nonce?: string;
|
|
61
61
|
}
|
|
62
62
|
export interface APIEvent extends FetchEvent {
|
|
63
63
|
params: {
|
|
64
64
|
[key: string]: string;
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
|
-
export
|
|
68
|
-
(event: APIEvent): Promise<any>;
|
|
69
|
-
}
|
|
67
|
+
export type APIHandler = (event: APIEvent) => Promise<any>;
|
|
70
68
|
export interface ServerFunctionMeta {
|
|
71
69
|
id: string;
|
|
72
70
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages
|
|
2
|
+
const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
3
|
+
export function getExpectedRedirectStatus(response) {
|
|
4
|
+
if (response.status && validRedirectStatuses.has(response.status)) {
|
|
5
|
+
return response.status;
|
|
6
|
+
}
|
|
7
|
+
return 302;
|
|
8
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @refresh skip
|
|
2
2
|
import { ErrorBoundary as DefaultErrorBoundary, catchError } from "solid-js";
|
|
3
3
|
import { isServer } from "solid-js/web";
|
|
4
|
-
import { HttpStatusCode } from "./HttpStatusCode";
|
|
5
|
-
import { DevOverlay } from "./dev-overlay";
|
|
4
|
+
import { HttpStatusCode } from "./HttpStatusCode.js";
|
|
5
|
+
import { DevOverlay } from "./dev-overlay/index.jsx";
|
|
6
6
|
export const ErrorBoundary = import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY
|
|
7
7
|
? (props) => <DevOverlay>{props.children}</DevOverlay>
|
|
8
8
|
: (props) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @refresh skip
|
|
2
2
|
import { onCleanup } from "solid-js";
|
|
3
3
|
import { getRequestEvent, isServer } from "solid-js/web";
|
|
4
|
+
import { appendHeader, setHeader } from "../http/index.js";
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
6
7
|
* Read more: https://docs.solidjs.com/solid-start/reference/server/http-header
|
|
@@ -9,10 +10,11 @@ export const HttpHeader = isServer
|
|
|
9
10
|
? (props) => {
|
|
10
11
|
const event = getRequestEvent();
|
|
11
12
|
if (props.append)
|
|
12
|
-
|
|
13
|
+
appendHeader(props.name, props.value);
|
|
13
14
|
else
|
|
14
|
-
|
|
15
|
+
setHeader(props.name, props.value);
|
|
15
16
|
onCleanup(() => {
|
|
17
|
+
// @ts-expect-error
|
|
16
18
|
if (event.nativeEvent.handled || event.complete)
|
|
17
19
|
return;
|
|
18
20
|
const value = event.response.headers.get(props.name);
|
|
@@ -10,7 +10,9 @@ export const HttpStatusCode = isServer
|
|
|
10
10
|
const event = getRequestEvent();
|
|
11
11
|
event.response.status = props.code;
|
|
12
12
|
event.response.statusText = props.text;
|
|
13
|
-
onCleanup(() =>
|
|
13
|
+
onCleanup(() =>
|
|
14
|
+
// !event.nativeEvent.handled &&
|
|
15
|
+
!event.complete && (event.response.status = 200));
|
|
14
16
|
return null;
|
|
15
17
|
}
|
|
16
18
|
: (_props) => null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { JSX } from
|
|
2
|
-
import
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import "./styles.css";
|
|
3
3
|
export declare function classNames(...classes: (string | boolean | undefined)[]): string;
|
|
4
4
|
interface DevOverlayDialogProps {
|
|
5
5
|
errors: any[];
|