@solidjs/start 1.1.7 → 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.d.ts +1 -0
- package/dist/server/fetchEvent.spec.js +65 -0
- package/dist/server/handler.d.ts +6 -12
- package/dist/server/handler.js +180 -95
- 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 +6 -10
- package/dist/{router → server}/routes.js +35 -27
- 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} +76 -103
- 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 +47 -65
- 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 -39
- package/config/index.js +0 -303
- 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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as h3 from "h3";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { createFetchEvent, getFetchEvent, mergeResponseHeaders, } from "./fetchEvent.js";
|
|
4
|
+
vi.mock(import("h3"), async (mod) => {
|
|
5
|
+
return {
|
|
6
|
+
...(await mod()),
|
|
7
|
+
getRequestIP: vi.fn(),
|
|
8
|
+
};
|
|
9
|
+
});
|
|
10
|
+
const mockedH3 = vi.mocked(h3);
|
|
11
|
+
const createMockH3Event = () => {
|
|
12
|
+
const event = new h3.H3Event(new Request("http://localhost/test"));
|
|
13
|
+
event.res.status = 200;
|
|
14
|
+
event.res.statusText = "OK";
|
|
15
|
+
return event;
|
|
16
|
+
};
|
|
17
|
+
describe("fetchEvent", () => {
|
|
18
|
+
let mockH3Event;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
mockH3Event = createMockH3Event();
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
mockedH3.getRequestIP.mockReturnValue("127.0.0.1");
|
|
23
|
+
});
|
|
24
|
+
describe("createFetchEvent", () => {
|
|
25
|
+
it("should create a FetchEvent from H3Event", () => {
|
|
26
|
+
const fetchEvent = createFetchEvent(mockH3Event);
|
|
27
|
+
expect(fetchEvent).toEqual({
|
|
28
|
+
request: mockH3Event.req,
|
|
29
|
+
response: expect.any(Object),
|
|
30
|
+
clientAddress: "127.0.0.1",
|
|
31
|
+
locals: {},
|
|
32
|
+
nativeEvent: mockH3Event,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it("should create response stub with correct properties", () => {
|
|
36
|
+
const fetchEvent = createFetchEvent(mockH3Event);
|
|
37
|
+
expect(fetchEvent.response).toHaveProperty("status");
|
|
38
|
+
expect(fetchEvent.response).toHaveProperty("statusText");
|
|
39
|
+
expect(fetchEvent.response).toHaveProperty("headers");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe("getFetchEvent", () => {
|
|
43
|
+
it("should create and cache FetchEvent on first call", () => {
|
|
44
|
+
const fetchEvent = getFetchEvent(mockH3Event);
|
|
45
|
+
expect(mockH3Event.context.solidFetchEvent).toBe(fetchEvent);
|
|
46
|
+
expect(fetchEvent.nativeEvent).toBe(mockH3Event);
|
|
47
|
+
});
|
|
48
|
+
it("should return cached FetchEvent on subsequent calls", () => {
|
|
49
|
+
const firstCall = getFetchEvent(mockH3Event);
|
|
50
|
+
const secondCall = getFetchEvent(mockH3Event);
|
|
51
|
+
expect(firstCall).toBe(secondCall);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe("mergeResponseHeaders", () => {
|
|
55
|
+
it("should merge headers from Headers object to H3Event", () => {
|
|
56
|
+
const headers = new Headers({
|
|
57
|
+
"content-type": "application/json",
|
|
58
|
+
"x-custom": "value",
|
|
59
|
+
});
|
|
60
|
+
mergeResponseHeaders(mockH3Event, headers);
|
|
61
|
+
expect(headers.get("content-type")).toBe("application/json");
|
|
62
|
+
expect(headers.get("x-custom")).toBe("value");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
package/dist/server/handler.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function createBaseHandler(fn: (context: PageEvent) => unknown, createPageEvent: (event: FetchEvent) => Promise<PageEvent>, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
|
|
11
|
-
*/
|
|
12
|
-
export declare function createHandler(fn: (context: PageEvent) => unknown, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
|
|
1
|
+
import { H3 } from "h3";
|
|
2
|
+
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>)): H3;
|
|
5
|
+
export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>)): H3;
|
|
6
|
+
export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
|
package/dist/server/handler.js
CHANGED
|
@@ -1,106 +1,182 @@
|
|
|
1
|
+
import middleware from "solid-start:middleware";
|
|
2
|
+
import { defineHandler, getCookie, H3, redirect, setCookie } from "h3";
|
|
3
|
+
import { join } from "pathe";
|
|
1
4
|
import { sharedConfig } from "solid-js";
|
|
2
|
-
import { renderToStream, renderToString } from "solid-js/web";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (res
|
|
38
|
-
return res;
|
|
39
|
-
|
|
40
|
-
throw new Error(`API handler for ${event.request.method} "${event.request.url}" did not return a response.`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// render
|
|
44
|
-
const context = await createPageEvent(event);
|
|
45
|
-
const resolvedOptions = typeof options == "function" ? await options(context) : { ...options };
|
|
46
|
-
const mode = resolvedOptions.mode || "stream";
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
if (resolvedOptions.nonce)
|
|
49
|
-
context.nonce = resolvedOptions.nonce;
|
|
50
|
-
if (mode === "sync" || !import.meta.env.START_SSR) {
|
|
51
|
-
const html = renderToString(() => {
|
|
52
|
-
sharedConfig.context.event = context;
|
|
53
|
-
return fn(context);
|
|
54
|
-
}, resolvedOptions);
|
|
55
|
-
context.complete = true;
|
|
56
|
-
if (context.response && context.response.headers.get("Location")) {
|
|
57
|
-
const status = getExpectedRedirectStatus(context.response);
|
|
58
|
-
return sendRedirect(e, context.response.headers.get("Location"), status);
|
|
59
|
-
}
|
|
60
|
-
return html;
|
|
5
|
+
import { getRequestEvent, renderToStream, renderToString } from "solid-js/web";
|
|
6
|
+
import { createRoutes } from "../router.jsx";
|
|
7
|
+
import { decorateHandler, decorateMiddleware } from "./fetchEvent.js";
|
|
8
|
+
import { getSsrManifest } from "./manifest/ssr-manifest.js";
|
|
9
|
+
import { matchAPIRoute } from "./routes.js";
|
|
10
|
+
import { handleServerFunction } from "./server-functions-handler.js";
|
|
11
|
+
import { getExpectedRedirectStatus } from "./util.js";
|
|
12
|
+
const SERVER_FN_BASE = "/_server";
|
|
13
|
+
export function createBaseHandler(createPageEvent, fn, options = {}) {
|
|
14
|
+
const handler = defineHandler({
|
|
15
|
+
middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined,
|
|
16
|
+
handler: decorateHandler(async (e) => {
|
|
17
|
+
const event = getRequestEvent();
|
|
18
|
+
const url = new URL(event.request.url);
|
|
19
|
+
const pathname = url.pathname;
|
|
20
|
+
const serverFunctionTest = join(import.meta.env.BASE_URL, SERVER_FN_BASE);
|
|
21
|
+
if (pathname.startsWith(serverFunctionTest)) {
|
|
22
|
+
const serverFnResponse = await handleServerFunction(e);
|
|
23
|
+
if (serverFnResponse instanceof Response)
|
|
24
|
+
return produceResponseWithEventHeaders(serverFnResponse);
|
|
25
|
+
return new Response(serverFnResponse, {
|
|
26
|
+
headers: e.res.headers,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const match = matchAPIRoute(pathname, event.request.method);
|
|
30
|
+
if (match) {
|
|
31
|
+
const mod = await match.handler.import();
|
|
32
|
+
const fn = event.request.method === "HEAD"
|
|
33
|
+
? mod["HEAD"] || mod["GET"]
|
|
34
|
+
: mod[event.request.method];
|
|
35
|
+
event.params = match.params || {};
|
|
36
|
+
// @ts-expect-error
|
|
37
|
+
sharedConfig.context = { event };
|
|
38
|
+
const res = await fn(event);
|
|
39
|
+
if (res !== undefined) {
|
|
40
|
+
if (res instanceof Response)
|
|
41
|
+
return produceResponseWithEventHeaders(res);
|
|
42
|
+
return res;
|
|
61
43
|
}
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
resolvedOptions.onCompleteAll = options => {
|
|
65
|
-
handleStreamCompleteRedirect(context)(options);
|
|
66
|
-
og(options);
|
|
67
|
-
};
|
|
44
|
+
if (event.request.method !== "GET") {
|
|
45
|
+
throw new Error(`API handler for ${event.request.method} "${event.request.url}" did not return a response.`);
|
|
68
46
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
resolvedOptions.onCompleteShell = handleShellCompleteRedirect(context, e);
|
|
80
|
-
const stream = renderToStream(() => {
|
|
47
|
+
if (!match.isPage)
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const context = await createPageEvent(event);
|
|
51
|
+
const resolvedOptions = typeof options === "function" ? await options(context) : { ...options };
|
|
52
|
+
const mode = resolvedOptions.mode || "stream";
|
|
53
|
+
if (resolvedOptions.nonce)
|
|
54
|
+
context.nonce = resolvedOptions.nonce;
|
|
55
|
+
if (mode === "sync" || !import.meta.env.START_SSR) {
|
|
56
|
+
const html = renderToString(() => {
|
|
81
57
|
sharedConfig.context.event = context;
|
|
82
58
|
return fn(context);
|
|
83
|
-
}
|
|
59
|
+
});
|
|
60
|
+
context.complete = true;
|
|
84
61
|
if (context.response && context.response.headers.get("Location")) {
|
|
85
62
|
const status = getExpectedRedirectStatus(context.response);
|
|
86
|
-
return
|
|
63
|
+
return redirect(context.response.headers.get("Location"), status);
|
|
87
64
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
65
|
+
return html;
|
|
66
|
+
}
|
|
67
|
+
if (resolvedOptions.onCompleteAll) {
|
|
68
|
+
const og = resolvedOptions.onCompleteAll;
|
|
69
|
+
resolvedOptions.onCompleteAll = options => {
|
|
70
|
+
handleStreamCompleteRedirect(context)(options);
|
|
71
|
+
og(options);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
resolvedOptions.onCompleteAll = handleStreamCompleteRedirect(context);
|
|
76
|
+
if (resolvedOptions.onCompleteShell) {
|
|
77
|
+
const og = resolvedOptions.onCompleteShell;
|
|
78
|
+
resolvedOptions.onCompleteShell = options => {
|
|
79
|
+
handleShellCompleteRedirect(context, e)();
|
|
80
|
+
og(options);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
resolvedOptions.onCompleteShell = handleShellCompleteRedirect(context, e);
|
|
85
|
+
const _stream = renderToStream(() => {
|
|
86
|
+
sharedConfig.context.event = context;
|
|
87
|
+
return fn(context);
|
|
88
|
+
}, resolvedOptions);
|
|
89
|
+
const stream = _stream; // stream has a hidden 'then' method
|
|
90
|
+
if (context.response && context.response.headers.get("Location")) {
|
|
91
|
+
const status = getExpectedRedirectStatus(context.response);
|
|
92
|
+
return redirect(context.response.headers.get("Location"), status);
|
|
93
|
+
}
|
|
94
|
+
if (mode === "async")
|
|
95
|
+
return await stream;
|
|
96
|
+
delete stream.then;
|
|
97
|
+
// using TransformStream in dev can cause solid-start-dev-server to crash
|
|
98
|
+
// when stream is cancelled
|
|
99
|
+
if (globalThis.USING_SOLID_START_DEV_SERVER)
|
|
100
|
+
return stream;
|
|
101
|
+
// returning stream directly breaks cloudflare workers
|
|
102
|
+
const { writable, readable } = new TransformStream();
|
|
103
|
+
stream.pipeTo(writable);
|
|
104
|
+
return readable;
|
|
105
|
+
}),
|
|
96
106
|
});
|
|
107
|
+
const app = new H3();
|
|
108
|
+
app.use(handler);
|
|
109
|
+
return app;
|
|
110
|
+
}
|
|
111
|
+
export function createHandler(fn, options = {}) {
|
|
112
|
+
return createBaseHandler(createPageEvent, fn, options);
|
|
113
|
+
}
|
|
114
|
+
export async function createPageEvent(ctx) {
|
|
115
|
+
ctx.response.headers.set("Content-Type", "text/html");
|
|
116
|
+
// const prevPath = ctx.request.headers.get("x-solid-referrer");
|
|
117
|
+
// const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
|
|
118
|
+
const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr" : "client");
|
|
119
|
+
// Handle Vite build.cssCodeSplit
|
|
120
|
+
// When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
|
|
121
|
+
const mergedCSS = import.meta.env.PROD ? await manifest.getAssets('style.css') : [];
|
|
122
|
+
const assets = [
|
|
123
|
+
...mergedCSS,
|
|
124
|
+
...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)),
|
|
125
|
+
...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)),
|
|
126
|
+
// ...(import.meta.env.START_ISLANDS
|
|
127
|
+
// ? (await serverManifest.inputs[serverManifest.handler]!.assets()).filter(
|
|
128
|
+
// s => (s as any).attrs.rel !== "modulepreload"
|
|
129
|
+
// )
|
|
130
|
+
// : [])
|
|
131
|
+
];
|
|
132
|
+
const pageEvent = Object.assign(ctx, {
|
|
133
|
+
assets,
|
|
134
|
+
router: {
|
|
135
|
+
submission: initFromFlash(ctx),
|
|
136
|
+
},
|
|
137
|
+
routes: createRoutes(),
|
|
138
|
+
// prevUrl: prevPath || "",
|
|
139
|
+
// mutation: mutation,
|
|
140
|
+
// $type: FETCH_EVENT,
|
|
141
|
+
complete: false,
|
|
142
|
+
$islands: new Set(),
|
|
143
|
+
});
|
|
144
|
+
return pageEvent;
|
|
145
|
+
}
|
|
146
|
+
function initFromFlash(ctx) {
|
|
147
|
+
const flash = getCookie(ctx.nativeEvent, "flash");
|
|
148
|
+
if (!flash)
|
|
149
|
+
return;
|
|
150
|
+
try {
|
|
151
|
+
const param = JSON.parse(flash);
|
|
152
|
+
if (!param || !param.result)
|
|
153
|
+
return;
|
|
154
|
+
const input = [
|
|
155
|
+
...param.input.slice(0, -1),
|
|
156
|
+
new Map(param.input[param.input.length - 1]),
|
|
157
|
+
];
|
|
158
|
+
const result = param.error ? new Error(param.result) : param.result;
|
|
159
|
+
return {
|
|
160
|
+
input,
|
|
161
|
+
url: param.url,
|
|
162
|
+
pending: false,
|
|
163
|
+
result: param.thrown ? undefined : result,
|
|
164
|
+
error: param.thrown ? result : undefined,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
console.error(e);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
172
|
+
}
|
|
97
173
|
}
|
|
98
174
|
function handleShellCompleteRedirect(context, e) {
|
|
99
175
|
return () => {
|
|
100
176
|
if (context.response && context.response.headers.get("Location")) {
|
|
101
177
|
const status = getExpectedRedirectStatus(context.response);
|
|
102
|
-
|
|
103
|
-
|
|
178
|
+
e.res.status = status;
|
|
179
|
+
e.res.headers.set("Location", context.response.headers.get("Location"));
|
|
104
180
|
}
|
|
105
181
|
};
|
|
106
182
|
}
|
|
@@ -111,10 +187,19 @@ function handleStreamCompleteRedirect(context) {
|
|
|
111
187
|
to && write(`<script>window.location="${to}"</script>`);
|
|
112
188
|
};
|
|
113
189
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
190
|
+
function produceResponseWithEventHeaders(res) {
|
|
191
|
+
const event = getRequestEvent();
|
|
192
|
+
let ret = res;
|
|
193
|
+
// Response.redirect returns an immutable value, so we clone on any redirect just in case
|
|
194
|
+
if (300 <= res.status && res.status < 400) {
|
|
195
|
+
ret = new Response(res.body, {
|
|
196
|
+
status: res.status,
|
|
197
|
+
statusText: res.statusText,
|
|
198
|
+
headers: Object.fromEntries(res.headers.entries())
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
for (const [name, value] of event.response.headers) {
|
|
202
|
+
ret.headers.set(name, value);
|
|
203
|
+
}
|
|
204
|
+
return ret;
|
|
120
205
|
}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
|
|
1
|
+
export { default as lazy } from "../shared/lazy.ts";
|
|
2
|
+
export { getServerFunctionMeta } from "../shared/serverFunction.ts";
|
|
3
|
+
export { StartServer } from "./StartServer.tsx";
|
|
4
|
+
export { createHandler } from "./handler.ts";
|
|
5
|
+
/**
|
|
6
|
+
* Checks if user has set a redirect status in the response.
|
|
7
|
+
* If not, falls back to the 302 (temporary redirect)
|
|
8
|
+
*/
|
package/dist/server/index.jsx
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
export { StartServer } from "./StartServer";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
|
|
1
|
+
export { default as lazy } from "../shared/lazy.js";
|
|
2
|
+
export { getServerFunctionMeta } from "../shared/serverFunction.js";
|
|
3
|
+
export { StartServer } from "./StartServer.jsx";
|
|
4
|
+
export { createHandler } from "./handler.js";
|
|
5
|
+
/**
|
|
6
|
+
* Checks if user has set a redirect status in the response.
|
|
7
|
+
* If not, falls back to the 302 (temporary redirect)
|
|
8
|
+
*/
|
|
9
|
+
// export function getExpectedRedirectStatus(response: ResponseStub): number {
|
|
10
|
+
// if (response.status && validRedirectStatuses.has(response.status)) {
|
|
11
|
+
// return response.status;
|
|
12
|
+
// }
|
|
13
|
+
// return 302;
|
|
14
|
+
// }
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function getClientManifest(): {
|
|
2
|
+
import(id: string): Promise<any>;
|
|
3
|
+
getAssets(id: string): Promise<any[]>;
|
|
4
|
+
} | {
|
|
5
|
+
import(id: string): Promise<any>;
|
|
6
|
+
getAssets(id: string): Promise<any>;
|
|
7
|
+
json(): Promise<any>;
|
|
8
|
+
};
|
|
9
|
+
export { getClientManifest as getManifest };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { getClientDevManifest } from "./dev-client-manifest.js";
|
|
2
|
+
import { getClientProdManifest } from "./prod-client-manifest.js";
|
|
3
|
+
export function getClientManifest() {
|
|
4
|
+
return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
|
|
5
|
+
}
|
|
6
|
+
export { getClientManifest as getManifest };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { join } from "pathe";
|
|
10
|
+
export function getClientDevManifest() {
|
|
11
|
+
return {
|
|
12
|
+
import(id) {
|
|
13
|
+
return import(__rewriteRelativeImportExtension(/* @vite-ignore */ join("/", id), true));
|
|
14
|
+
},
|
|
15
|
+
async getAssets(id) {
|
|
16
|
+
const assetsPath = `/@manifest/client/${Date.now()}/assets?id=${id}`;
|
|
17
|
+
const assets = (await import(__rewriteRelativeImportExtension(/* @vite-ignore */ assetsPath, true))).default;
|
|
18
|
+
return await Promise.all(assets.map(async (v) => ({
|
|
19
|
+
...v,
|
|
20
|
+
children: await v.children()
|
|
21
|
+
})));
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { join, normalize } from "pathe";
|
|
10
|
+
export function getSsrDevManifest(environment) {
|
|
11
|
+
return {
|
|
12
|
+
path: (id) => normalize(join(import.meta.env.BASE_URL, id)),
|
|
13
|
+
async getAssets(id) {
|
|
14
|
+
const assetsPath = `/@manifest/${environment}/${Date.now()}/assets?id=${id}`;
|
|
15
|
+
const assets = (await import(__rewriteRelativeImportExtension(/* @vite-ignore */ assetsPath, true))).default;
|
|
16
|
+
return await Promise.all(assets.map(async (v) => ({
|
|
17
|
+
...v,
|
|
18
|
+
children: await v.children()
|
|
19
|
+
})));
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export { getSsrDevManifest as getSsrManifest };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
export function getClientProdManifest() {
|
|
10
|
+
return {
|
|
11
|
+
import(id) {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
return import(__rewriteRelativeImportExtension(/* @vite-ignore */ window.manifest[id].output, true));
|
|
14
|
+
},
|
|
15
|
+
async getAssets(id) {
|
|
16
|
+
if (id.startsWith("./"))
|
|
17
|
+
id = id.slice(2);
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
return window.manifest[id]?.assets ?? [];
|
|
20
|
+
},
|
|
21
|
+
async json() {
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
return window.manifest;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { clientViteManifest } from "solid-start:client-vite-manifest";
|
|
2
|
+
import { join } from "pathe";
|
|
3
|
+
// Only reads from client manifest atm, might need server support for islands
|
|
4
|
+
export function getSsrProdManifest() {
|
|
5
|
+
const viteManifest = clientViteManifest;
|
|
6
|
+
return {
|
|
7
|
+
path(id) {
|
|
8
|
+
if (id.startsWith("./"))
|
|
9
|
+
id = id.slice(2);
|
|
10
|
+
const viteManifestEntry = clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
|
|
11
|
+
if (!viteManifestEntry)
|
|
12
|
+
throw new Error(`No entry found in vite manifest for '${id}'`);
|
|
13
|
+
return join("/", viteManifestEntry.file);
|
|
14
|
+
},
|
|
15
|
+
async getAssets(id) {
|
|
16
|
+
if (id.startsWith("./"))
|
|
17
|
+
id = id.slice(2);
|
|
18
|
+
return createHtmlTagsForAssets(findAssetsInViteManifest(clientViteManifest, id));
|
|
19
|
+
},
|
|
20
|
+
async json() {
|
|
21
|
+
const json = {};
|
|
22
|
+
const entryKeys = Object.keys(viteManifest)
|
|
23
|
+
.filter((id) => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
|
|
24
|
+
.map((id) => id);
|
|
25
|
+
for (const entryKey of entryKeys) {
|
|
26
|
+
json[entryKey] = {
|
|
27
|
+
output: join("/", viteManifest[entryKey].file),
|
|
28
|
+
assets: await this.getAssets(entryKey),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return json;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createHtmlTagsForAssets(assets) {
|
|
36
|
+
return assets
|
|
37
|
+
.filter((asset) => asset.endsWith(".css") ||
|
|
38
|
+
asset.endsWith(".js") ||
|
|
39
|
+
asset.endsWith(".ts") ||
|
|
40
|
+
asset.endsWith(".mjs"))
|
|
41
|
+
.map((asset) => ({
|
|
42
|
+
tag: "link",
|
|
43
|
+
attrs: {
|
|
44
|
+
href: '/' + asset,
|
|
45
|
+
key: asset,
|
|
46
|
+
...(asset.endsWith(".css")
|
|
47
|
+
? { rel: "stylesheet" }
|
|
48
|
+
: { rel: "modulepreload" }),
|
|
49
|
+
},
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
const entryId = import.meta.env.START_CLIENT_ENTRY.slice(2);
|
|
53
|
+
let entryImports = undefined;
|
|
54
|
+
function findAssetsInViteManifest(manifest, id, assetMap = new Map(), stack = []) {
|
|
55
|
+
if (stack.includes(id)) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const cached = assetMap.get(id);
|
|
59
|
+
if (cached) {
|
|
60
|
+
return cached;
|
|
61
|
+
}
|
|
62
|
+
const chunk = manifest[id];
|
|
63
|
+
if (!chunk) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (!entryImports) {
|
|
67
|
+
entryImports = [
|
|
68
|
+
entryId,
|
|
69
|
+
...(manifest[entryId]?.imports ?? [])
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
// Only include entry imports, if we are specifically crawling the entry
|
|
73
|
+
// Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
|
|
74
|
+
const excludeEntryImports = id !== entryId;
|
|
75
|
+
const assets = chunk.css?.filter(Boolean) || [];
|
|
76
|
+
if (chunk.imports) {
|
|
77
|
+
stack.push(id);
|
|
78
|
+
for (let i = 0, l = chunk.imports.length; i < l; i++) {
|
|
79
|
+
const importId = chunk.imports[i];
|
|
80
|
+
if (!importId || (excludeEntryImports && entryImports.includes(importId)))
|
|
81
|
+
continue;
|
|
82
|
+
assets.push(...findAssetsInViteManifest(manifest, importId, assetMap, stack));
|
|
83
|
+
}
|
|
84
|
+
stack.pop();
|
|
85
|
+
}
|
|
86
|
+
assets.push(chunk.file);
|
|
87
|
+
const all = Array.from(new Set(assets));
|
|
88
|
+
assetMap.set(id, all);
|
|
89
|
+
return all;
|
|
90
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { getSsrDevManifest } from "./dev-ssr-manifest.ts";
|
|
2
|
+
import { getSsrProdManifest } from "./prod-ssr-manifest.ts";
|
|
3
|
+
export declare function getSsrManifest(target: "client" | "ssr"): ReturnType<typeof getSsrDevManifest> | ReturnType<typeof getSsrProdManifest>;
|
|
4
|
+
export { getSsrManifest as getManifest };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { getSsrDevManifest } from "./dev-ssr-manifest.js";
|
|
2
|
+
import { getSsrProdManifest } from "./prod-ssr-manifest.js";
|
|
3
|
+
export function getSsrManifest(target) {
|
|
4
|
+
return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest();
|
|
5
|
+
}
|
|
6
|
+
export { getSsrManifest as getManifest };
|