@solidjs/start 0.7.1 → 0.7.3
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 +42 -0
- package/package.json +22 -23
- 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
package/config/server-runtime.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { deserialize, toJSONAsync } from "seroval";
|
|
2
|
-
import {
|
|
3
|
-
CustomEventPlugin,
|
|
4
|
-
DOMExceptionPlugin,
|
|
5
|
-
EventPlugin,
|
|
6
|
-
FormDataPlugin,
|
|
7
|
-
HeadersPlugin,
|
|
8
|
-
ReadableStreamPlugin,
|
|
9
|
-
RequestPlugin,
|
|
10
|
-
ResponsePlugin,
|
|
11
|
-
URLPlugin,
|
|
12
|
-
URLSearchParamsPlugin
|
|
13
|
-
} from "seroval-plugins/web";
|
|
14
|
-
import { type Component } from "solid-js";
|
|
15
|
-
import { createIslandReference } from "../server/islands";
|
|
16
|
-
|
|
17
|
-
class SerovalChunkReader {
|
|
18
|
-
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
19
|
-
buffer: string;
|
|
20
|
-
done: boolean;
|
|
21
|
-
constructor(stream: ReadableStream<Uint8Array>) {
|
|
22
|
-
this.reader = stream.getReader();
|
|
23
|
-
this.buffer = "";
|
|
24
|
-
this.done = false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async readChunk() {
|
|
28
|
-
// if there's no chunk, read again
|
|
29
|
-
const chunk = await this.reader.read();
|
|
30
|
-
if (!chunk.done) {
|
|
31
|
-
// repopulate the buffer
|
|
32
|
-
this.buffer += new TextDecoder().decode(chunk.value);
|
|
33
|
-
} else {
|
|
34
|
-
this.done = true;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async next(): Promise<any> {
|
|
39
|
-
// Check if the buffer is empty
|
|
40
|
-
if (this.buffer === "") {
|
|
41
|
-
// if we are already done...
|
|
42
|
-
if (this.done) {
|
|
43
|
-
return {
|
|
44
|
-
done: true,
|
|
45
|
-
value: undefined
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
// Otherwise, read a new chunk
|
|
49
|
-
await this.readChunk();
|
|
50
|
-
return await this.next();
|
|
51
|
-
}
|
|
52
|
-
// Read the "byte header"
|
|
53
|
-
// The byte header tells us how big the expected data is
|
|
54
|
-
// so we know how much data we should wait before we
|
|
55
|
-
// deserialize the data
|
|
56
|
-
const bytes = Number.parseInt(this.buffer.substring(1, 11), 16); // ;0x00000000;
|
|
57
|
-
// Check if the buffer has enough bytes to be parsed
|
|
58
|
-
while (bytes > this.buffer.length - 12) {
|
|
59
|
-
// If it's not enough, and the reader is done
|
|
60
|
-
// then the chunk is invalid.
|
|
61
|
-
if (this.done) {
|
|
62
|
-
throw new Error("Malformed server function stream.");
|
|
63
|
-
}
|
|
64
|
-
// Otherwise, we read more chunks
|
|
65
|
-
await this.readChunk();
|
|
66
|
-
}
|
|
67
|
-
// Extract the exact chunk as defined by the byte header
|
|
68
|
-
const partial = this.buffer.substring(12, 12 + bytes);
|
|
69
|
-
// The rest goes to the buffer
|
|
70
|
-
this.buffer = this.buffer.substring(12 + bytes);
|
|
71
|
-
// Deserialize the chunk
|
|
72
|
-
return {
|
|
73
|
-
done: false,
|
|
74
|
-
value: deserialize(partial)
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async drain() {
|
|
79
|
-
while (true) {
|
|
80
|
-
const result = await this.next();
|
|
81
|
-
if (result.done) {
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async function deserializeStream(id: string, response: Response) {
|
|
89
|
-
if (!response.body) {
|
|
90
|
-
throw new Error("missing body");
|
|
91
|
-
}
|
|
92
|
-
const reader = new SerovalChunkReader(response.body);
|
|
93
|
-
|
|
94
|
-
const result = await reader.next();
|
|
95
|
-
|
|
96
|
-
if (!result.done) {
|
|
97
|
-
reader.drain().then(
|
|
98
|
-
() => {
|
|
99
|
-
// @ts-ignore
|
|
100
|
-
delete $R[id];
|
|
101
|
-
},
|
|
102
|
-
() => {
|
|
103
|
-
// no-op
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return result.value;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let INSTANCE = 0;
|
|
112
|
-
|
|
113
|
-
function createRequest(base: string, id: string, instance: string, options: RequestInit) {
|
|
114
|
-
return fetch(base, {
|
|
115
|
-
method: "POST",
|
|
116
|
-
...options,
|
|
117
|
-
headers: {
|
|
118
|
-
...options.headers,
|
|
119
|
-
"X-Server-Id": id,
|
|
120
|
-
"X-Server-Instance": instance
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async function fetchServerFunction(
|
|
126
|
-
base: string,
|
|
127
|
-
id: string,
|
|
128
|
-
options: Omit<RequestInit, "body">,
|
|
129
|
-
args: any[]
|
|
130
|
-
) {
|
|
131
|
-
const instance = `server-fn:${INSTANCE++}`;
|
|
132
|
-
const response = await (args.length === 0
|
|
133
|
-
? createRequest(base, id, instance, options)
|
|
134
|
-
: args.length === 1 && args[0] instanceof FormData
|
|
135
|
-
? createRequest(base, id, instance, { ...options, body: args[0] })
|
|
136
|
-
: createRequest(base, id, instance, {
|
|
137
|
-
...options,
|
|
138
|
-
body: JSON.stringify(
|
|
139
|
-
await Promise.resolve(
|
|
140
|
-
toJSONAsync(args, {
|
|
141
|
-
plugins: [
|
|
142
|
-
CustomEventPlugin,
|
|
143
|
-
DOMExceptionPlugin,
|
|
144
|
-
EventPlugin,
|
|
145
|
-
FormDataPlugin,
|
|
146
|
-
HeadersPlugin,
|
|
147
|
-
ReadableStreamPlugin,
|
|
148
|
-
RequestPlugin,
|
|
149
|
-
ResponsePlugin,
|
|
150
|
-
URLSearchParamsPlugin,
|
|
151
|
-
URLPlugin
|
|
152
|
-
]
|
|
153
|
-
})
|
|
154
|
-
)
|
|
155
|
-
),
|
|
156
|
-
headers: { ...options.headers, "Content-Type": "application/json" }
|
|
157
|
-
}));
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
response.headers.get("Location") ||
|
|
161
|
-
response.headers.get("X-Revalidate") ||
|
|
162
|
-
response.headers.get("X-Single-Flight")
|
|
163
|
-
) {
|
|
164
|
-
if (response.body) {
|
|
165
|
-
/* @ts-ignore-next-line */
|
|
166
|
-
response.customBody = () => {
|
|
167
|
-
return deserializeStream(instance, response);
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
return response;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const contentType = response.headers.get("Content-Type");
|
|
174
|
-
let result;
|
|
175
|
-
if (contentType && contentType.startsWith("text/plain")) {
|
|
176
|
-
result = await response.text();
|
|
177
|
-
} else if (contentType && contentType.startsWith("application/json")) {
|
|
178
|
-
result = await response.json();
|
|
179
|
-
} else {
|
|
180
|
-
result = await deserializeStream(instance, response);
|
|
181
|
-
}
|
|
182
|
-
if (response.headers.has("X-Error")) {
|
|
183
|
-
throw result;
|
|
184
|
-
}
|
|
185
|
-
return result;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export function createServerReference(fn: Function, id: string, name: string) {
|
|
189
|
-
const baseURL = import.meta.env.SERVER_BASE_URL;
|
|
190
|
-
return new Proxy(fn, {
|
|
191
|
-
get(target, prop, receiver) {
|
|
192
|
-
if (prop === "url") {
|
|
193
|
-
return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
|
|
194
|
-
}
|
|
195
|
-
if (prop === "GET") {
|
|
196
|
-
return receiver.withOptions({ method: "GET" });
|
|
197
|
-
}
|
|
198
|
-
if (prop === "withOptions") {
|
|
199
|
-
const url = `${baseURL}/_server/?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`
|
|
200
|
-
return (options: RequestInit) => {
|
|
201
|
-
const fn = (...args: any[]) => {
|
|
202
|
-
const encodeArgs = options.method && options.method.toUpperCase() === "GET";
|
|
203
|
-
return fetchServerFunction(
|
|
204
|
-
encodeArgs
|
|
205
|
-
? url + (args.length ? `&args=${JSON.stringify(args)}` : "")
|
|
206
|
-
: `${baseURL}/_server`,
|
|
207
|
-
`${id}#${name}`,
|
|
208
|
-
options,
|
|
209
|
-
encodeArgs ? [] : args
|
|
210
|
-
);
|
|
211
|
-
};
|
|
212
|
-
fn.url = url;
|
|
213
|
-
return fn;
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
apply(target, thisArg, args) {
|
|
218
|
-
return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, {}, args);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export function createClientReference(Component: Component<any>, id: string, name: string) {
|
|
224
|
-
if (typeof Component === "function") {
|
|
225
|
-
return createIslandReference(Component, id, name);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return Component;
|
|
229
|
-
}
|
package/middleware/index.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HTTPEvent,
|
|
3
|
-
defineMiddleware,
|
|
4
|
-
sendWebResponse
|
|
5
|
-
} from "vinxi/http";
|
|
6
|
-
import { getFetchEvent } from "../server/fetchEvent";
|
|
7
|
-
import type { FetchEvent } from "../server/types";
|
|
8
|
-
|
|
9
|
-
/** Function responsible for receiving an observable [operation]{@link Operation} and returning a [result]{@link OperationResult}. */
|
|
10
|
-
|
|
11
|
-
export type MiddlewareFn = (event: FetchEvent) => Promise<unknown> | unknown;
|
|
12
|
-
/** This composes an array of Exchanges into a single ExchangeIO function */
|
|
13
|
-
|
|
14
|
-
export type RequestMiddleware = (event: FetchEvent) => Response | Promise<Response> | void | Promise<void>;
|
|
15
|
-
|
|
16
|
-
// copy-pasted from h3/dist/index.d.ts
|
|
17
|
-
type EventHandlerResponse<T = any> = T | Promise<T>;
|
|
18
|
-
type ResponseMiddlewareResponseParam = { body?: Awaited<EventHandlerResponse> };
|
|
19
|
-
|
|
20
|
-
export type ResponseMiddleware = (
|
|
21
|
-
event: FetchEvent,
|
|
22
|
-
response: ResponseMiddlewareResponseParam
|
|
23
|
-
) => Response | Promise<Response> | void | Promise<void>;
|
|
24
|
-
|
|
25
|
-
function wrapRequestMiddleware(onRequest: RequestMiddleware) {
|
|
26
|
-
return async (h3Event: HTTPEvent) => {
|
|
27
|
-
const fetchEvent = getFetchEvent(h3Event);
|
|
28
|
-
const response = await onRequest(fetchEvent);
|
|
29
|
-
if (!response) {
|
|
30
|
-
return;
|
|
31
|
-
} else {
|
|
32
|
-
sendWebResponse(h3Event, response);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function wrapResponseMiddleware(onBeforeResponse: ResponseMiddleware) {
|
|
38
|
-
return async (h3Event: HTTPEvent, response: ResponseMiddlewareResponseParam) => {
|
|
39
|
-
const fetchEvent = getFetchEvent(h3Event);
|
|
40
|
-
const mwResponse = await onBeforeResponse(fetchEvent, response);
|
|
41
|
-
if (!mwResponse) {
|
|
42
|
-
return;
|
|
43
|
-
} else {
|
|
44
|
-
sendWebResponse(h3Event, mwResponse);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function createMiddleware({
|
|
50
|
-
onRequest,
|
|
51
|
-
onBeforeResponse
|
|
52
|
-
}: {
|
|
53
|
-
onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
|
|
54
|
-
onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined;
|
|
55
|
-
}) {
|
|
56
|
-
return defineMiddleware({
|
|
57
|
-
onRequest:
|
|
58
|
-
typeof onRequest === "function"
|
|
59
|
-
? wrapRequestMiddleware(onRequest)
|
|
60
|
-
: Array.isArray(onRequest)
|
|
61
|
-
? onRequest.map(wrapRequestMiddleware)
|
|
62
|
-
: undefined,
|
|
63
|
-
onBeforeResponse:
|
|
64
|
-
typeof onBeforeResponse === "function"
|
|
65
|
-
? wrapResponseMiddleware(onBeforeResponse)
|
|
66
|
-
: Array.isArray(onBeforeResponse)
|
|
67
|
-
? onBeforeResponse.map(wrapResponseMiddleware)
|
|
68
|
-
: undefined
|
|
69
|
-
});
|
|
70
|
-
}
|
package/router/FileRoutes.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/* @refresh skip */
|
|
2
|
-
import { getRequestEvent, isServer } from "solid-js/web";
|
|
3
|
-
import lazyRoute from "./lazyRoute";
|
|
4
|
-
|
|
5
|
-
import type { Route } from "vinxi/fs-router";
|
|
6
|
-
import type { PageEvent } from "../server/types";
|
|
7
|
-
import { pageRoutes as routeConfigs } from "./routes";
|
|
8
|
-
|
|
9
|
-
export function createRoutes() {
|
|
10
|
-
function createRoute(route: Route) {
|
|
11
|
-
return {
|
|
12
|
-
...route,
|
|
13
|
-
...(route.$$route ? route.$$route.require().route : undefined),
|
|
14
|
-
info: {
|
|
15
|
-
...(route.$$route ? route.$$route.require().route.info : {}),
|
|
16
|
-
filesystem: true
|
|
17
|
-
},
|
|
18
|
-
component: lazyRoute(
|
|
19
|
-
route.$component,
|
|
20
|
-
import.meta.env.START_ISLANDS
|
|
21
|
-
? import.meta.env.MANIFEST["ssr"]
|
|
22
|
-
: import.meta.env.MANIFEST["client"],
|
|
23
|
-
import.meta.env.MANIFEST["ssr"]
|
|
24
|
-
),
|
|
25
|
-
children: route.children ? route.children.map(createRoute) : undefined
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const routes = routeConfigs.map(createRoute);
|
|
29
|
-
return routes;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let routes: any[];
|
|
33
|
-
export const FileRoutes = isServer
|
|
34
|
-
? () => (getRequestEvent() as PageEvent).routes
|
|
35
|
-
: () => routes || (routes = createRoutes());
|
package/router/lazyRoute.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/// <reference types="vinxi/types/client" />
|
|
2
|
-
import { createComponent, lazy, onCleanup, type Component, type JSX } from "solid-js";
|
|
3
|
-
import { appendStyles, cleanupStyles, preloadStyles, updateStyles } from "vinxi/css";
|
|
4
|
-
|
|
5
|
-
import { renderAsset } from "../server/renderAsset";
|
|
6
|
-
import { Asset } from "../server/types";
|
|
7
|
-
|
|
8
|
-
export default function lazyRoute<T>(component: any, clientManifest: any, serverManifest: any, exported = "default") {
|
|
9
|
-
return lazy(async () => {
|
|
10
|
-
if (import.meta.env.DEV) {
|
|
11
|
-
let manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
12
|
-
|
|
13
|
-
const mod = await manifest.inputs[component.src].import();
|
|
14
|
-
if (!mod[exported]) console.error(`Module ${component.src} does not export ${exported}`);
|
|
15
|
-
const Component = mod[exported];
|
|
16
|
-
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
17
|
-
const styles = assets.filter((asset: Asset) => asset.tag === "style");
|
|
18
|
-
|
|
19
|
-
if (typeof window !== "undefined" && import.meta.hot) {
|
|
20
|
-
import.meta.hot.on("css-update", data => {
|
|
21
|
-
updateStyles(styles, data);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const Comp: Component<T> = props => {
|
|
26
|
-
if (typeof window !== "undefined") {
|
|
27
|
-
appendStyles(styles);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
onCleanup(() => {
|
|
31
|
-
if (typeof window !== "undefined") {
|
|
32
|
-
// remove style tags added by vite when a CSS file is imported
|
|
33
|
-
cleanupStyles(styles);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
return [...assets.map((asset: Asset) => renderAsset(asset)), createComponent(Component, props)];
|
|
37
|
-
};
|
|
38
|
-
return { default: Comp };
|
|
39
|
-
} else {
|
|
40
|
-
const mod = await component.import();
|
|
41
|
-
const Component = mod[exported];
|
|
42
|
-
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
43
|
-
const styles = assets.filter(
|
|
44
|
-
(asset: Asset) => asset.tag === "style" || (asset.attrs as JSX.LinkHTMLAttributes<HTMLLinkElement>).rel === "stylesheet"
|
|
45
|
-
);
|
|
46
|
-
if (typeof window !== "undefined") {
|
|
47
|
-
preloadStyles(styles);
|
|
48
|
-
}
|
|
49
|
-
const Comp: Component<T> = props => {
|
|
50
|
-
return [...styles.map((asset: Asset) => renderAsset(asset)), createComponent(Component, props)];
|
|
51
|
-
};
|
|
52
|
-
return { default: Comp };
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
package/router/routes.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { createRouter } from "radix3";
|
|
2
|
-
import fileRoutes from "vinxi/routes";
|
|
3
|
-
|
|
4
|
-
interface Route {
|
|
5
|
-
path: string;
|
|
6
|
-
id: string;
|
|
7
|
-
children?: Route[];
|
|
8
|
-
$component?: any;
|
|
9
|
-
$GET?: any;
|
|
10
|
-
$POST?: any;
|
|
11
|
-
$PUT?: any;
|
|
12
|
-
$PATCH?: any;
|
|
13
|
-
$DELETE?: any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
declare module "vinxi/routes" {
|
|
17
|
-
export interface Register {
|
|
18
|
-
route: {
|
|
19
|
-
path: string;
|
|
20
|
-
children?: Route[];
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const pageRoutes = defineRoutes(
|
|
26
|
-
(fileRoutes as unknown as Route[]).filter(o => o.$component)
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
function defineRoutes(fileRoutes: Route[]) {
|
|
30
|
-
function processRoute(routes: Route[], route: Route, id: string, full: string) {
|
|
31
|
-
const parentRoute = Object.values(routes).find(o => {
|
|
32
|
-
return id.startsWith(o.id + "/");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
if (!parentRoute) {
|
|
36
|
-
routes.push({ ...route, id, path: id.replace(/\/\([^)/]+\)/g, "").replace(/\./g, "/") });
|
|
37
|
-
return routes;
|
|
38
|
-
}
|
|
39
|
-
processRoute(
|
|
40
|
-
parentRoute.children || (parentRoute.children = []),
|
|
41
|
-
route,
|
|
42
|
-
id.slice(parentRoute.id.length),
|
|
43
|
-
full
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
return routes;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return fileRoutes
|
|
50
|
-
.sort((a, b) => a.path.length - b.path.length)
|
|
51
|
-
.reduce((prevRoutes: Route[], route) => {
|
|
52
|
-
return processRoute(prevRoutes, route, route.path, route.path);
|
|
53
|
-
}, []);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function matchAPIRoute(path: string, method: string) {
|
|
57
|
-
const match = router.lookup(path);
|
|
58
|
-
if (match) {
|
|
59
|
-
const handler = match.route[`$${method}`];
|
|
60
|
-
if (handler === undefined) return;
|
|
61
|
-
return {
|
|
62
|
-
handler,
|
|
63
|
-
params: match.params
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function containsHTTP(route: Route) {
|
|
69
|
-
return route["$GET"] || route["$POST"] || route["$PUT"] || route["$PATCH"] || route["$DELETE"];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const router = createRouter({
|
|
73
|
-
routes: (fileRoutes as unknown as Route[]).reduce((memo, route) => {
|
|
74
|
-
if (!containsHTTP(route)) return memo;
|
|
75
|
-
let path = route.path.replace(/\(.*\)\/?/g, "").replace(/\*([^/]*)/g, (_, m) => `**:${m}`);
|
|
76
|
-
if (/:[^/]*\?/g.test(path)) {
|
|
77
|
-
throw new Error(`Optional parameters are not supported in API routes: ${path}`);
|
|
78
|
-
}
|
|
79
|
-
if (memo[path]) {
|
|
80
|
-
throw new Error(
|
|
81
|
-
`Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${route.path}"`
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
memo[path] = { route };
|
|
85
|
-
return memo;
|
|
86
|
-
}, {} as Record<string, { route: Route }>)
|
|
87
|
-
});
|
package/server/StartServer.tsx
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// @refresh skip
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
import App from "#start/app";
|
|
4
|
-
import type { Component, JSX } from "solid-js";
|
|
5
|
-
import {
|
|
6
|
-
Hydration,
|
|
7
|
-
HydrationScript,
|
|
8
|
-
NoHydration,
|
|
9
|
-
getRequestEvent,
|
|
10
|
-
ssr,
|
|
11
|
-
useAssets
|
|
12
|
-
} from "solid-js/web";
|
|
13
|
-
import { ErrorBoundary } from "../shared/ErrorBoundary";
|
|
14
|
-
import { renderAsset } from "./renderAsset";
|
|
15
|
-
import type { Asset, DocumentComponentProps, PageEvent } from "./types";
|
|
16
|
-
|
|
17
|
-
const docType = ssr("<!DOCTYPE html>");
|
|
18
|
-
|
|
19
|
-
function matchRoute(matches: any[], routes: any[], matched = []): any[] | undefined {
|
|
20
|
-
for (let i = 0; i < routes.length; i++) {
|
|
21
|
-
const segment = routes[i];
|
|
22
|
-
if (segment.path !== matches[0].path) continue;
|
|
23
|
-
let next: any = [...matched, segment];
|
|
24
|
-
if (segment.children) {
|
|
25
|
-
const nextMatches = matches.slice(1);
|
|
26
|
-
if (nextMatches.length === 0) continue;
|
|
27
|
-
next = matchRoute(nextMatches, segment.children, next);
|
|
28
|
-
if (!next) continue;
|
|
29
|
-
}
|
|
30
|
-
return next;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function StartServer(props: { document: Component<DocumentComponentProps> }) {
|
|
35
|
-
const context = getRequestEvent() as PageEvent;
|
|
36
|
-
// @ts-ignore
|
|
37
|
-
const nonce = context.nonce;
|
|
38
|
-
|
|
39
|
-
let assets: Asset[] = [];
|
|
40
|
-
Promise.resolve().then(async () => {
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
if (context.router && context.router.matches) {
|
|
43
|
-
// @ts-ignore
|
|
44
|
-
const matches = [...context.router.matches];
|
|
45
|
-
while (matches.length && (!matches[0].info || !matches[0].info.filesystem)) matches.shift();
|
|
46
|
-
const matched = matches.length && matchRoute(matches, context.routes);
|
|
47
|
-
if (matched) {
|
|
48
|
-
for (let i = 0; i < matched.length; i++) {
|
|
49
|
-
const segment = matched[i];
|
|
50
|
-
const part = import.meta.env.MANIFEST[import.meta.env.START_ISLANDS ? "ssr" : "client"]!
|
|
51
|
-
.inputs[segment["$component"].src]!;
|
|
52
|
-
const asset = (await part.assets()) as any;
|
|
53
|
-
assets.push.apply(assets, asset);
|
|
54
|
-
}
|
|
55
|
-
} else console.warn("No route matched for preloading js assets");
|
|
56
|
-
}
|
|
57
|
-
// dedupe assets
|
|
58
|
-
assets = [...new Map(assets.map(item => [item.attrs.key, item])).values()].filter(asset =>
|
|
59
|
-
import.meta.env.START_ISLANDS
|
|
60
|
-
? false
|
|
61
|
-
: (asset.attrs as JSX.LinkHTMLAttributes<HTMLLinkElement>).rel === "modulepreload" &&
|
|
62
|
-
!context.assets.find((a: Asset) => a.attrs.key === asset.attrs.key)
|
|
63
|
-
);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
useAssets(() => (assets.length ? assets.map(m => renderAsset(m)) : undefined));
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<NoHydration>
|
|
70
|
-
{docType as unknown as any}
|
|
71
|
-
<props.document
|
|
72
|
-
assets={
|
|
73
|
-
<>
|
|
74
|
-
<HydrationScript />
|
|
75
|
-
{context.assets.map((m: any) => renderAsset(m))}
|
|
76
|
-
</>
|
|
77
|
-
}
|
|
78
|
-
scripts={
|
|
79
|
-
nonce ? (
|
|
80
|
-
<>
|
|
81
|
-
<script
|
|
82
|
-
nonce={nonce}
|
|
83
|
-
innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}
|
|
84
|
-
/>
|
|
85
|
-
<script
|
|
86
|
-
type="module"
|
|
87
|
-
nonce={nonce}
|
|
88
|
-
async
|
|
89
|
-
src={
|
|
90
|
-
import.meta.env.MANIFEST["client"]!.inputs[
|
|
91
|
-
import.meta.env.MANIFEST["client"]!.handler
|
|
92
|
-
]!.output.path
|
|
93
|
-
}
|
|
94
|
-
/>
|
|
95
|
-
</>
|
|
96
|
-
) : (
|
|
97
|
-
<>
|
|
98
|
-
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`} />
|
|
99
|
-
<script
|
|
100
|
-
type="module"
|
|
101
|
-
async
|
|
102
|
-
src={
|
|
103
|
-
import.meta.env.MANIFEST["client"]!.inputs[
|
|
104
|
-
import.meta.env.MANIFEST["client"]!.handler
|
|
105
|
-
]!.output.path
|
|
106
|
-
}
|
|
107
|
-
/>
|
|
108
|
-
</>
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
>
|
|
112
|
-
{!import.meta.env.START_ISLANDS ? (
|
|
113
|
-
<Hydration>
|
|
114
|
-
<ErrorBoundary>
|
|
115
|
-
<App />
|
|
116
|
-
</ErrorBoundary>
|
|
117
|
-
</Hydration>
|
|
118
|
-
) : (
|
|
119
|
-
<ErrorBoundary>
|
|
120
|
-
<App />
|
|
121
|
-
</ErrorBoundary>
|
|
122
|
-
)}
|
|
123
|
-
</props.document>
|
|
124
|
-
</NoHydration>
|
|
125
|
-
);
|
|
126
|
-
}
|