@solidjs/start 1.0.9 → 1.0.11
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/config/fs-router.js +8 -1
- package/dist/middleware/index.d.ts +2 -2
- package/dist/router/routes.d.ts +1 -0
- package/dist/router/routes.js +2 -2
- package/dist/runtime/server-handler.js +51 -23
- package/dist/server/handler.js +1 -1
- package/dist/server/pageEvent.js +23 -14
- package/package.json +2 -2
package/config/fs-router.js
CHANGED
|
@@ -58,7 +58,7 @@ export class SolidStartClientFileRouter extends BaseFileSystemRouter {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
61
|
+
const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"];
|
|
62
62
|
function createHTTPHandlers(src, exports) {
|
|
63
63
|
const handlers = {};
|
|
64
64
|
for (const exp of exports) {
|
|
@@ -67,8 +67,15 @@ function createHTTPHandlers(src, exports) {
|
|
|
67
67
|
src: src,
|
|
68
68
|
pick: [exp.n]
|
|
69
69
|
};
|
|
70
|
+
if (exp.n === "GET" && !exports.find(exp => exp.n === "HEAD")) {
|
|
71
|
+
handlers.$HEAD = {
|
|
72
|
+
src: src,
|
|
73
|
+
pick: [exp.n]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
}
|
|
78
|
+
|
|
72
79
|
return handlers;
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -12,7 +12,7 @@ export declare function createMiddleware({ onRequest, onBeforeResponse }: {
|
|
|
12
12
|
onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
|
|
13
13
|
onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined;
|
|
14
14
|
}): {
|
|
15
|
-
onRequest?: import("h3")._RequestMiddleware
|
|
16
|
-
onBeforeResponse?: import("h3")._ResponseMiddleware
|
|
15
|
+
onRequest?: import("h3")._RequestMiddleware | import("h3")._RequestMiddleware[] | undefined;
|
|
16
|
+
onBeforeResponse?: import("h3")._ResponseMiddleware | import("h3")._ResponseMiddleware[] | undefined;
|
|
17
17
|
};
|
|
18
18
|
export {};
|
package/dist/router/routes.d.ts
CHANGED
package/dist/router/routes.js
CHANGED
|
@@ -22,7 +22,7 @@ function defineRoutes(fileRoutes) {
|
|
|
22
22
|
export function matchAPIRoute(path, method) {
|
|
23
23
|
const match = router.lookup(path);
|
|
24
24
|
if (match && match.route) {
|
|
25
|
-
const handler = match.route[`$${method}`];
|
|
25
|
+
const handler = method === "HEAD" ? match.route["$HEAD"] || match.route["$GET"] : match.route[`$${method}`];
|
|
26
26
|
if (handler === undefined)
|
|
27
27
|
return;
|
|
28
28
|
return {
|
|
@@ -32,7 +32,7 @@ export function matchAPIRoute(path, method) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
function containsHTTP(route) {
|
|
35
|
-
return route["$GET"] || route["$POST"] || route["$PUT"] || route["$PATCH"] || route["$DELETE"];
|
|
35
|
+
return route["$HEAD"] || route["$GET"] || route["$POST"] || route["$PUT"] || route["$PATCH"] || route["$DELETE"];
|
|
36
36
|
}
|
|
37
37
|
const router = createRouter({
|
|
38
38
|
routes: fileRoutes.reduce((memo, route) => {
|
|
@@ -5,7 +5,7 @@ import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, Hea
|
|
|
5
5
|
import { sharedConfig } from "solid-js";
|
|
6
6
|
import { renderToString } from "solid-js/web";
|
|
7
7
|
import { provideRequestEvent } from "solid-js/web/storage";
|
|
8
|
-
import { eventHandler, setHeader, setResponseStatus } from "vinxi/http";
|
|
8
|
+
import { eventHandler, parseCookies, setHeader, setResponseStatus } from "vinxi/http";
|
|
9
9
|
import invariant from "vinxi/lib/invariant";
|
|
10
10
|
import { cloneEvent, getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
|
|
11
11
|
import { getExpectedRedirectStatus } from "../server/handler";
|
|
@@ -100,12 +100,13 @@ async function handleServerFunction(h3Event) {
|
|
|
100
100
|
// This should never be the case in "proper" Nitro presets since node.req has to be IncomingMessage,
|
|
101
101
|
// But the new azure-functions preset for some reason uses a ReadableStream in node.req (#1521)
|
|
102
102
|
const isReadableStream = h3Request instanceof ReadableStream;
|
|
103
|
-
const
|
|
103
|
+
const hasReadableStream = h3Request.body instanceof ReadableStream;
|
|
104
|
+
const isH3EventBodyStreamLocked = (isReadableStream && h3Request.locked) || (hasReadableStream && h3Request.body.locked);
|
|
104
105
|
const requestBody = isReadableStream ? h3Request : h3Request.body;
|
|
105
106
|
if (contentType?.startsWith("multipart/form-data") ||
|
|
106
107
|
contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
107
108
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
108
|
-
// (issue only in edge runtimes)
|
|
109
|
+
// (issue only in edge runtimes and netlify preset)
|
|
109
110
|
parsed.push(await (isH3EventBodyStreamLocked
|
|
110
111
|
? request
|
|
111
112
|
: new Request(request, { ...request, body: requestBody })).formData());
|
|
@@ -114,7 +115,7 @@ async function handleServerFunction(h3Event) {
|
|
|
114
115
|
}
|
|
115
116
|
else if (contentType?.startsWith("application/json")) {
|
|
116
117
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
117
|
-
// (issue only in edge runtimes)
|
|
118
|
+
// (issue only in edge runtimes and netlify preset)
|
|
118
119
|
const tmpReq = isH3EventBodyStreamLocked
|
|
119
120
|
? request
|
|
120
121
|
: new Request(request, { ...request, body: requestBody });
|
|
@@ -207,31 +208,58 @@ async function handleServerFunction(h3Event) {
|
|
|
207
208
|
function handleNoJS(result, request, parsed, thrown) {
|
|
208
209
|
const url = new URL(request.url);
|
|
209
210
|
const isError = result instanceof Error;
|
|
210
|
-
let redirectUrl = new URL(request.headers.get("referer")).toString();
|
|
211
211
|
let statusCode = 302;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
let headers;
|
|
213
|
+
if (result instanceof Response) {
|
|
214
|
+
headers = new Headers(result.headers);
|
|
215
|
+
if (result.headers.has("Location")) {
|
|
216
|
+
headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.SERVER_BASE_URL).toString());
|
|
217
|
+
statusCode = getExpectedRedirectStatus(result);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
headers = new Headers({ Location: new URL(request.headers.get("referer")).toString() });
|
|
222
|
+
if (result) {
|
|
223
|
+
headers.append("Set-Cookie", `flash=${encodeURIComponent(JSON.stringify({
|
|
224
|
+
url: url.pathname + url.search,
|
|
225
|
+
result: isError ? result.message : result,
|
|
226
|
+
thrown: thrown,
|
|
227
|
+
error: isError,
|
|
228
|
+
input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
|
|
229
|
+
}))}; Secure; HttpOnly;`);
|
|
215
230
|
}
|
|
216
231
|
return new Response(null, {
|
|
217
232
|
status: statusCode,
|
|
218
|
-
headers
|
|
219
|
-
Location: redirectUrl,
|
|
220
|
-
...(result
|
|
221
|
-
? {
|
|
222
|
-
"Set-Cookie": `flash=${JSON.stringify({
|
|
223
|
-
url: url.pathname + encodeURIComponent(url.search),
|
|
224
|
-
result: isError ? result.message : result,
|
|
225
|
-
thrown: thrown,
|
|
226
|
-
error: isError,
|
|
227
|
-
input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
|
|
228
|
-
})}; Secure; HttpOnly;`
|
|
229
|
-
}
|
|
230
|
-
: {})
|
|
231
|
-
}
|
|
233
|
+
headers
|
|
232
234
|
});
|
|
233
235
|
}
|
|
234
236
|
let App;
|
|
237
|
+
function createSingleFlightHeaders(sourceEvent) {
|
|
238
|
+
// cookie handling logic is pretty simplistic so this might be imperfect
|
|
239
|
+
// unclear if h3 internals are available on all platforms but we need a way to
|
|
240
|
+
// update request headers on the underlying H3 event.
|
|
241
|
+
const headers = new Headers(sourceEvent.request.headers);
|
|
242
|
+
const cookies = parseCookies(sourceEvent.nativeEvent);
|
|
243
|
+
const SetCookies = sourceEvent.response.headers.getSetCookie();
|
|
244
|
+
headers.delete("cookie");
|
|
245
|
+
let useH3Internals = false;
|
|
246
|
+
if (sourceEvent.nativeEvent.node?.req) {
|
|
247
|
+
useH3Internals = true;
|
|
248
|
+
sourceEvent.nativeEvent.node.req.headers.cookie = "";
|
|
249
|
+
}
|
|
250
|
+
SetCookies.forEach((cookie) => {
|
|
251
|
+
if (!cookie)
|
|
252
|
+
return;
|
|
253
|
+
const keyValue = cookie.split(";")[0];
|
|
254
|
+
const [key, value] = keyValue.split("=");
|
|
255
|
+
key && value && (cookies[key] = value);
|
|
256
|
+
});
|
|
257
|
+
Object.entries(cookies).forEach(([key, value]) => {
|
|
258
|
+
headers.append("cookie", `${key}=${value}`);
|
|
259
|
+
useH3Internals && (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
|
|
260
|
+
});
|
|
261
|
+
return headers;
|
|
262
|
+
}
|
|
235
263
|
async function handleSingleFlight(sourceEvent, result) {
|
|
236
264
|
let revalidate;
|
|
237
265
|
let url = new URL(sourceEvent.request.headers.get("referer")).toString();
|
|
@@ -242,7 +270,7 @@ async function handleSingleFlight(sourceEvent, result) {
|
|
|
242
270
|
url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin + import.meta.env.SERVER_BASE_URL).toString();
|
|
243
271
|
}
|
|
244
272
|
const event = cloneEvent(sourceEvent);
|
|
245
|
-
event.request = new Request(url);
|
|
273
|
+
event.request = new Request(url, { headers: createSingleFlightHeaders(sourceEvent) });
|
|
246
274
|
return await provideRequestEvent(event, async () => {
|
|
247
275
|
await createPageEvent(event);
|
|
248
276
|
/* @ts-ignore */
|
package/dist/server/handler.js
CHANGED
|
@@ -26,7 +26,7 @@ export function createBaseHandler(fn, createPageEvent, options = {}) {
|
|
|
26
26
|
const match = matchAPIRoute(new URL(event.request.url).pathname, event.request.method);
|
|
27
27
|
if (match) {
|
|
28
28
|
const mod = await match.handler.import();
|
|
29
|
-
const fn = mod[event.request.method];
|
|
29
|
+
const fn = event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method];
|
|
30
30
|
event.params = match.params || {};
|
|
31
31
|
// @ts-ignore
|
|
32
32
|
sharedConfig.context = { event };
|
package/dist/server/pageEvent.js
CHANGED
|
@@ -4,19 +4,26 @@ function initFromFlash(ctx) {
|
|
|
4
4
|
const flash = getCookie(ctx.nativeEvent, "flash");
|
|
5
5
|
if (!flash)
|
|
6
6
|
return;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
try {
|
|
8
|
+
let param = JSON.parse(flash);
|
|
9
|
+
if (!param || !param.result)
|
|
10
|
+
return;
|
|
11
|
+
const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
|
|
12
|
+
const result = param.error ? new Error(param.result) : param.result;
|
|
13
|
+
return {
|
|
14
|
+
input,
|
|
15
|
+
url: param.url,
|
|
16
|
+
pending: false,
|
|
17
|
+
result: param.thrown ? undefined : result,
|
|
18
|
+
error: param.thrown ? result : undefined
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.error(e);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
26
|
+
}
|
|
20
27
|
}
|
|
21
28
|
export async function createPageEvent(ctx) {
|
|
22
29
|
const clientManifest = import.meta.env.MANIFEST["client"];
|
|
@@ -28,7 +35,9 @@ export async function createPageEvent(ctx) {
|
|
|
28
35
|
manifest: await clientManifest.json(),
|
|
29
36
|
assets: [
|
|
30
37
|
...(await clientManifest.inputs[clientManifest.handler].assets()),
|
|
31
|
-
...(import.meta.env.DEV
|
|
38
|
+
...(import.meta.env.DEV
|
|
39
|
+
? await clientManifest.inputs[import.meta.env.START_APP].assets()
|
|
40
|
+
: []),
|
|
32
41
|
...(import.meta.env.START_ISLANDS
|
|
33
42
|
? (await serverManifest.inputs[serverManifest.handler].assets()).filter(s => s.attrs.rel !== "modulepreload")
|
|
34
43
|
: [])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/start",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"source-map-js": "^1.0.2",
|
|
74
74
|
"terracotta": "^1.0.4",
|
|
75
75
|
"tinyglobby": "^0.2.2",
|
|
76
|
-
"vite-plugin-solid": "^2.
|
|
76
|
+
"vite-plugin-solid": "^2.11.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
79
|
"typecheck": "tsc --noEmit",
|