@solidjs/start 0.5.5 → 0.5.6
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/client/StartClient.tsx +2 -1
- package/client/mount.ts +6 -5
- package/client/spa/index.tsx +3 -2
- package/config/index.js +16 -10
- package/config/server-fns-runtime.ts +1 -1
- package/config/server-handler.ts +20 -20
- package/config/server-runtime.ts +7 -6
- package/package.json +1 -1
- package/server/StartServer.tsx +17 -15
- package/server/fetchEvent.ts +5 -4
- package/server/handler.ts +5 -5
- package/server/pageEvent.ts +4 -4
- package/server/renderAsset.tsx +18 -13
- package/server/spa/StartServer.tsx +8 -6
- package/server/spa/handler.ts +2 -2
- package/server/types.ts +20 -7
- package/shared/FileRoutes.tsx +3 -2
- package/shared/HttpHeader.tsx +2 -1
- package/shared/HttpStatusCode.tsx +2 -1
- package/shared/dev-overlay/CodeView.tsx +2 -2
- package/shared/dev-overlay/DevOverlayDialog.tsx +9 -9
- package/shared/dev-overlay/createStackFrame.ts +6 -7
- package/shared/dev-overlay/get-source-map.ts +1 -1
- package/shared/lazyRoute.tsx +10 -9
- package/shared/routes.ts +7 -2
package/client/StartClient.tsx
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import App from "#start/app";
|
|
3
|
+
import type { JSX } from "solid-js";
|
|
3
4
|
import { ErrorBoundary } from "../shared/ErrorBoundary";
|
|
4
5
|
import "./mount";
|
|
5
6
|
|
|
6
|
-
function Dummy(props) {
|
|
7
|
+
function Dummy(props: { children: JSX.Element }) {
|
|
7
8
|
return props.children;
|
|
8
9
|
}
|
|
9
10
|
|
package/client/mount.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
1
2
|
import { createStore } from "solid-js/store";
|
|
2
|
-
import { createComponent, getHydrationKey, getOwner, hydrate } from "solid-js/web";
|
|
3
|
+
import { createComponent, getHydrationKey, getOwner, hydrate, type MountableElement } from "solid-js/web";
|
|
3
4
|
|
|
4
|
-
export function mount(fn, el) {
|
|
5
|
+
export function mount(fn: () => JSX.Element, el: MountableElement) {
|
|
5
6
|
if (import.meta.env.START_ISLANDS) {
|
|
6
7
|
const map = new WeakMap();
|
|
7
8
|
async function mountIsland(el: HTMLElement) {
|
|
@@ -19,11 +20,11 @@ export function mount(fn, el) {
|
|
|
19
20
|
|
|
20
21
|
let mod = await import(
|
|
21
22
|
/* @vite-ignore */
|
|
22
|
-
import.meta.env.MANIFEST["client"]
|
|
23
|
+
import.meta.env.MANIFEST["client"]!.chunks[el.dataset.id!.split("#")[0] as string]!.output.path
|
|
23
24
|
);
|
|
24
25
|
if (!mod || !el.dataset.hk) return;
|
|
25
26
|
|
|
26
|
-
let Component = mod[el.dataset.id
|
|
27
|
+
let Component = mod[el.dataset.id!.split("#")[1] as string];
|
|
27
28
|
let hk = el.dataset.hk;
|
|
28
29
|
// _$DEBUG("hydrating island", el.dataset.island, hk.slice(0, hk.length - 1) + `1-`, el);
|
|
29
30
|
|
|
@@ -68,7 +69,7 @@ export function mount(fn, el) {
|
|
|
68
69
|
Promise.all(
|
|
69
70
|
[...assets].map(
|
|
70
71
|
asset =>
|
|
71
|
-
import(/* @vite-ignore */import.meta.env.MANIFEST["client"]
|
|
72
|
+
import(/* @vite-ignore */import.meta.env.MANIFEST["client"]!.chunks[asset.split("#")[0] as string]!.output.path)
|
|
72
73
|
)
|
|
73
74
|
)
|
|
74
75
|
.then(() => {
|
package/client/spa/index.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import { render, type MountableElement } from "solid-js/web";
|
|
2
3
|
import "vinxi/client";
|
|
3
4
|
|
|
4
|
-
export function mount(fn, el) {
|
|
5
|
+
export function mount(fn: () => JSX.Element, el: MountableElement) {
|
|
5
6
|
render(fn, el);
|
|
6
7
|
}
|
|
7
8
|
|
package/config/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { serverFunctions } from "@vinxi/server-functions/plugin";
|
|
2
|
-
import { serverTransform } from "@vinxi/server-functions/server";
|
|
2
|
+
import { server as serverFunctionServer, serverTransform } from "@vinxi/server-functions/server";
|
|
3
3
|
import defu from "defu";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
@@ -8,10 +8,7 @@ import { createApp, resolve } from "vinxi";
|
|
|
8
8
|
import { normalize } from "vinxi/lib/path";
|
|
9
9
|
import { config } from "vinxi/plugins/config";
|
|
10
10
|
import solid from "vite-plugin-solid";
|
|
11
|
-
import {
|
|
12
|
-
SolidStartClientFileRouter,
|
|
13
|
-
SolidStartServerFileRouter
|
|
14
|
-
} from "./fs-router.js";
|
|
11
|
+
import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js";
|
|
15
12
|
import { serverComponents } from "./server-components.js";
|
|
16
13
|
|
|
17
14
|
const DEFAULT_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
|
|
@@ -120,6 +117,7 @@ export function defineConfig(baseConfig = {}) {
|
|
|
120
117
|
...userConfig.resolve?.alias
|
|
121
118
|
}
|
|
122
119
|
},
|
|
120
|
+
cacheDir: "node_modules/.vinxi/server",
|
|
123
121
|
define: {
|
|
124
122
|
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
125
123
|
"import.meta.env.SSR": JSON.stringify(true),
|
|
@@ -176,6 +174,7 @@ export function defineConfig(baseConfig = {}) {
|
|
|
176
174
|
...userConfig.resolve?.alias
|
|
177
175
|
}
|
|
178
176
|
},
|
|
177
|
+
cacheDir: "node_modules/.vinxi/client",
|
|
179
178
|
define: {
|
|
180
179
|
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
181
180
|
"import.meta.env.SSR": JSON.stringify(false),
|
|
@@ -187,9 +186,13 @@ export function defineConfig(baseConfig = {}) {
|
|
|
187
186
|
],
|
|
188
187
|
base: "/_build"
|
|
189
188
|
},
|
|
190
|
-
|
|
189
|
+
|
|
190
|
+
{
|
|
191
|
+
name: "server-fns",
|
|
192
|
+
type: "http",
|
|
193
|
+
base: "/_server",
|
|
191
194
|
handler: normalize(fileURLToPath(new URL("./server-handler.ts", import.meta.url))),
|
|
192
|
-
|
|
195
|
+
target: "server",
|
|
193
196
|
routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
|
|
194
197
|
plugins: async () => [
|
|
195
198
|
config("user", {
|
|
@@ -201,10 +204,13 @@ export function defineConfig(baseConfig = {}) {
|
|
|
201
204
|
"@solidjs/start > source-map-js",
|
|
202
205
|
"@solidjs/start > error-stack-parser"
|
|
203
206
|
]
|
|
204
|
-
}
|
|
207
|
+
},
|
|
208
|
+
cacheDir: "node_modules/.vinxi/server-fns"
|
|
205
209
|
}),
|
|
206
210
|
...(typeof plugins === "function" ? [...(await plugins())] : plugins),
|
|
207
|
-
|
|
211
|
+
serverFunctionServer({
|
|
212
|
+
runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url)))
|
|
213
|
+
}),
|
|
208
214
|
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
|
|
209
215
|
config("app-server", {
|
|
210
216
|
resolve: {
|
|
@@ -228,7 +234,7 @@ export function defineConfig(baseConfig = {}) {
|
|
|
228
234
|
})
|
|
229
235
|
],
|
|
230
236
|
middleware: start.middleware
|
|
231
|
-
}
|
|
237
|
+
}
|
|
232
238
|
]
|
|
233
239
|
});
|
|
234
240
|
}
|
|
@@ -2,7 +2,7 @@ import { getRequestEvent } from "solid-js/web";
|
|
|
2
2
|
import { provideRequestEvent } from "solid-js/web/storage";
|
|
3
3
|
import { cloneEvent } from "../server/fetchEvent";
|
|
4
4
|
|
|
5
|
-
export function createServerReference(fn, id, name) {
|
|
5
|
+
export function createServerReference(fn: Function, id: string, name: string) {
|
|
6
6
|
if (typeof fn !== "function") throw new Error("Export from a 'use server' module must be a function");
|
|
7
7
|
const baseURL = import.meta.env.SERVER_BASE_URL;
|
|
8
8
|
return new Proxy(fn, {
|
package/config/server-handler.ts
CHANGED
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
URLSearchParamsPlugin
|
|
15
15
|
} from "seroval-plugins/web";
|
|
16
16
|
import { sharedConfig } from "solid-js";
|
|
17
|
-
import {
|
|
17
|
+
import { renderToStream } from "solid-js/web";
|
|
18
18
|
import { provideRequestEvent } from "solid-js/web/storage";
|
|
19
|
-
import { eventHandler, setHeader, setResponseStatus } from "vinxi/http";
|
|
19
|
+
import { eventHandler, setHeader, setResponseStatus, type H3Event } from "vinxi/http";
|
|
20
20
|
import invariant from "vinxi/lib/invariant";
|
|
21
21
|
import { cloneEvent, getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
|
|
22
22
|
import { createPageEvent } from "../server/pageEvent";
|
|
@@ -24,14 +24,14 @@ import { createPageEvent } from "../server/pageEvent";
|
|
|
24
24
|
import App from "#start/app";
|
|
25
25
|
import { FetchEvent, PageEvent } from "../server";
|
|
26
26
|
|
|
27
|
-
function createChunk(data) {
|
|
27
|
+
function createChunk(data: string) {
|
|
28
28
|
const bytes = data.length;
|
|
29
29
|
const baseHex = bytes.toString(16);
|
|
30
30
|
const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
|
|
31
31
|
return new TextEncoder().encode(`;0x${totalHex};${data}`);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function serializeToStream(id, value) {
|
|
34
|
+
function serializeToStream(id: string, value: any) {
|
|
35
35
|
return new ReadableStream({
|
|
36
36
|
start(controller) {
|
|
37
37
|
crossSerializeStream(value, {
|
|
@@ -64,7 +64,7 @@ function serializeToStream(id, value) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
async function handleServerFunction(h3Event) {
|
|
67
|
+
async function handleServerFunction(h3Event: H3Event) {
|
|
68
68
|
const event = getFetchEvent(h3Event);
|
|
69
69
|
const request = event.request;
|
|
70
70
|
|
|
@@ -83,32 +83,32 @@ async function handleServerFunction(h3Event) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const serverFunction = (
|
|
86
|
-
await import.meta.env.MANIFEST[import.meta.env.ROUTER_NAME]
|
|
87
|
-
)[name];
|
|
88
|
-
let parsed = [];
|
|
86
|
+
await import.meta.env.MANIFEST[import.meta.env.ROUTER_NAME]!.chunks[filepath!]!.import()
|
|
87
|
+
)[name!];
|
|
88
|
+
let parsed: any[] = [];
|
|
89
89
|
|
|
90
90
|
// grab bound arguments from url when no JS
|
|
91
91
|
if (!instance || h3Event.method === "GET") {
|
|
92
92
|
const args = url.searchParams.get("args");
|
|
93
|
-
if (args) JSON.parse(args).forEach(arg => parsed.push(arg));
|
|
93
|
+
if (args) JSON.parse(args).forEach((arg: any) => parsed.push(arg));
|
|
94
94
|
}
|
|
95
95
|
if (h3Event.method === "POST") {
|
|
96
96
|
const contentType = request.headers.get("content-type");
|
|
97
97
|
if (
|
|
98
|
-
contentType
|
|
99
|
-
contentType
|
|
98
|
+
contentType?.startsWith("multipart/form-data") ||
|
|
99
|
+
contentType?.startsWith("application/x-www-form-urlencoded")
|
|
100
100
|
) {
|
|
101
101
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
102
102
|
// (issue only in edge runtimes)
|
|
103
103
|
parsed.push(
|
|
104
|
-
await new Request(request, { ...request, body: h3Event.node.req.body }).formData()
|
|
104
|
+
await new Request(request, { ...request, body: (h3Event.node.req as any).body }).formData()
|
|
105
105
|
);
|
|
106
106
|
// what should work when #1721 is fixed
|
|
107
107
|
// parsed.push(await request.formData);
|
|
108
108
|
} else {
|
|
109
109
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
110
110
|
// (issue only in edge runtimes)
|
|
111
|
-
const tmpReq = new Request(request, { ...request, body: h3Event.node.req.body });
|
|
111
|
+
const tmpReq = new Request(request, { ...request, body: (h3Event.node.req as any).body });
|
|
112
112
|
// what should work when #1721 is fixed
|
|
113
113
|
// just use request.json() here
|
|
114
114
|
parsed = fromJSON(await tmpReq.json(), {
|
|
@@ -150,7 +150,7 @@ async function handleServerFunction(h3Event) {
|
|
|
150
150
|
// handle no JS success case
|
|
151
151
|
if (!instance) {
|
|
152
152
|
const isError = result instanceof Error;
|
|
153
|
-
const refererUrl = new URL(request.headers.get("referer"));
|
|
153
|
+
const refererUrl = new URL(request.headers.get("referer")!);
|
|
154
154
|
return new Response(null, {
|
|
155
155
|
status: 302,
|
|
156
156
|
headers: {
|
|
@@ -184,14 +184,14 @@ async function handleServerFunction(h3Event) {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
async function handleSingleFlight(sourceEvent: FetchEvent, result: any) {
|
|
187
|
-
let revalidate;
|
|
188
|
-
let url = new URL(sourceEvent.request.headers.get("referer")).toString();
|
|
187
|
+
let revalidate: string[];
|
|
188
|
+
let url = new URL(sourceEvent.request.headers.get("referer")!).toString();
|
|
189
189
|
if (result instanceof Response) {
|
|
190
190
|
if (result.headers.has("X-Revalidate"))
|
|
191
|
-
revalidate = result.headers.get("X-Revalidate")
|
|
191
|
+
revalidate = result.headers.get("X-Revalidate")!.split(",");
|
|
192
192
|
if (result.headers.has("Location"))
|
|
193
193
|
url = new URL(
|
|
194
|
-
result.headers.get("Location")
|
|
194
|
+
result.headers.get("Location")!,
|
|
195
195
|
new URL(sourceEvent.request.url).origin + import.meta.env.SERVER_BASE_URL
|
|
196
196
|
).toString();
|
|
197
197
|
}
|
|
@@ -205,9 +205,9 @@ async function handleSingleFlight(sourceEvent: FetchEvent, result: any) {
|
|
|
205
205
|
event.router.previousUrl = sourceEvent.request.headers.get("referer");
|
|
206
206
|
(async () => {
|
|
207
207
|
try {
|
|
208
|
-
await
|
|
208
|
+
await renderToStream(() => {
|
|
209
209
|
/* @ts-ignore */
|
|
210
|
-
sharedConfig.context =
|
|
210
|
+
sharedConfig.context.event = event;
|
|
211
211
|
App();
|
|
212
212
|
});
|
|
213
213
|
} catch (e) {
|
package/config/server-runtime.ts
CHANGED
|
@@ -11,13 +11,14 @@ import {
|
|
|
11
11
|
URLPlugin,
|
|
12
12
|
URLSearchParamsPlugin
|
|
13
13
|
} from "seroval-plugins/web";
|
|
14
|
+
import { type Component } from "solid-js";
|
|
14
15
|
import { createIslandReference } from "../server/islands";
|
|
15
16
|
|
|
16
17
|
class SerovalChunkReader {
|
|
17
18
|
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
18
19
|
buffer: string;
|
|
19
20
|
done: boolean;
|
|
20
|
-
constructor(stream) {
|
|
21
|
+
constructor(stream: ReadableStream<Uint8Array>) {
|
|
21
22
|
this.reader = stream.getReader();
|
|
22
23
|
this.buffer = "";
|
|
23
24
|
this.done = false;
|
|
@@ -34,7 +35,7 @@ class SerovalChunkReader {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
async next() {
|
|
38
|
+
async next(): Promise<any> {
|
|
38
39
|
// Check if the buffer is empty
|
|
39
40
|
if (this.buffer === "") {
|
|
40
41
|
// if we are already done...
|
|
@@ -84,7 +85,7 @@ class SerovalChunkReader {
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
async function deserializeStream(id, response) {
|
|
88
|
+
async function deserializeStream(id: string, response: Response) {
|
|
88
89
|
if (!response.body) {
|
|
89
90
|
throw new Error("missing body");
|
|
90
91
|
}
|
|
@@ -184,7 +185,7 @@ async function fetchServerFunction(
|
|
|
184
185
|
throw result;
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
export function createServerReference(fn, id, name) {
|
|
188
|
+
export function createServerReference(fn: Function, id: string, name: string) {
|
|
188
189
|
const baseURL = import.meta.env.SERVER_BASE_URL;
|
|
189
190
|
return new Proxy(fn, {
|
|
190
191
|
get(target, prop, receiver) {
|
|
@@ -196,7 +197,7 @@ export function createServerReference(fn, id, name) {
|
|
|
196
197
|
}
|
|
197
198
|
if (prop === "withOptions") {
|
|
198
199
|
return (options: RequestInit) => {
|
|
199
|
-
const fn = (...args) => {
|
|
200
|
+
const fn = (...args: any[]) => {
|
|
200
201
|
const encodeArgs = options.method && options.method.toUpperCase() === "GET";
|
|
201
202
|
return fetchServerFunction(
|
|
202
203
|
encodeArgs
|
|
@@ -218,7 +219,7 @@ export function createServerReference(fn, id, name) {
|
|
|
218
219
|
});
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
export function createClientReference(Component
|
|
222
|
+
export function createClientReference(Component: Component<any>, id: string, name: string) {
|
|
222
223
|
if (typeof Component === "function") {
|
|
223
224
|
return createIslandReference(Component, id, name);
|
|
224
225
|
}
|
package/package.json
CHANGED
package/server/StartServer.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import App from "#start/app";
|
|
3
|
-
import type { Component } from "solid-js";
|
|
3
|
+
import type { Component, JSX } from "solid-js";
|
|
4
4
|
import {
|
|
5
5
|
Hydration,
|
|
6
6
|
HydrationScript,
|
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
} from "solid-js/web";
|
|
12
12
|
import { ErrorBoundary } from "../shared/ErrorBoundary";
|
|
13
13
|
import { renderAsset } from "./renderAsset";
|
|
14
|
-
import type { DocumentComponentProps } from "./types";
|
|
14
|
+
import type { Asset, DocumentComponentProps, PageEvent } from "./types";
|
|
15
15
|
|
|
16
16
|
const docType = ssr("<!DOCTYPE html>");
|
|
17
17
|
|
|
18
|
-
function matchRoute(matches, routes, matched = []) {
|
|
18
|
+
function matchRoute(matches: any[], routes: any[], matched = []): any[] | undefined {
|
|
19
19
|
for (let i = 0; i < routes.length; i++) {
|
|
20
20
|
const segment = routes[i];
|
|
21
21
|
if (segment.path !== matches[0].path) continue;
|
|
22
|
-
let next = [...matched, segment];
|
|
22
|
+
let next: any = [...matched, segment];
|
|
23
23
|
if (segment.children) {
|
|
24
24
|
const nextMatches = matches.slice(1);
|
|
25
25
|
if (nextMatches.length === 0) continue;
|
|
@@ -31,11 +31,13 @@ function matchRoute(matches, routes, matched = []) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function StartServer(props: { document: Component<DocumentComponentProps> }) {
|
|
34
|
-
const context = getRequestEvent() as
|
|
34
|
+
const context = getRequestEvent() as PageEvent;
|
|
35
35
|
|
|
36
|
-
let assets = [];
|
|
36
|
+
let assets: Asset[] = [];
|
|
37
37
|
Promise.resolve().then(async () => {
|
|
38
|
+
// @ts-ignore
|
|
38
39
|
if (context.router && context.router.matches) {
|
|
40
|
+
// @ts-ignore
|
|
39
41
|
const matches = [...context.router.matches];
|
|
40
42
|
while (matches.length && (!matches[0].info || !matches[0].info.filesystem))
|
|
41
43
|
matches.shift();
|
|
@@ -43,9 +45,9 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
43
45
|
if (matched) {
|
|
44
46
|
for (let i = 0; i < matched.length; i++) {
|
|
45
47
|
const segment = matched[i];
|
|
46
|
-
const part = import.meta.env.MANIFEST[import.meta.env.START_ISLANDS ? "ssr" : "client"]
|
|
47
|
-
.inputs[segment["$component"].src]
|
|
48
|
-
const asset = await part.assets();
|
|
48
|
+
const part = import.meta.env.MANIFEST[import.meta.env.START_ISLANDS ? "ssr" : "client"]!
|
|
49
|
+
.inputs[segment["$component"].src]!;
|
|
50
|
+
const asset = await part.assets() as any;
|
|
49
51
|
assets.push.apply(assets, asset);
|
|
50
52
|
}
|
|
51
53
|
} else console.warn("No route matched for preloading js assets");
|
|
@@ -54,8 +56,8 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
54
56
|
assets = [...new Map(assets.map(item => [item.attrs.key, item])).values()].filter(asset =>
|
|
55
57
|
import.meta.env.START_ISLANDS
|
|
56
58
|
? false
|
|
57
|
-
: asset.attrs.rel === "modulepreload" &&
|
|
58
|
-
!context.assets.find(a => a.attrs.key === asset.attrs.key)
|
|
59
|
+
: (asset.attrs as JSX.LinkHTMLAttributes<HTMLLinkElement>).rel === "modulepreload" &&
|
|
60
|
+
!context.assets.find((a: Asset) => a.attrs.key === asset.attrs.key)
|
|
59
61
|
);
|
|
60
62
|
});
|
|
61
63
|
|
|
@@ -68,7 +70,7 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
68
70
|
assets={
|
|
69
71
|
<>
|
|
70
72
|
<HydrationScript />
|
|
71
|
-
{context.assets.map(m => renderAsset(m))}
|
|
73
|
+
{context.assets.map((m: any) => renderAsset(m))}
|
|
72
74
|
</>
|
|
73
75
|
}
|
|
74
76
|
scripts={
|
|
@@ -78,9 +80,9 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
78
80
|
type="module"
|
|
79
81
|
async
|
|
80
82
|
src={
|
|
81
|
-
import.meta.env.MANIFEST["client"]
|
|
82
|
-
import.meta.env.MANIFEST["client"]
|
|
83
|
-
]
|
|
83
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
84
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
85
|
+
]!.output.path
|
|
84
86
|
}
|
|
85
87
|
/>
|
|
86
88
|
</>
|
package/server/fetchEvent.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
H3Event,
|
|
3
|
+
HTTPEvent,
|
|
3
4
|
HTTPEventSymbol,
|
|
4
5
|
appendResponseHeader,
|
|
5
6
|
getRequestIP,
|
|
@@ -37,15 +38,15 @@ export function cloneEvent<T extends FetchEvent>(fetchEvent: T): T {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function getFetchEvent(h3Event: H3Event): FetchEvent {
|
|
40
|
-
if (!h3Event[fetchEventSymbol]) {
|
|
41
|
+
if (!(h3Event as any)[fetchEventSymbol]) {
|
|
41
42
|
const fetchEvent = createFetchEvent(h3Event);
|
|
42
|
-
h3Event[fetchEventSymbol] = fetchEvent;
|
|
43
|
+
(h3Event as any)[fetchEventSymbol] = fetchEvent;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
return h3Event[fetchEventSymbol];
|
|
46
|
+
return (h3Event as any)[fetchEventSymbol];
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
export function mergeResponseHeaders(h3Event, headers) {
|
|
49
|
+
export function mergeResponseHeaders(h3Event: HTTPEvent, headers: Headers) {
|
|
49
50
|
for (const [key, value] of headers.entries()) {
|
|
50
51
|
setHeader(h3Event, key, value);
|
|
51
52
|
}
|
package/server/handler.ts
CHANGED
|
@@ -31,7 +31,7 @@ export function createBaseHandler(
|
|
|
31
31
|
return eventHandler({
|
|
32
32
|
onRequest: options.onRequest,
|
|
33
33
|
onBeforeResponse: options.onBeforeResponse,
|
|
34
|
-
handler: (e: H3Event<EventHandlerRequest>
|
|
34
|
+
handler: (e: H3Event<EventHandlerRequest>) => {
|
|
35
35
|
const event = getFetchEvent(e);
|
|
36
36
|
const mode = import.meta.env.START_SSR;
|
|
37
37
|
|
|
@@ -41,7 +41,7 @@ export function createBaseHandler(
|
|
|
41
41
|
if (match) {
|
|
42
42
|
const mod = await match.handler.import();
|
|
43
43
|
const fn = mod[event.request.method];
|
|
44
|
-
(event as APIEvent).params = match.params;
|
|
44
|
+
(event as APIEvent).params = match.params || {};
|
|
45
45
|
// @ts-ignore
|
|
46
46
|
sharedConfig.context = { event };
|
|
47
47
|
const res = await fn(event);
|
|
@@ -61,7 +61,7 @@ export function createBaseHandler(
|
|
|
61
61
|
return fn(context);
|
|
62
62
|
}, options);
|
|
63
63
|
if (context.response && context.response.headers.get("Location")) {
|
|
64
|
-
return sendRedirect(event, context.response.headers.get("Location"));
|
|
64
|
+
return sendRedirect(event, context.response.headers.get("Location")!);
|
|
65
65
|
}
|
|
66
66
|
return html;
|
|
67
67
|
}
|
|
@@ -85,7 +85,7 @@ export function createBaseHandler(
|
|
|
85
85
|
return fn(context);
|
|
86
86
|
}, cloned);
|
|
87
87
|
if (context.response && context.response.headers.get("Location")) {
|
|
88
|
-
return sendRedirect(event, context.response.headers.get("Location"));
|
|
88
|
+
return sendRedirect(event, context.response.headers.get("Location")!);
|
|
89
89
|
}
|
|
90
90
|
if (mode === "async") return stream;
|
|
91
91
|
// fix cloudflare streaming
|
|
@@ -101,7 +101,7 @@ function handleShellCompleteRedirect(context: PageEvent, e: H3Event<EventHandler
|
|
|
101
101
|
return () => {
|
|
102
102
|
if (context.response && context.response.headers.get("Location")) {
|
|
103
103
|
setResponseStatus(e, 302);
|
|
104
|
-
setHeader(e, "Location", context.response.headers.get("Location"));
|
|
104
|
+
setHeader(e, "Location", context.response.headers.get("Location")!);
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
107
|
}
|
package/server/pageEvent.ts
CHANGED
|
@@ -20,17 +20,17 @@ function initFromFlash(ctx: FetchEvent) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export async function createPageEvent(ctx: FetchEvent) {
|
|
23
|
-
const clientManifest = import.meta.env.MANIFEST["client"]
|
|
24
|
-
const serverManifest = import.meta.env.MANIFEST["ssr"]
|
|
23
|
+
const clientManifest = import.meta.env.MANIFEST["client"]!;
|
|
24
|
+
const serverManifest = import.meta.env.MANIFEST["ssr"]!;
|
|
25
25
|
ctx.response.headers.set("Content-Type", "text/html");
|
|
26
26
|
// const prevPath = ctx.request.headers.get("x-solid-referrer");
|
|
27
27
|
// const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
|
|
28
28
|
const pageEvent: PageEvent = Object.assign(ctx, {
|
|
29
29
|
manifest: await clientManifest.json(),
|
|
30
30
|
assets: [
|
|
31
|
-
...(await clientManifest.inputs[clientManifest.handler]
|
|
31
|
+
...(await clientManifest.inputs[clientManifest.handler]!.assets()),
|
|
32
32
|
...(import.meta.env.START_ISLANDS
|
|
33
|
-
? (await serverManifest.inputs[serverManifest.handler]
|
|
33
|
+
? (await serverManifest.inputs[serverManifest.handler]!.assets()).filter(
|
|
34
34
|
s => (s as any).attrs.rel !== "modulepreload"
|
|
35
35
|
)
|
|
36
36
|
: [])
|
package/server/renderAsset.tsx
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import type { Asset } from "./types";
|
|
3
|
+
|
|
1
4
|
const assetMap = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
style: (props: { attrs: JSX.StyleHTMLAttributes<HTMLStyleElement>; children?: JSX.Element }) => (
|
|
6
|
+
<style {...props.attrs}>{props.children}</style>
|
|
7
|
+
),
|
|
8
|
+
link: (props: { attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> }) => <link {...props.attrs} />,
|
|
9
|
+
script: (props: { attrs: JSX.ScriptHTMLAttributes<HTMLScriptElement>; key: string | undefined }) => {
|
|
10
|
+
return props.attrs.src ? (
|
|
11
|
+
<script {...props.attrs} id={props.key}>
|
|
12
|
+
{" "}
|
|
13
|
+
</script>
|
|
14
|
+
) : null;
|
|
15
|
+
}
|
|
11
16
|
};
|
|
12
17
|
|
|
13
|
-
export function renderAsset(asset) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
18
|
+
export function renderAsset(asset: Asset) {
|
|
19
|
+
let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset as any;
|
|
20
|
+
return (assetMap as any)[tag]({ attrs, key, children });
|
|
21
|
+
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
|
+
import type { Component } from "solid-js";
|
|
2
3
|
import { NoHydration, getRequestEvent, ssr } from "solid-js/web";
|
|
3
4
|
import { renderAsset } from "../renderAsset";
|
|
5
|
+
import type { DocumentComponentProps, PageEvent } from "../types";
|
|
4
6
|
|
|
5
7
|
const docType = ssr("<!DOCTYPE html>");
|
|
6
8
|
|
|
7
|
-
export function StartServer(props) {
|
|
8
|
-
const context = getRequestEvent() as
|
|
9
|
+
export function StartServer(props: { document: Component<DocumentComponentProps> }) {
|
|
10
|
+
const context = getRequestEvent() as PageEvent;
|
|
9
11
|
return (
|
|
10
12
|
<NoHydration>
|
|
11
13
|
{docType as unknown as any}
|
|
12
14
|
<props.document
|
|
13
15
|
assets={
|
|
14
16
|
<>
|
|
15
|
-
{context.assets.map(m => renderAsset(m))}
|
|
17
|
+
{context.assets.map((m: any) => renderAsset(m))}
|
|
16
18
|
</>
|
|
17
19
|
}
|
|
18
20
|
scripts={
|
|
@@ -21,9 +23,9 @@ export function StartServer(props) {
|
|
|
21
23
|
<script
|
|
22
24
|
type="module"
|
|
23
25
|
src={
|
|
24
|
-
import.meta.env.MANIFEST["client"]
|
|
25
|
-
import.meta.env.MANIFEST["client"]
|
|
26
|
-
]
|
|
26
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
27
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
28
|
+
]!.output.path
|
|
27
29
|
}
|
|
28
30
|
/>
|
|
29
31
|
</>
|
package/server/spa/handler.ts
CHANGED
|
@@ -9,10 +9,10 @@ export function createHandler(
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export async function createPageEvent(ctx: FetchEvent) {
|
|
12
|
-
const clientManifest = import.meta.env.MANIFEST["client"]
|
|
12
|
+
const clientManifest = import.meta.env.MANIFEST["client"]!;
|
|
13
13
|
const pageEvent: PageEvent = Object.assign(ctx, {
|
|
14
14
|
manifest: await clientManifest.json(),
|
|
15
|
-
assets: [...(await clientManifest.inputs[clientManifest.handler]
|
|
15
|
+
assets: [...(await clientManifest.inputs[clientManifest.handler]!.assets())],
|
|
16
16
|
routes: [],
|
|
17
17
|
// prevUrl: "",
|
|
18
18
|
// mutation: false,
|
package/server/types.ts
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import type { JSX } from "solid-js";
|
|
2
|
-
import {
|
|
2
|
+
import { RequestEvent } from "solid-js/web";
|
|
3
|
+
import { H3Event, HTTPEventSymbol } from "vinxi/http";
|
|
3
4
|
|
|
4
5
|
// export const FETCH_EVENT = "$FETCH";
|
|
5
6
|
|
|
6
7
|
export type DocumentComponentProps = {
|
|
7
8
|
assets: JSX.Element;
|
|
8
9
|
scripts: JSX.Element;
|
|
9
|
-
children
|
|
10
|
-
}
|
|
10
|
+
children?: JSX.Element;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Asset = {
|
|
14
|
+
tag: "style";
|
|
15
|
+
attrs: JSX.StyleHTMLAttributes<HTMLStyleElement> & { key?: string };
|
|
16
|
+
children?: JSX.Element;
|
|
17
|
+
} | {
|
|
18
|
+
tag: "script";
|
|
19
|
+
attrs: JSX.ScriptHTMLAttributes<HTMLScriptElement> & { key?: string };
|
|
20
|
+
} | {
|
|
21
|
+
tag: "link";
|
|
22
|
+
attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> & { key?: string };
|
|
23
|
+
};
|
|
11
24
|
|
|
12
25
|
export type ContextMatches = {
|
|
13
26
|
originalPath: string;
|
|
@@ -24,15 +37,15 @@ export interface ResponseStub {
|
|
|
24
37
|
export interface FetchEvent {
|
|
25
38
|
request: Request;
|
|
26
39
|
response: ResponseStub;
|
|
27
|
-
clientAddress
|
|
40
|
+
clientAddress?: string;
|
|
28
41
|
locals: RequestEventLocals;
|
|
29
|
-
nativeEvent: H3Event
|
|
30
|
-
[HTTPEventSymbol]: H3Event
|
|
42
|
+
nativeEvent: H3Event;
|
|
43
|
+
[HTTPEventSymbol]: H3Event;
|
|
31
44
|
}
|
|
32
45
|
export interface RequestEventLocals {
|
|
33
46
|
[key: string | symbol]: any;
|
|
34
47
|
}
|
|
35
|
-
export interface PageEvent extends
|
|
48
|
+
export interface PageEvent extends RequestEvent {
|
|
36
49
|
manifest: any;
|
|
37
50
|
assets: any;
|
|
38
51
|
routes: any[];
|
package/shared/FileRoutes.tsx
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { getRequestEvent, isServer } from "solid-js/web";
|
|
3
3
|
import lazyRoute from "./lazyRoute";
|
|
4
4
|
|
|
5
|
+
import type { Route } from "vinxi/fs-router";
|
|
5
6
|
import type { PageEvent } from "../server/types";
|
|
6
7
|
import { pageRoutes as routeConfigs } from "./routes";
|
|
7
8
|
|
|
8
9
|
export function createRoutes() {
|
|
9
|
-
function createRoute(route) {
|
|
10
|
+
function createRoute(route: Route) {
|
|
10
11
|
return {
|
|
11
12
|
...route,
|
|
12
13
|
...(route.$$route ? route.$$route.require().route : undefined),
|
|
@@ -28,7 +29,7 @@ export function createRoutes() {
|
|
|
28
29
|
return routes;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
let routes;
|
|
32
|
+
let routes: any[];
|
|
32
33
|
export const FileRoutes = () => {
|
|
33
34
|
return isServer ? (getRequestEvent() as PageEvent).routes : routes || (routes = createRoutes());
|
|
34
35
|
};
|
package/shared/HttpHeader.tsx
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { onCleanup } from "solid-js";
|
|
2
2
|
import { getRequestEvent, isServer } from "solid-js/web";
|
|
3
|
+
import type { PageEvent } from "../server/types";
|
|
3
4
|
|
|
4
5
|
export function HttpHeader(props: { name: string; value: string; append?: boolean }) {
|
|
5
6
|
if (isServer) {
|
|
6
|
-
const event = getRequestEvent();
|
|
7
|
+
const event = getRequestEvent() as PageEvent;
|
|
7
8
|
|
|
8
9
|
if (props.append) event.response.headers.append(props.name, props.value);
|
|
9
10
|
else event.response.headers.set(props.name, props.value);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { onCleanup } from "solid-js";
|
|
2
2
|
import { getRequestEvent, isServer } from "solid-js/web";
|
|
3
|
+
import type { PageEvent } from "../server/types";
|
|
3
4
|
|
|
4
5
|
export function HttpStatusCode(props: { code: number, text?: string }) {
|
|
5
6
|
if (isServer) {
|
|
6
|
-
const event = getRequestEvent();
|
|
7
|
+
const event = getRequestEvent() as PageEvent;
|
|
7
8
|
event.response.status = props.code;
|
|
8
9
|
event.response.statusText = props.text;
|
|
9
10
|
onCleanup(() => !event.nativeEvent.handled && (event.response.status = 200));
|
|
@@ -58,7 +58,7 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
|
|
|
58
58
|
) ,async (value) => {
|
|
59
59
|
const highlighter = await loadHighlighter();
|
|
60
60
|
const lang = props.fileName
|
|
61
|
-
.split(/[#?]/)[0]
|
|
61
|
+
.split(/[#?]/)[0]!
|
|
62
62
|
.split('.')
|
|
63
63
|
.pop()
|
|
64
64
|
?.trim() as BuiltinLanguage;
|
|
@@ -76,7 +76,7 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
|
|
|
76
76
|
const lines = ref.querySelectorAll('span[class="line"]');
|
|
77
77
|
|
|
78
78
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
79
|
-
const el = lines[i];
|
|
79
|
+
const el = lines[i] as HTMLElement;
|
|
80
80
|
if ((props.line - minLine() - 1) === i) {
|
|
81
81
|
el.classList.add('dev-overlay-error-line');
|
|
82
82
|
}
|
|
@@ -6,7 +6,7 @@ import { Portal } from 'solid-js/web';
|
|
|
6
6
|
import { Dialog, DialogOverlay, DialogPanel, Select, SelectOption } from 'terracotta';
|
|
7
7
|
import info from '../../package.json';
|
|
8
8
|
import { CodeView } from './CodeView';
|
|
9
|
-
import { type StackFrameSource
|
|
9
|
+
import { createStackFrame, type StackFrameSource } from './createStackFrame';
|
|
10
10
|
import download from './download';
|
|
11
11
|
import { ArrowLeftIcon, ArrowRightIcon, CameraIcon, DiscordIcon, GithubIcon, RefreshIcon, SolidStartIcon, ViewCompiledIcon, ViewOriginalIcon } from './icons';
|
|
12
12
|
import './styles.css';
|
|
@@ -21,7 +21,7 @@ interface ErrorInfoProps {
|
|
|
21
21
|
|
|
22
22
|
function ErrorInfo(props: ErrorInfoProps): JSX.Element {
|
|
23
23
|
return (
|
|
24
|
-
<Show when={props.error instanceof Error && props.error} keyed fallback={<span>{props.error.toString()}</span>}>
|
|
24
|
+
<Show when={props.error instanceof Error && props.error} keyed fallback={<span>{(props.error as Error).toString()}</span>}>
|
|
25
25
|
{(current) => (
|
|
26
26
|
<span class="dev-overlay-error-info">
|
|
27
27
|
<span class="dev-overlay-error-info-name">{current.name}</span>
|
|
@@ -41,7 +41,7 @@ function getFileName(source: string): string {
|
|
|
41
41
|
try {
|
|
42
42
|
const path = source.startsWith('/') ? new URL(source, 'file://') : new URL(source);
|
|
43
43
|
const paths = path.pathname.split('/');
|
|
44
|
-
return paths[paths.length - 1]
|
|
44
|
+
return paths[paths.length - 1]!;
|
|
45
45
|
} catch (error) {
|
|
46
46
|
return getFileName(`/${source}`);
|
|
47
47
|
}
|
|
@@ -62,7 +62,7 @@ function CodeFallback(): JSX.Element {
|
|
|
62
62
|
function StackFramesContent(props: StackFramesContentProps) {
|
|
63
63
|
const stackframes = ErrorStackParser.parse(props.error);
|
|
64
64
|
|
|
65
|
-
const [selectedFrame, setSelectedFrame] = createSignal(stackframes[0]);
|
|
65
|
+
const [selectedFrame, setSelectedFrame] = createSignal(stackframes[0]!);
|
|
66
66
|
|
|
67
67
|
return (
|
|
68
68
|
<div class="dev-overlay-stack-frames-content">
|
|
@@ -98,10 +98,10 @@ function StackFramesContent(props: StackFramesContentProps) {
|
|
|
98
98
|
<div class="dev-overlay-stack-frame">
|
|
99
99
|
<span class="dev-overlay-stack-frame-function">{current.functionName ?? '<anonymous>'}</span>
|
|
100
100
|
<span class="dev-overlay-stack-frame-file">{getFilePath({
|
|
101
|
-
source: current.getFileName()
|
|
101
|
+
source: current.getFileName()!,
|
|
102
102
|
content: '',
|
|
103
|
-
line: current.getLineNumber()
|
|
104
|
-
column: current.getColumnNumber()
|
|
103
|
+
line: current.getLineNumber()!,
|
|
104
|
+
column: current.getColumnNumber()!,
|
|
105
105
|
name: current.getFunctionName(),
|
|
106
106
|
})}</span>
|
|
107
107
|
</div>
|
|
@@ -204,11 +204,11 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem
|
|
|
204
204
|
url.searchParams.append('labels', 'needs+triage');
|
|
205
205
|
url.searchParams.append('template', 'bug.yml');
|
|
206
206
|
url.searchParams.append('title', `[Bug?]:` + props.errors[truncated() - 1].toString());
|
|
207
|
-
window.open(url, '_blank')
|
|
207
|
+
window.open(url, '_blank')!.focus();
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
function redirectToDiscord() {
|
|
211
|
-
window.open(DISCORD_INVITE, '_blank')
|
|
211
|
+
window.open(DISCORD_INVITE, '_blank')!.focus();
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createMemo, createResource, type Accessor } from "solid-js";
|
|
2
2
|
import getSourceMap from "./get-source-map";
|
|
3
3
|
|
|
4
4
|
export interface StackFrameSource {
|
|
@@ -19,7 +19,7 @@ function getActualFileSource(path: string): string {
|
|
|
19
19
|
export function createStackFrame(
|
|
20
20
|
stackframe: StackFrame,
|
|
21
21
|
isCompiled: () => boolean,
|
|
22
|
-
)
|
|
22
|
+
) {
|
|
23
23
|
const [data] = createResource(
|
|
24
24
|
() => ({
|
|
25
25
|
fileName: stackframe.fileName,
|
|
@@ -45,14 +45,13 @@ export function createStackFrame(
|
|
|
45
45
|
},
|
|
46
46
|
);
|
|
47
47
|
|
|
48
|
-
const info = createMemo
|
|
48
|
+
const info = createMemo(() => {
|
|
49
49
|
const current = data();
|
|
50
50
|
if (!current) {
|
|
51
51
|
return undefined;
|
|
52
52
|
}
|
|
53
53
|
const { source, content, sourceMap } = current;
|
|
54
54
|
|
|
55
|
-
|
|
56
55
|
if (!isCompiled() && source.line && source.column && sourceMap) {
|
|
57
56
|
const result = sourceMap.originalPositionFor({
|
|
58
57
|
line: source.line,
|
|
@@ -62,7 +61,7 @@ export function createStackFrame(
|
|
|
62
61
|
return {
|
|
63
62
|
...result,
|
|
64
63
|
content: sourceMap.sourceContentFor(result.source),
|
|
65
|
-
};
|
|
64
|
+
} as StackFrameSource;
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
return {
|
|
@@ -71,8 +70,8 @@ export function createStackFrame(
|
|
|
71
70
|
column: source.column,
|
|
72
71
|
name: source.functionName,
|
|
73
72
|
content,
|
|
74
|
-
};
|
|
73
|
+
} as StackFrameSource;
|
|
75
74
|
});
|
|
76
75
|
|
|
77
|
-
return info
|
|
76
|
+
return info as Accessor<StackFrameSource>;
|
|
78
77
|
}
|
|
@@ -11,7 +11,7 @@ export default async function getSourceMap(
|
|
|
11
11
|
const lines = content.split('\n');
|
|
12
12
|
let sourceMapUrl: string | undefined;
|
|
13
13
|
for (let i = lines.length - 1; i >= 0 && !sourceMapUrl; i--) {
|
|
14
|
-
const result = lines[i]
|
|
14
|
+
const result = lines[i]!.match(SOURCEMAP_REGEX);
|
|
15
15
|
if (result) {
|
|
16
16
|
sourceMapUrl = result[1];
|
|
17
17
|
}
|
package/shared/lazyRoute.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/// <reference types="vinxi/types/client" />
|
|
2
|
-
import { createComponent, lazy, onCleanup } from "solid-js";
|
|
3
|
-
import { appendStyles, cleanupStyles,
|
|
2
|
+
import { createComponent, lazy, onCleanup, type Component, type JSX } from "solid-js";
|
|
3
|
+
import { appendStyles, cleanupStyles, preloadStyles, updateStyles } from "vinxi/css";
|
|
4
4
|
|
|
5
5
|
import { renderAsset } from "../server/renderAsset";
|
|
6
|
+
import { Asset } from "../server/types";
|
|
6
7
|
|
|
7
|
-
export default function lazyRoute(component, clientManifest, serverManifest, exported = "default") {
|
|
8
|
+
export default function lazyRoute<T>(component: any, clientManifest: any, serverManifest: any, exported = "default") {
|
|
8
9
|
return lazy(async () => {
|
|
9
10
|
if (import.meta.env.DEV) {
|
|
10
11
|
let manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
@@ -13,7 +14,7 @@ export default function lazyRoute(component, clientManifest, serverManifest, exp
|
|
|
13
14
|
if (!mod[exported]) console.error(`Module ${component.src} does not export ${exported}`);
|
|
14
15
|
const Component = mod[exported];
|
|
15
16
|
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
16
|
-
const styles = assets.filter(asset => asset.tag === "style");
|
|
17
|
+
const styles = assets.filter((asset: Asset) => asset.tag === "style");
|
|
17
18
|
|
|
18
19
|
if (typeof window !== "undefined" && import.meta.hot) {
|
|
19
20
|
import.meta.hot.on("css-update", data => {
|
|
@@ -21,7 +22,7 @@ export default function lazyRoute(component, clientManifest, serverManifest, exp
|
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
const Comp = props => {
|
|
25
|
+
const Comp: Component<T> = props => {
|
|
25
26
|
if (typeof window !== "undefined") {
|
|
26
27
|
appendStyles(styles);
|
|
27
28
|
}
|
|
@@ -32,7 +33,7 @@ export default function lazyRoute(component, clientManifest, serverManifest, exp
|
|
|
32
33
|
cleanupStyles(styles);
|
|
33
34
|
}
|
|
34
35
|
});
|
|
35
|
-
return [...assets.map(asset => renderAsset(asset)), createComponent(Component, props)];
|
|
36
|
+
return [...assets.map((asset: Asset) => renderAsset(asset)), createComponent(Component, props)];
|
|
36
37
|
};
|
|
37
38
|
return { default: Comp };
|
|
38
39
|
} else {
|
|
@@ -40,13 +41,13 @@ export default function lazyRoute(component, clientManifest, serverManifest, exp
|
|
|
40
41
|
const Component = mod[exported];
|
|
41
42
|
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
42
43
|
const styles = assets.filter(
|
|
43
|
-
asset => asset.tag === "style" || asset.attrs.rel === "stylesheet"
|
|
44
|
+
(asset: Asset) => asset.tag === "style" || (asset.attrs as JSX.LinkHTMLAttributes<HTMLLinkElement>).rel === "stylesheet"
|
|
44
45
|
);
|
|
45
46
|
if (typeof window !== "undefined") {
|
|
46
47
|
preloadStyles(styles);
|
|
47
48
|
}
|
|
48
|
-
const Comp = props => {
|
|
49
|
-
return [...styles.map(asset => renderAsset(asset)), createComponent(Component, props)];
|
|
49
|
+
const Comp: Component<T> = props => {
|
|
50
|
+
return [...styles.map((asset: Asset) => renderAsset(asset)), createComponent(Component, props)];
|
|
50
51
|
};
|
|
51
52
|
return { default: Comp };
|
|
52
53
|
}
|
package/shared/routes.ts
CHANGED
|
@@ -6,6 +6,11 @@ interface Route {
|
|
|
6
6
|
id: string;
|
|
7
7
|
children?: Route[];
|
|
8
8
|
$component?: any;
|
|
9
|
+
$GET?: any;
|
|
10
|
+
$POST?: any;
|
|
11
|
+
$PUT?: any;
|
|
12
|
+
$PATCH?: any;
|
|
13
|
+
$DELETE?: any;
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
declare module "vinxi/routes" {
|
|
@@ -43,7 +48,7 @@ function defineRoutes(fileRoutes: Route[]) {
|
|
|
43
48
|
|
|
44
49
|
return fileRoutes
|
|
45
50
|
.sort((a, b) => a.path.length - b.path.length)
|
|
46
|
-
.reduce((prevRoutes, route) => {
|
|
51
|
+
.reduce((prevRoutes: Route[], route) => {
|
|
47
52
|
return processRoute(prevRoutes, route, route.path, route.path);
|
|
48
53
|
}, []);
|
|
49
54
|
}
|
|
@@ -73,7 +78,7 @@ const router = createRouter({
|
|
|
73
78
|
}
|
|
74
79
|
if (memo[path]) {
|
|
75
80
|
throw new Error(
|
|
76
|
-
`Duplicate API routes for "${path}" found at "${memo[path]
|
|
81
|
+
`Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${route.path}"`
|
|
77
82
|
);
|
|
78
83
|
}
|
|
79
84
|
memo[path] = { route };
|