@solidjs/start 0.7.1 → 0.7.2
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/index.js +4 -4
- package/config/server-components.js +1 -1
- package/dist/client/StartClient.d.ts +3 -0
- package/{client/StartClient.tsx → dist/client/StartClient.jsx} +4 -9
- package/{client/index.tsx → dist/client/index.d.ts} +0 -1
- package/dist/client/index.jsx +4 -0
- package/dist/client/islands.d.ts +3 -0
- package/{client/islands.ts → dist/client/islands.jsx} +1 -1
- package/dist/client/mount.d.ts +3 -0
- package/dist/client/mount.js +85 -0
- package/dist/client/spa/index.d.ts +5 -0
- package/dist/client/spa/index.jsx +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.jsx +5 -0
- package/dist/middleware/index.d.ts +18 -0
- package/dist/middleware/index.js +40 -0
- package/dist/router/FileRoutes.d.ts +2 -0
- package/dist/router/FileRoutes.js +25 -0
- package/dist/router/index.jsx +2 -0
- package/dist/router/lazyRoute.d.ts +6 -0
- package/dist/router/lazyRoute.js +48 -0
- package/dist/router/routes.d.ts +25 -0
- package/dist/router/routes.js +51 -0
- package/dist/runtime/server-fns-runtime.d.ts +1 -0
- package/dist/runtime/server-fns-runtime.js +30 -0
- package/dist/runtime/server-handler.d.ts +2 -0
- package/dist/runtime/server-handler.js +242 -0
- package/dist/runtime/server-runtime.d.ts +3 -0
- package/dist/runtime/server-runtime.js +185 -0
- package/dist/server/StartServer.d.ts +5 -0
- package/dist/server/StartServer.jsx +78 -0
- package/dist/server/fetchEvent.d.ts +6 -0
- package/dist/server/fetchEvent.js +88 -0
- package/dist/server/handler.d.ts +3 -0
- package/dist/server/handler.js +98 -0
- package/dist/server/index.jsx +5 -0
- package/dist/server/islands/index.d.ts +19 -0
- package/dist/server/islands/index.jsx +62 -0
- package/dist/server/islands/utils.d.ts +1 -0
- package/dist/server/islands/utils.jsx +85 -0
- package/dist/server/pageEvent.d.ts +2 -0
- package/dist/server/pageEvent.js +43 -0
- package/dist/server/renderAsset.d.ts +2 -0
- package/dist/server/renderAsset.jsx +13 -0
- package/dist/server/serverFunction.d.ts +2 -0
- package/dist/server/serverFunction.jsx +4 -0
- package/dist/server/spa/StartServer.d.ts +5 -0
- package/dist/server/spa/StartServer.jsx +18 -0
- package/dist/server/spa/handler.d.ts +3 -0
- package/dist/server/spa/handler.js +17 -0
- package/{server/spa/index.tsx → dist/server/spa/index.d.ts} +0 -1
- package/dist/server/spa/index.jsx +4 -0
- package/dist/server/types.d.ts +79 -0
- package/dist/server/types.js +1 -0
- package/dist/shared/ErrorBoundary.d.ts +2 -0
- package/dist/shared/ErrorBoundary.jsx +16 -0
- package/dist/shared/GET.d.ts +1 -0
- package/dist/shared/GET.js +5 -0
- package/dist/shared/HttpHeader.d.ts +6 -0
- package/dist/shared/HttpHeader.jsx +32 -0
- package/dist/shared/HttpStatusCode.d.ts +5 -0
- package/dist/shared/HttpStatusCode.jsx +12 -0
- package/dist/shared/clientOnly.d.ts +6 -0
- package/dist/shared/clientOnly.jsx +19 -0
- package/dist/shared/dev-overlay/CodeView.d.ts +7 -0
- package/dist/shared/dev-overlay/CodeView.jsx +71 -0
- package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +9 -0
- package/dist/shared/dev-overlay/DevOverlayDialog.jsx +209 -0
- package/dist/shared/dev-overlay/createStackFrame.d.ts +9 -0
- package/dist/shared/dev-overlay/createStackFrame.js +56 -0
- package/dist/shared/dev-overlay/download.d.ts +1 -0
- package/dist/shared/dev-overlay/download.js +6 -0
- package/dist/shared/dev-overlay/get-source-map.d.ts +2 -0
- package/dist/shared/dev-overlay/get-source-map.js +25 -0
- package/dist/shared/dev-overlay/icons.d.ts +28 -0
- package/{shared/dev-overlay/icons.tsx → dist/shared/dev-overlay/icons.jsx} +35 -173
- package/dist/shared/dev-overlay/index.d.ts +5 -0
- package/dist/shared/dev-overlay/index.jsx +37 -0
- package/package.json +20 -22
- package/client/mount.ts +0 -99
- package/client/spa/index.tsx +0 -10
- package/config/server-fns-runtime.ts +0 -28
- package/config/server-handler.ts +0 -261
- package/config/server-runtime.ts +0 -229
- package/middleware/index.ts +0 -70
- package/router/FileRoutes.ts +0 -35
- package/router/lazyRoute.ts +0 -55
- package/router/routes.ts +0 -87
- package/server/StartServer.tsx +0 -126
- package/server/fetchEvent.ts +0 -113
- package/server/handler.ts +0 -112
- package/server/islands/index.tsx +0 -103
- package/server/islands/utils.tsx +0 -89
- package/server/pageEvent.ts +0 -50
- package/server/renderAsset.tsx +0 -23
- package/server/serverFunction.tsx +0 -6
- package/server/spa/StartServer.tsx +0 -52
- package/server/spa/handler.ts +0 -24
- package/server/types.ts +0 -81
- package/shared/ErrorBoundary.tsx +0 -23
- package/shared/GET.ts +0 -5
- package/shared/HttpHeader.tsx +0 -35
- package/shared/HttpStatusCode.tsx +0 -19
- package/shared/clientOnly.tsx +0 -29
- package/shared/dev-overlay/CodeView.tsx +0 -95
- package/shared/dev-overlay/DevOverlayDialog.tsx +0 -280
- package/shared/dev-overlay/createStackFrame.ts +0 -77
- package/shared/dev-overlay/download.ts +0 -6
- package/shared/dev-overlay/env.d.ts +0 -4
- package/shared/dev-overlay/get-source-map.ts +0 -35
- package/shared/dev-overlay/index.tsx +0 -61
- package/shared/index.ts +0 -5
- /package/{router/index.ts → dist/router/index.d.ts} +0 -0
- /package/{server/index.tsx → dist/server/index.d.ts} +0 -0
- /package/{shared → dist/shared}/dev-overlay/styles.css +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { sharedConfig } from "solid-js";
|
|
2
|
+
import { renderToStream, renderToString } from "solid-js/web";
|
|
3
|
+
import { provideRequestEvent } from "solid-js/web/storage";
|
|
4
|
+
import { eventHandler, sendRedirect, setHeader, setResponseStatus } from "vinxi/http";
|
|
5
|
+
import { matchAPIRoute } from "../router/routes";
|
|
6
|
+
import { getFetchEvent } from "./fetchEvent";
|
|
7
|
+
import { createPageEvent } from "./pageEvent";
|
|
8
|
+
export function createBaseHandler(fn, createPageEvent, options = {}) {
|
|
9
|
+
return eventHandler({
|
|
10
|
+
handler: (e) => {
|
|
11
|
+
const event = getFetchEvent(e);
|
|
12
|
+
return provideRequestEvent(event, async () => {
|
|
13
|
+
// api
|
|
14
|
+
const match = matchAPIRoute(new URL(event.request.url).pathname, event.request.method);
|
|
15
|
+
if (match) {
|
|
16
|
+
const mod = await match.handler.import();
|
|
17
|
+
const fn = mod[event.request.method];
|
|
18
|
+
event.params = match.params || {};
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
sharedConfig.context = { event };
|
|
21
|
+
const res = await fn(event);
|
|
22
|
+
if (res !== undefined)
|
|
23
|
+
return res;
|
|
24
|
+
if (event.request.method !== "GET") {
|
|
25
|
+
throw new Error(`API handler for ${event.request.method} "${event.request.url}" did not return a response.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// render
|
|
29
|
+
const context = await createPageEvent(event);
|
|
30
|
+
if (typeof options === "function")
|
|
31
|
+
options = await options(context);
|
|
32
|
+
const mode = options.mode || "stream";
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
if (options.nonce)
|
|
35
|
+
context.nonce = options.nonce;
|
|
36
|
+
if (mode === "sync" || !import.meta.env.START_SSR) {
|
|
37
|
+
const html = renderToString(() => {
|
|
38
|
+
sharedConfig.context.event = context;
|
|
39
|
+
return fn(context);
|
|
40
|
+
}, options);
|
|
41
|
+
if (context.response && context.response.headers.get("Location")) {
|
|
42
|
+
return sendRedirect(e, context.response.headers.get("Location"));
|
|
43
|
+
}
|
|
44
|
+
return html;
|
|
45
|
+
}
|
|
46
|
+
let cloned = { ...options };
|
|
47
|
+
if (cloned.onCompleteAll) {
|
|
48
|
+
const og = cloned.onCompleteAll;
|
|
49
|
+
cloned.onCompleteAll = options => {
|
|
50
|
+
handleStreamCompleteRedirect(context)(options);
|
|
51
|
+
og(options);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
cloned.onCompleteAll = handleStreamCompleteRedirect(context);
|
|
56
|
+
if (cloned.onCompleteShell) {
|
|
57
|
+
const og = cloned.onCompleteShell;
|
|
58
|
+
cloned.onCompleteShell = options => {
|
|
59
|
+
handleShellCompleteRedirect(context, e)();
|
|
60
|
+
og(options);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
cloned.onCompleteShell = handleShellCompleteRedirect(context, e);
|
|
65
|
+
const stream = renderToStream(() => {
|
|
66
|
+
sharedConfig.context.event = context;
|
|
67
|
+
return fn(context);
|
|
68
|
+
}, cloned);
|
|
69
|
+
if (context.response && context.response.headers.get("Location")) {
|
|
70
|
+
return sendRedirect(e, context.response.headers.get("Location"));
|
|
71
|
+
}
|
|
72
|
+
if (mode === "async")
|
|
73
|
+
return stream;
|
|
74
|
+
// fix cloudflare streaming
|
|
75
|
+
const { writable, readable } = new TransformStream();
|
|
76
|
+
stream.pipeTo(writable);
|
|
77
|
+
return readable;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function handleShellCompleteRedirect(context, e) {
|
|
83
|
+
return () => {
|
|
84
|
+
if (context.response && context.response.headers.get("Location")) {
|
|
85
|
+
setResponseStatus(e, 302);
|
|
86
|
+
setHeader(e, "Location", context.response.headers.get("Location"));
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function handleStreamCompleteRedirect(context) {
|
|
91
|
+
return ({ write }) => {
|
|
92
|
+
const to = context.response && context.response.headers.get("Location");
|
|
93
|
+
to && write(`<script>window.location="${to}"</script>`);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function createHandler(fn, options) {
|
|
97
|
+
return createBaseHandler(fn, createPageEvent, options);
|
|
98
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Component } from "solid-js";
|
|
2
|
+
declare module "solid-js" {
|
|
3
|
+
namespace JSX {
|
|
4
|
+
interface IntrinsicElements {
|
|
5
|
+
"solid-island": {
|
|
6
|
+
"data-props": string;
|
|
7
|
+
"data-id": string;
|
|
8
|
+
"data-when": "idle" | "load";
|
|
9
|
+
children: JSX.Element;
|
|
10
|
+
};
|
|
11
|
+
"solid-children": {
|
|
12
|
+
children: JSX.Element;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export declare function createIslandReference<T extends Component<any>>(Comp: T | (() => Promise<{
|
|
18
|
+
default: T;
|
|
19
|
+
}>), id: string, name: string): T;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
import { lazy, sharedConfig } from "solid-js";
|
|
3
|
+
import { Hydration, NoHydration, getRequestEvent } from "solid-js/web";
|
|
4
|
+
// import { IslandManifest } from "./types";
|
|
5
|
+
import { splitProps } from "./utils";
|
|
6
|
+
export function createIslandReference(Comp, id, name) {
|
|
7
|
+
let Component = Comp;
|
|
8
|
+
if (!import.meta.env.START_ISLANDS) {
|
|
9
|
+
// TODO: have some sane semantics for islands used in non-island mode
|
|
10
|
+
return lazy(Comp);
|
|
11
|
+
}
|
|
12
|
+
function IslandComponent(props) {
|
|
13
|
+
return (<Component {...props}>
|
|
14
|
+
<NoHydration>{props.children}</NoHydration>
|
|
15
|
+
</Component>);
|
|
16
|
+
}
|
|
17
|
+
return ((compProps) => {
|
|
18
|
+
if (import.meta.env.SSR) {
|
|
19
|
+
const context = getRequestEvent();
|
|
20
|
+
const [, props] = splitProps(compProps, ["children"]);
|
|
21
|
+
const [, spreadProps] = splitProps(compProps, []);
|
|
22
|
+
let fpath;
|
|
23
|
+
let styles = [];
|
|
24
|
+
// if (import.meta.env.PROD) {
|
|
25
|
+
// let x = context.env.manifest?.[path] as IslandManifest;
|
|
26
|
+
// context.$islands.add(path);
|
|
27
|
+
// if (x) {
|
|
28
|
+
// fpath = x.script.href;
|
|
29
|
+
// styles = x.assets.filter(v => v.type == "style").map(v => v.href);
|
|
30
|
+
// }
|
|
31
|
+
// } else {
|
|
32
|
+
fpath = id + "#" + name;
|
|
33
|
+
// }
|
|
34
|
+
const serialize = (props) => {
|
|
35
|
+
let offset = 0;
|
|
36
|
+
let el = JSON.stringify(props, (key, value) => {
|
|
37
|
+
if (value && value.t) {
|
|
38
|
+
offset++;
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
"data-props": el,
|
|
45
|
+
"data-offset": offset
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
if (!sharedConfig.context?.noHydrate) {
|
|
50
|
+
return <Component {...compProps}/>;
|
|
51
|
+
}
|
|
52
|
+
return (<Hydration>
|
|
53
|
+
<solid-island data-id={fpath} data-when={props["client:idle"] ? "idle" : "load"} data-css={JSON.stringify(styles)} {...serialize(props)}>
|
|
54
|
+
<IslandComponent {...spreadProps}/>
|
|
55
|
+
</solid-island>
|
|
56
|
+
</Hydration>);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return <Component {...compProps}/>;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function splitProps<T>(props: T, ...keys: (keyof T)[]): [T, T];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
// TODO rename to utils.ts?
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
import { $PROXY } from "solid-js";
|
|
5
|
+
function trueFn() {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
const propTraps = {
|
|
9
|
+
get(_, property, receiver) {
|
|
10
|
+
if (property === $PROXY)
|
|
11
|
+
return receiver;
|
|
12
|
+
return _.get(property);
|
|
13
|
+
},
|
|
14
|
+
has(_, property) {
|
|
15
|
+
return _.has(property);
|
|
16
|
+
},
|
|
17
|
+
set: trueFn,
|
|
18
|
+
deleteProperty: trueFn,
|
|
19
|
+
getOwnPropertyDescriptor(_, property) {
|
|
20
|
+
return {
|
|
21
|
+
configurable: true,
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get() {
|
|
24
|
+
return _.get(property);
|
|
25
|
+
},
|
|
26
|
+
set: trueFn,
|
|
27
|
+
deleteProperty: trueFn
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
ownKeys(_) {
|
|
31
|
+
return _.keys();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export function splitProps(props, ...keys) {
|
|
35
|
+
const blocked = new Set(keys.flat());
|
|
36
|
+
const descriptors = Object.getOwnPropertyDescriptors(props);
|
|
37
|
+
const isProxy = $PROXY in props;
|
|
38
|
+
if (!isProxy)
|
|
39
|
+
keys.push(Object.keys(descriptors).filter(k => !blocked.has(k)));
|
|
40
|
+
const res = keys.map(k => {
|
|
41
|
+
const clone = {};
|
|
42
|
+
for (let i = 0; i < k.length; i++) {
|
|
43
|
+
const key = k[i];
|
|
44
|
+
let cache;
|
|
45
|
+
Object.defineProperty(clone, key, {
|
|
46
|
+
enumerable: descriptors[key]?.enumerable ?? false,
|
|
47
|
+
configurable: true,
|
|
48
|
+
get() {
|
|
49
|
+
if (cache) {
|
|
50
|
+
return cache;
|
|
51
|
+
}
|
|
52
|
+
let val = props[key];
|
|
53
|
+
if (val?.t) {
|
|
54
|
+
val.t = `<solid-children>${val.t}</solid-children>`;
|
|
55
|
+
}
|
|
56
|
+
else if (Array.isArray(val) && val.every(v => v?.t)) {
|
|
57
|
+
val = {
|
|
58
|
+
t: `<solid-children>${val.map(v => `${v.t}`).join("\n")}</solid-children>`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
cache = val;
|
|
62
|
+
return val;
|
|
63
|
+
},
|
|
64
|
+
set() {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return clone;
|
|
70
|
+
});
|
|
71
|
+
if (isProxy) {
|
|
72
|
+
res.push(new Proxy({
|
|
73
|
+
get(property) {
|
|
74
|
+
return blocked.has(property) ? undefined : props[property];
|
|
75
|
+
},
|
|
76
|
+
has(property) {
|
|
77
|
+
return blocked.has(property) ? false : property in props;
|
|
78
|
+
},
|
|
79
|
+
keys() {
|
|
80
|
+
return Object.keys(props).filter(k => !blocked.has(k));
|
|
81
|
+
}
|
|
82
|
+
}, propTraps));
|
|
83
|
+
}
|
|
84
|
+
return res;
|
|
85
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getCookie, setCookie } from "vinxi/http";
|
|
2
|
+
import { createRoutes } from "../router/FileRoutes";
|
|
3
|
+
function initFromFlash(ctx) {
|
|
4
|
+
const flash = getCookie(ctx.nativeEvent, "flash");
|
|
5
|
+
if (!flash)
|
|
6
|
+
return;
|
|
7
|
+
let param = JSON.parse(flash);
|
|
8
|
+
if (!param || !param.result)
|
|
9
|
+
return;
|
|
10
|
+
const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
|
|
11
|
+
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
12
|
+
return {
|
|
13
|
+
input,
|
|
14
|
+
url: param.url,
|
|
15
|
+
pending: false,
|
|
16
|
+
result: param.error ? new Error(param.result) : param.result,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export async function createPageEvent(ctx) {
|
|
20
|
+
const clientManifest = import.meta.env.MANIFEST["client"];
|
|
21
|
+
const serverManifest = import.meta.env.MANIFEST["ssr"];
|
|
22
|
+
ctx.response.headers.set("Content-Type", "text/html");
|
|
23
|
+
// const prevPath = ctx.request.headers.get("x-solid-referrer");
|
|
24
|
+
// const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
|
|
25
|
+
const pageEvent = Object.assign(ctx, {
|
|
26
|
+
manifest: await clientManifest.json(),
|
|
27
|
+
assets: [
|
|
28
|
+
...(await clientManifest.inputs[clientManifest.handler].assets()),
|
|
29
|
+
...(import.meta.env.START_ISLANDS
|
|
30
|
+
? (await serverManifest.inputs[serverManifest.handler].assets()).filter(s => s.attrs.rel !== "modulepreload")
|
|
31
|
+
: [])
|
|
32
|
+
],
|
|
33
|
+
router: {
|
|
34
|
+
submission: initFromFlash(ctx)
|
|
35
|
+
},
|
|
36
|
+
routes: createRoutes(),
|
|
37
|
+
// prevUrl: prevPath || "",
|
|
38
|
+
// mutation: mutation,
|
|
39
|
+
// $type: FETCH_EVENT,
|
|
40
|
+
$islands: new Set()
|
|
41
|
+
});
|
|
42
|
+
return pageEvent;
|
|
43
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const assetMap = {
|
|
2
|
+
style: (props) => (<style {...props.attrs}>{props.children}</style>),
|
|
3
|
+
link: (props) => <link {...props.attrs}/>,
|
|
4
|
+
script: (props) => {
|
|
5
|
+
return props.attrs.src ? (<script {...props.attrs} id={props.key}>
|
|
6
|
+
{" "}
|
|
7
|
+
</script>) : null;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
export function renderAsset(asset) {
|
|
11
|
+
let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset;
|
|
12
|
+
return assetMap[tag]({ attrs, key, children });
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NoHydration, getRequestEvent, ssr } from "solid-js/web";
|
|
2
|
+
import { renderAsset } from "../renderAsset";
|
|
3
|
+
const docType = ssr("<!DOCTYPE html>");
|
|
4
|
+
export function StartServer(props) {
|
|
5
|
+
const context = getRequestEvent();
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
const nonce = context.nonce;
|
|
8
|
+
return (<NoHydration>
|
|
9
|
+
{docType}
|
|
10
|
+
<props.document assets={<>{context.assets.map((m) => renderAsset(m))}</>} scripts={nonce ? (<>
|
|
11
|
+
<script nonce={nonce} innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
|
|
12
|
+
<script type="module" src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
|
|
13
|
+
</>) : (<>
|
|
14
|
+
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
|
|
15
|
+
<script type="module" src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
|
|
16
|
+
</>)}/>
|
|
17
|
+
</NoHydration>);
|
|
18
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { FetchEvent, HandlerOptions, PageEvent } from "../types";
|
|
2
|
+
export declare function createHandler(fn: (context: PageEvent) => unknown, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions)): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
|
|
3
|
+
export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createBaseHandler } from "../handler";
|
|
2
|
+
export function createHandler(fn, options) {
|
|
3
|
+
return createBaseHandler(fn, createPageEvent, options);
|
|
4
|
+
}
|
|
5
|
+
export async function createPageEvent(ctx) {
|
|
6
|
+
const clientManifest = import.meta.env.MANIFEST["client"];
|
|
7
|
+
const pageEvent = Object.assign(ctx, {
|
|
8
|
+
manifest: await clientManifest.json(),
|
|
9
|
+
assets: [...(await clientManifest.inputs[clientManifest.handler].assets())],
|
|
10
|
+
routes: [],
|
|
11
|
+
// prevUrl: "",
|
|
12
|
+
// mutation: false,
|
|
13
|
+
// $type: FETCH_EVENT,
|
|
14
|
+
$islands: new Set()
|
|
15
|
+
});
|
|
16
|
+
return pageEvent;
|
|
17
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import { RequestEvent } from "solid-js/web";
|
|
3
|
+
import { HTTPEvent } from "vinxi/http";
|
|
4
|
+
export type DocumentComponentProps = {
|
|
5
|
+
assets: JSX.Element;
|
|
6
|
+
scripts: JSX.Element;
|
|
7
|
+
children?: JSX.Element;
|
|
8
|
+
};
|
|
9
|
+
export type Asset = {
|
|
10
|
+
tag: "style";
|
|
11
|
+
attrs: JSX.StyleHTMLAttributes<HTMLStyleElement> & {
|
|
12
|
+
key?: string;
|
|
13
|
+
};
|
|
14
|
+
children?: JSX.Element;
|
|
15
|
+
} | {
|
|
16
|
+
tag: "script";
|
|
17
|
+
attrs: JSX.ScriptHTMLAttributes<HTMLScriptElement> & {
|
|
18
|
+
key?: string;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
tag: "link";
|
|
22
|
+
attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> & {
|
|
23
|
+
key?: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type HandlerOptions = {
|
|
27
|
+
mode?: "sync" | "async" | "stream";
|
|
28
|
+
nonce?: string;
|
|
29
|
+
renderId?: string;
|
|
30
|
+
onCompleteAll?: (options: {
|
|
31
|
+
write: (v: any) => void;
|
|
32
|
+
}) => void;
|
|
33
|
+
onCompleteShell?: (options: {
|
|
34
|
+
write: (v: any) => void;
|
|
35
|
+
}) => void;
|
|
36
|
+
};
|
|
37
|
+
export type ContextMatches = {
|
|
38
|
+
originalPath: string;
|
|
39
|
+
pattern: string;
|
|
40
|
+
path: string;
|
|
41
|
+
params: unknown;
|
|
42
|
+
};
|
|
43
|
+
export interface ResponseStub {
|
|
44
|
+
status?: number;
|
|
45
|
+
statusText?: string;
|
|
46
|
+
headers: Headers;
|
|
47
|
+
}
|
|
48
|
+
export interface FetchEvent {
|
|
49
|
+
request: Request;
|
|
50
|
+
response: ResponseStub;
|
|
51
|
+
clientAddress?: string;
|
|
52
|
+
locals: RequestEventLocals;
|
|
53
|
+
nativeEvent: HTTPEvent;
|
|
54
|
+
}
|
|
55
|
+
export interface RequestEventLocals {
|
|
56
|
+
[key: string | symbol]: any;
|
|
57
|
+
}
|
|
58
|
+
export interface PageEvent extends RequestEvent {
|
|
59
|
+
manifest: any;
|
|
60
|
+
assets: any;
|
|
61
|
+
routes: any[];
|
|
62
|
+
$islands: Set<string>;
|
|
63
|
+
}
|
|
64
|
+
export interface APIEvent extends FetchEvent {
|
|
65
|
+
params: {
|
|
66
|
+
[key: string]: string;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export interface APIHandler {
|
|
70
|
+
(event: APIEvent): Promise<any>;
|
|
71
|
+
}
|
|
72
|
+
export interface ServerFunctionMeta {
|
|
73
|
+
id: string;
|
|
74
|
+
}
|
|
75
|
+
declare module "solid-js/web" {
|
|
76
|
+
interface RequestEvent extends FetchEvent {
|
|
77
|
+
serverOnly?: boolean;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
import { ErrorBoundary as DefaultErrorBoundary } from "solid-js";
|
|
3
|
+
import { isServer } from "solid-js/web";
|
|
4
|
+
import { HttpStatusCode } from "./HttpStatusCode";
|
|
5
|
+
import { DevOverlay } from "./dev-overlay";
|
|
6
|
+
export const ErrorBoundary = import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY
|
|
7
|
+
? (props) => <DevOverlay>{props.children}</DevOverlay>
|
|
8
|
+
: (props) => {
|
|
9
|
+
const message = isServer ? "500 | Internal Server Error" : "Error | Uncaught Client Exception";
|
|
10
|
+
return (<DefaultErrorBoundary fallback={<>
|
|
11
|
+
<span style="font-size:1.5em;text-align:center;position:fixed;left:0px;bottom:55%;width:100%;">{message}</span>
|
|
12
|
+
<HttpStatusCode code={500}/>
|
|
13
|
+
</>}>
|
|
14
|
+
{props.children}
|
|
15
|
+
</DefaultErrorBoundary>);
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function GET<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
import { onCleanup } from "solid-js";
|
|
3
|
+
import { getRequestEvent, isServer } from "solid-js/web";
|
|
4
|
+
export const HttpHeader = isServer
|
|
5
|
+
? (props) => {
|
|
6
|
+
const event = getRequestEvent();
|
|
7
|
+
if (props.append)
|
|
8
|
+
event.response.headers.append(props.name, props.value);
|
|
9
|
+
else
|
|
10
|
+
event.response.headers.set(props.name, props.value);
|
|
11
|
+
onCleanup(() => {
|
|
12
|
+
if (event.nativeEvent.handled)
|
|
13
|
+
return;
|
|
14
|
+
const value = event.response.headers.get(props.name);
|
|
15
|
+
if (!value)
|
|
16
|
+
return;
|
|
17
|
+
if (!value.includes(", ")) {
|
|
18
|
+
if (value === props.value)
|
|
19
|
+
event.response.headers.delete(props.name);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const values = value.split(", ");
|
|
23
|
+
const index = values.indexOf(props.value);
|
|
24
|
+
index !== -1 && values.splice(index, 1);
|
|
25
|
+
if (values.length)
|
|
26
|
+
event.response.headers.set(props.name, values.join(","));
|
|
27
|
+
else
|
|
28
|
+
event.response.headers.delete(props.name);
|
|
29
|
+
});
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
: (_props) => null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @refresh skip
|
|
2
|
+
import { onCleanup } from "solid-js";
|
|
3
|
+
import { getRequestEvent, isServer } from "solid-js/web";
|
|
4
|
+
export const HttpStatusCode = isServer
|
|
5
|
+
? (props) => {
|
|
6
|
+
const event = getRequestEvent();
|
|
7
|
+
event.response.status = props.code;
|
|
8
|
+
event.response.statusText = props.text;
|
|
9
|
+
onCleanup(() => !event.nativeEvent.handled && (event.response.status = 200));
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
: (_props) => null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createMemo, createSignal, onMount, sharedConfig, splitProps, untrack } from "solid-js";
|
|
2
|
+
import { isServer } from "solid-js/web";
|
|
3
|
+
// not using Suspense
|
|
4
|
+
export default function clientOnly(fn) {
|
|
5
|
+
if (isServer)
|
|
6
|
+
return (props) => props.fallback;
|
|
7
|
+
const [comp, setComp] = createSignal();
|
|
8
|
+
fn().then(m => setComp(() => m.default));
|
|
9
|
+
return (props) => {
|
|
10
|
+
let Comp;
|
|
11
|
+
let m;
|
|
12
|
+
const [, rest] = splitProps(props, ["fallback"]);
|
|
13
|
+
if ((Comp = comp()) && !sharedConfig.context)
|
|
14
|
+
return Comp(rest);
|
|
15
|
+
const [mounted, setMounted] = createSignal(!sharedConfig.context);
|
|
16
|
+
onMount(() => setMounted(true));
|
|
17
|
+
return createMemo(() => ((Comp = comp()), (m = mounted()), untrack(() => (Comp && m ? Comp(rest) : props.fallback))));
|
|
18
|
+
};
|
|
19
|
+
}
|