@solidjs/start 0.5.10 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/index.d.ts +16 -21
- package/config/index.js +146 -128
- package/config/server-fns-runtime.ts +1 -1
- package/config/server-runtime.ts +4 -3
- package/env.d.ts +2 -5
- package/package.json +5 -5
- package/server/StartServer.tsx +35 -15
- package/server/fetchEvent.ts +1 -2
- package/server/handler.ts +10 -18
- package/server/spa/StartServer.tsx +32 -17
- package/server/spa/handler.ts +3 -3
- package/server/types.ts +8 -0
- package/shared/ErrorBoundary.tsx +11 -2
package/config/index.d.ts
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
import { AppOptions } from "vinxi";
|
|
2
|
-
import {
|
|
1
|
+
import type { AppOptions } from "vinxi";
|
|
2
|
+
import type { CustomizableConfig } from "vinxi/dist/types/lib/vite-dev";
|
|
3
3
|
import type { Options } from "vite-plugin-solid";
|
|
4
4
|
|
|
5
|
+
type SolidStartInlineConfig = {
|
|
6
|
+
ssr?: boolean;
|
|
7
|
+
solid?: Options;
|
|
8
|
+
extensions?: string[];
|
|
9
|
+
server?: AppOptions["server"];
|
|
10
|
+
appRoot?: string;
|
|
11
|
+
middleware?: string;
|
|
12
|
+
islands?: boolean;
|
|
13
|
+
devOverlay?: boolean;
|
|
14
|
+
vite?:
|
|
15
|
+
| CustomizableConfig
|
|
16
|
+
| ((options: { router: "server" | "client" | "server-function" }) => CustomizableConfig);
|
|
17
|
+
};
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
start?: {
|
|
8
|
-
/**
|
|
9
|
-
* true: streaming mode
|
|
10
|
-
* false: csr only
|
|
11
|
-
* async: ssr is in async mode
|
|
12
|
-
* sync: ssr is in sync mode
|
|
13
|
-
*/
|
|
14
|
-
ssr?: boolean | "async" | "sync",
|
|
15
|
-
solid?: Options,
|
|
16
|
-
extensions?: string[],
|
|
17
|
-
server?: AppOptions['server'],
|
|
18
|
-
appRoot?: string,
|
|
19
|
-
middleware?: string,
|
|
20
|
-
islands?: boolean
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export declare function defineConfig(baseConfig?: SolidStartInlineConfig)
|
|
19
|
+
export declare function defineConfig(baseConfig?: SolidStartInlineConfig): any;
|
package/config/index.js
CHANGED
|
@@ -38,11 +38,12 @@ function solidStartServerFsRouter(config) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function defineConfig(baseConfig = {}) {
|
|
41
|
-
let {
|
|
41
|
+
let { vite = {}, ...start } = baseConfig;
|
|
42
42
|
const extensions = [...DEFAULT_EXTENSIONS, ...(start.extensions || [])];
|
|
43
43
|
start = defu(start, {
|
|
44
44
|
appRoot: "./src",
|
|
45
45
|
ssr: true,
|
|
46
|
+
devOverlay: true,
|
|
46
47
|
islands: false,
|
|
47
48
|
solid: {},
|
|
48
49
|
server: {
|
|
@@ -71,8 +72,8 @@ export function defineConfig(baseConfig = {}) {
|
|
|
71
72
|
{
|
|
72
73
|
name: "public",
|
|
73
74
|
type: "static",
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
base: "/",
|
|
76
|
+
dir: "./public"
|
|
76
77
|
},
|
|
77
78
|
{
|
|
78
79
|
name: "ssr",
|
|
@@ -85,51 +86,57 @@ export function defineConfig(baseConfig = {}) {
|
|
|
85
86
|
routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
|
|
86
87
|
extensions,
|
|
87
88
|
target: "server",
|
|
88
|
-
plugins: async () =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
serverTransform({
|
|
103
|
-
runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url)))
|
|
104
|
-
}),
|
|
105
|
-
start.islands ? serverComponents.server() : null,
|
|
106
|
-
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
|
|
107
|
-
config("app-server", {
|
|
108
|
-
resolve: {
|
|
109
|
-
alias: {
|
|
110
|
-
"#start/app": join(process.cwd(), start.appRoot, `app${entryExtension}`),
|
|
111
|
-
"~": join(process.cwd(), start.appRoot),
|
|
112
|
-
...(!start.ssr
|
|
113
|
-
? {
|
|
114
|
-
"@solidjs/start/server": "@solidjs/start/server/spa"
|
|
115
|
-
}
|
|
116
|
-
: {}),
|
|
117
|
-
...userConfig.resolve?.alias
|
|
89
|
+
plugins: async () => {
|
|
90
|
+
const userConfig = typeof vite === "function" ? await vite({ router: "server" }) : { ...vite };
|
|
91
|
+
const plugins = userConfig.plugins || [];
|
|
92
|
+
delete userConfig.plugins;
|
|
93
|
+
return [
|
|
94
|
+
config("user", {
|
|
95
|
+
...userConfig,
|
|
96
|
+
optimizeDeps: {
|
|
97
|
+
...(userConfig.optimizeDeps || {}),
|
|
98
|
+
include: [
|
|
99
|
+
...(userConfig.optimizeDeps?.include || []),
|
|
100
|
+
"@solidjs/start > source-map-js",
|
|
101
|
+
"@solidjs/start > error-stack-parser"
|
|
102
|
+
]
|
|
118
103
|
}
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
104
|
+
}),
|
|
105
|
+
...plugins,
|
|
106
|
+
serverTransform({
|
|
107
|
+
runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url)))
|
|
108
|
+
}),
|
|
109
|
+
start.islands ? serverComponents.server() : null,
|
|
110
|
+
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
|
|
111
|
+
config("app-server", {
|
|
112
|
+
resolve: {
|
|
113
|
+
alias: {
|
|
114
|
+
"#start/app": join(process.cwd(), start.appRoot, `app${entryExtension}`),
|
|
115
|
+
"~": join(process.cwd(), start.appRoot),
|
|
116
|
+
...(!start.ssr
|
|
117
|
+
? {
|
|
118
|
+
"@solidjs/start/server": "@solidjs/start/server/spa"
|
|
119
|
+
}
|
|
120
|
+
: {}),
|
|
121
|
+
...userConfig.resolve?.alias
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
cacheDir: "node_modules/.vinxi/server",
|
|
125
|
+
define: {
|
|
126
|
+
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
127
|
+
"import.meta.env.SSR": JSON.stringify(true),
|
|
128
|
+
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
129
|
+
"import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
|
|
130
|
+
...userConfig.define
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
];
|
|
134
|
+
}
|
|
129
135
|
},
|
|
130
136
|
{
|
|
131
137
|
name: "client",
|
|
132
138
|
type: "client",
|
|
139
|
+
base: "/_build",
|
|
133
140
|
handler: `${start.appRoot}/entry-client${entryExtension}`,
|
|
134
141
|
...(start.islands
|
|
135
142
|
? {}
|
|
@@ -138,53 +145,58 @@ export function defineConfig(baseConfig = {}) {
|
|
|
138
145
|
}),
|
|
139
146
|
extensions,
|
|
140
147
|
target: "browser",
|
|
141
|
-
plugins: async () =>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
148
|
+
plugins: async () => {
|
|
149
|
+
const userConfig = typeof vite === "function" ? await vite({ router: "client" }) : { ...vite };
|
|
150
|
+
const plugins = userConfig.plugins || [];
|
|
151
|
+
delete userConfig.plugins;
|
|
152
|
+
return [
|
|
153
|
+
config("user", {
|
|
154
|
+
...userConfig,
|
|
155
|
+
optimizeDeps: {
|
|
156
|
+
...(userConfig.optimizeDeps || {}),
|
|
157
|
+
include: [
|
|
158
|
+
...(userConfig.optimizeDeps?.include || []),
|
|
159
|
+
"@solidjs/start > source-map-js",
|
|
160
|
+
"@solidjs/start > error-stack-parser"
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
}),
|
|
164
|
+
...plugins,
|
|
165
|
+
serverFunctions.client({
|
|
166
|
+
runtime: normalize(fileURLToPath(new URL("./server-runtime.ts", import.meta.url)))
|
|
167
|
+
}),
|
|
168
|
+
start.islands ? serverComponents.client() : null,
|
|
169
|
+
solid({ ...start.solid, ssr: start.ssr, extensions: extensions.map(ext => `.${ext}`) }),
|
|
170
|
+
config("app-client", {
|
|
171
|
+
resolve: {
|
|
172
|
+
alias: {
|
|
173
|
+
"#start/app": join(process.cwd(), start.appRoot, `app${entryExtension}`),
|
|
174
|
+
"~": join(process.cwd(), start.appRoot),
|
|
175
|
+
...(start.islands
|
|
176
|
+
? {
|
|
177
|
+
"@solidjs/start/client": "@solidjs/start/client/islands"
|
|
178
|
+
}
|
|
179
|
+
: {}),
|
|
180
|
+
...(!start.ssr
|
|
181
|
+
? {
|
|
182
|
+
"@solidjs/start/client": "@solidjs/start/client/spa"
|
|
183
|
+
}
|
|
184
|
+
: {}),
|
|
185
|
+
...userConfig.resolve?.alias
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
cacheDir: "node_modules/.vinxi/client",
|
|
189
|
+
define: {
|
|
190
|
+
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
191
|
+
"import.meta.env.SSR": JSON.stringify(false),
|
|
192
|
+
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
193
|
+
"import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
|
|
194
|
+
"import.meta.env.SERVER_BASE_URL": JSON.stringify(server?.baseURL ?? ""),
|
|
195
|
+
...userConfig.define
|
|
175
196
|
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
180
|
-
"import.meta.env.SSR": JSON.stringify(false),
|
|
181
|
-
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
182
|
-
"import.meta.env.SERVER_BASE_URL": JSON.stringify(server?.baseURL ?? ""),
|
|
183
|
-
...userConfig.define
|
|
184
|
-
}
|
|
185
|
-
})
|
|
186
|
-
],
|
|
187
|
-
base: "/_build"
|
|
197
|
+
})
|
|
198
|
+
];
|
|
199
|
+
}
|
|
188
200
|
},
|
|
189
201
|
|
|
190
202
|
{
|
|
@@ -192,48 +204,54 @@ export function defineConfig(baseConfig = {}) {
|
|
|
192
204
|
type: "http",
|
|
193
205
|
base: "/_server",
|
|
194
206
|
handler: normalize(fileURLToPath(new URL("./server-handler.ts", import.meta.url))),
|
|
207
|
+
middleware: start.middleware,
|
|
195
208
|
target: "server",
|
|
196
209
|
routes: solidStartServerFsRouter({ dir: `${start.appRoot}/routes`, extensions }),
|
|
197
|
-
plugins: async () =>
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
210
|
+
plugins: async () => {
|
|
211
|
+
const userConfig = typeof vite === "function" ? await vite({ router: "server-function" }) : { ...vite };
|
|
212
|
+
const plugins = userConfig.plugins || [];
|
|
213
|
+
delete userConfig.plugins;
|
|
214
|
+
return [
|
|
215
|
+
config("user", {
|
|
216
|
+
...userConfig,
|
|
217
|
+
optimizeDeps: {
|
|
218
|
+
...(userConfig.optimizeDeps || {}),
|
|
219
|
+
include: [
|
|
220
|
+
...(userConfig.optimizeDeps?.include || []),
|
|
221
|
+
"@solidjs/start > source-map-js",
|
|
222
|
+
"@solidjs/start > error-stack-parser"
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
cacheDir: "node_modules/.vinxi/server-fns"
|
|
226
|
+
}),
|
|
227
|
+
...plugins,
|
|
228
|
+
serverFunctionServer({
|
|
229
|
+
runtime: normalize(fileURLToPath(new URL("./server-fns-runtime.ts", import.meta.url)))
|
|
230
|
+
}),
|
|
231
|
+
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
|
|
232
|
+
config("app-server", {
|
|
233
|
+
resolve: {
|
|
234
|
+
alias: {
|
|
235
|
+
"#start/app": join(process.cwd(), start.appRoot, `app${entryExtension}`),
|
|
236
|
+
"~": join(process.cwd(), start.appRoot),
|
|
237
|
+
...(!start.ssr
|
|
238
|
+
? {
|
|
239
|
+
"@solidjs/start/server": "@solidjs/start/server/spa"
|
|
240
|
+
}
|
|
241
|
+
: {}),
|
|
242
|
+
...userConfig.resolve?.alias
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
define: {
|
|
246
|
+
"import.meta.env.START_ISLANDS": JSON.stringify(start.islands),
|
|
247
|
+
"import.meta.env.SSR": JSON.stringify(true),
|
|
248
|
+
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
249
|
+
"import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
|
|
250
|
+
...userConfig.define
|
|
226
251
|
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
"import.meta.env.SSR": JSON.stringify(true),
|
|
231
|
-
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
232
|
-
...userConfig.define
|
|
233
|
-
}
|
|
234
|
-
})
|
|
235
|
-
],
|
|
236
|
-
middleware: start.middleware
|
|
252
|
+
})
|
|
253
|
+
];
|
|
254
|
+
}
|
|
237
255
|
}
|
|
238
256
|
]
|
|
239
257
|
});
|
|
@@ -8,7 +8,7 @@ export function createServerReference(fn: Function, id: string, name: string) {
|
|
|
8
8
|
return new Proxy(fn, {
|
|
9
9
|
get(target, prop, receiver) {
|
|
10
10
|
if (prop === "url") {
|
|
11
|
-
return `${baseURL}/_server
|
|
11
|
+
return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
|
|
12
12
|
}
|
|
13
13
|
if (prop === "GET") return receiver;
|
|
14
14
|
},
|
package/config/server-runtime.ts
CHANGED
|
@@ -190,25 +190,26 @@ export function createServerReference(fn: Function, id: string, name: string) {
|
|
|
190
190
|
return new Proxy(fn, {
|
|
191
191
|
get(target, prop, receiver) {
|
|
192
192
|
if (prop === "url") {
|
|
193
|
-
return `${baseURL}/_server
|
|
193
|
+
return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
|
|
194
194
|
}
|
|
195
195
|
if (prop === "GET") {
|
|
196
196
|
return receiver.withOptions({ method: "GET" });
|
|
197
197
|
}
|
|
198
198
|
if (prop === "withOptions") {
|
|
199
|
+
const url = `${baseURL}/_server/?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`
|
|
199
200
|
return (options: RequestInit) => {
|
|
200
201
|
const fn = (...args: any[]) => {
|
|
201
202
|
const encodeArgs = options.method && options.method.toUpperCase() === "GET";
|
|
202
203
|
return fetchServerFunction(
|
|
203
204
|
encodeArgs
|
|
204
|
-
?
|
|
205
|
+
? url + (args.length ? `&args=${JSON.stringify(args)}` : "")
|
|
205
206
|
: `${baseURL}/_server`,
|
|
206
207
|
`${id}#${name}`,
|
|
207
208
|
options,
|
|
208
209
|
encodeArgs ? [] : args
|
|
209
210
|
);
|
|
210
211
|
};
|
|
211
|
-
fn.url =
|
|
212
|
+
fn.url = url;
|
|
212
213
|
return fn;
|
|
213
214
|
};
|
|
214
215
|
}
|
package/env.d.ts
CHANGED
|
@@ -13,11 +13,8 @@ interface ImportMetaEnv extends Record<`VITE_${string}`, any>, SolidStartMetaEnv
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
interface SolidStartMetaEnv {
|
|
16
|
-
START_ISLANDS_ROUTER: string;
|
|
17
|
-
START_INDEX_HTML: string;
|
|
18
|
-
START_ENTRY_CLIENT: string;
|
|
19
16
|
START_SSR: string;
|
|
20
17
|
START_ISLANDS: string;
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
START_DEV_OVERLAY: string;
|
|
19
|
+
SERVER_BASE_URL: string;
|
|
23
20
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/start",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"publishConfig": {
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"solid-js": "^1.8.15",
|
|
46
|
-
"vinxi": "^0.
|
|
46
|
+
"vinxi": "^0.3.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@vinxi/plugin-directives": "^0.
|
|
50
|
-
"@vinxi/server-components": "^0.
|
|
51
|
-
"@vinxi/server-functions": "^0.
|
|
49
|
+
"@vinxi/plugin-directives": "^0.3.0",
|
|
50
|
+
"@vinxi/server-components": "^0.3.0",
|
|
51
|
+
"@vinxi/server-functions": "^0.3.0",
|
|
52
52
|
"defu": "^6.1.2",
|
|
53
53
|
"error-stack-parser": "^2.1.4",
|
|
54
54
|
"html-to-image": "^1.11.11",
|
package/server/StartServer.tsx
CHANGED
|
@@ -32,6 +32,8 @@ function matchRoute(matches: any[], routes: any[], matched = []): any[] | undefi
|
|
|
32
32
|
|
|
33
33
|
export function StartServer(props: { document: Component<DocumentComponentProps> }) {
|
|
34
34
|
const context = getRequestEvent() as PageEvent;
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
const nonce = context.nonce;
|
|
35
37
|
|
|
36
38
|
let assets: Asset[] = [];
|
|
37
39
|
Promise.resolve().then(async () => {
|
|
@@ -39,15 +41,14 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
39
41
|
if (context.router && context.router.matches) {
|
|
40
42
|
// @ts-ignore
|
|
41
43
|
const matches = [...context.router.matches];
|
|
42
|
-
while (matches.length && (!matches[0].info || !matches[0].info.filesystem))
|
|
43
|
-
matches.shift();
|
|
44
|
+
while (matches.length && (!matches[0].info || !matches[0].info.filesystem)) matches.shift();
|
|
44
45
|
const matched = matches.length && matchRoute(matches, context.routes);
|
|
45
46
|
if (matched) {
|
|
46
47
|
for (let i = 0; i < matched.length; i++) {
|
|
47
48
|
const segment = matched[i];
|
|
48
49
|
const part = import.meta.env.MANIFEST[import.meta.env.START_ISLANDS ? "ssr" : "client"]!
|
|
49
50
|
.inputs[segment["$component"].src]!;
|
|
50
|
-
const asset = await part.assets() as any;
|
|
51
|
+
const asset = (await part.assets()) as any;
|
|
51
52
|
assets.push.apply(assets, asset);
|
|
52
53
|
}
|
|
53
54
|
} else console.warn("No route matched for preloading js assets");
|
|
@@ -74,18 +75,37 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
|
|
|
74
75
|
</>
|
|
75
76
|
}
|
|
76
77
|
scripts={
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
nonce ? (
|
|
79
|
+
<>
|
|
80
|
+
<script
|
|
81
|
+
nonce={nonce}
|
|
82
|
+
innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}
|
|
83
|
+
/>
|
|
84
|
+
<script
|
|
85
|
+
type="module"
|
|
86
|
+
nonce={nonce}
|
|
87
|
+
async
|
|
88
|
+
src={
|
|
89
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
90
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
91
|
+
]!.output.path
|
|
92
|
+
}
|
|
93
|
+
/>
|
|
94
|
+
</>
|
|
95
|
+
) : (
|
|
96
|
+
<>
|
|
97
|
+
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`} />
|
|
98
|
+
<script
|
|
99
|
+
type="module"
|
|
100
|
+
async
|
|
101
|
+
src={
|
|
102
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
103
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
104
|
+
]!.output.path
|
|
105
|
+
}
|
|
106
|
+
/>
|
|
107
|
+
</>
|
|
108
|
+
)
|
|
89
109
|
}
|
|
90
110
|
>
|
|
91
111
|
{!import.meta.env.START_ISLANDS ? (
|
package/server/fetchEvent.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
H3Event,
|
|
3
|
-
HTTPEvent,
|
|
4
3
|
HTTPEventSymbol,
|
|
5
4
|
appendResponseHeader,
|
|
6
5
|
getRequestIP,
|
|
@@ -45,7 +44,7 @@ export function getFetchEvent(h3Event: H3Event): FetchEvent {
|
|
|
45
44
|
return (h3Event as any)[fetchEventSymbol];
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
export function mergeResponseHeaders(h3Event:
|
|
47
|
+
export function mergeResponseHeaders(h3Event: H3Event, headers: Headers) {
|
|
49
48
|
for (const [key, value] of headers.entries()) {
|
|
50
49
|
setHeader(h3Event, key, value);
|
|
51
50
|
}
|
package/server/handler.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { sharedConfig } from "solid-js";
|
|
|
2
2
|
import { renderToStream, renderToString } from "solid-js/web";
|
|
3
3
|
import { provideRequestEvent } from "solid-js/web/storage";
|
|
4
4
|
import {
|
|
5
|
-
EventHandlerObject,
|
|
6
5
|
EventHandlerRequest,
|
|
7
6
|
H3Event,
|
|
8
7
|
eventHandler,
|
|
@@ -13,27 +12,16 @@ import {
|
|
|
13
12
|
import { matchAPIRoute } from "../shared/routes";
|
|
14
13
|
import { getFetchEvent } from "./fetchEvent";
|
|
15
14
|
import { createPageEvent } from "./pageEvent";
|
|
16
|
-
import type { APIEvent, FetchEvent, PageEvent } from "./types";
|
|
15
|
+
import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types";
|
|
17
16
|
|
|
18
17
|
export function createBaseHandler(
|
|
19
18
|
fn: (context: PageEvent) => unknown,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
renderId?: string;
|
|
23
|
-
timeoutMs?: number;
|
|
24
|
-
onCompleteAll?: (options: { write: (v: any) => void }) => void;
|
|
25
|
-
onCompleteShell?: (options: { write: (v: any) => void }) => void;
|
|
26
|
-
createPageEvent?: (event: FetchEvent) => Promise<PageEvent>;
|
|
27
|
-
onRequest?: EventHandlerObject["onRequest"];
|
|
28
|
-
onBeforeResponse?: EventHandlerObject["onBeforeResponse"];
|
|
29
|
-
} = {}
|
|
19
|
+
createPageEvent: (event: FetchEvent) => Promise<PageEvent>,
|
|
20
|
+
options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {}
|
|
30
21
|
) {
|
|
31
22
|
return eventHandler({
|
|
32
|
-
onRequest: options.onRequest,
|
|
33
|
-
onBeforeResponse: options.onBeforeResponse,
|
|
34
23
|
handler: (e: H3Event<EventHandlerRequest>) => {
|
|
35
24
|
const event = getFetchEvent(e);
|
|
36
|
-
const mode = import.meta.env.START_SSR;
|
|
37
25
|
|
|
38
26
|
return provideRequestEvent(event, async () => {
|
|
39
27
|
// api
|
|
@@ -55,7 +43,11 @@ export function createBaseHandler(
|
|
|
55
43
|
|
|
56
44
|
// render
|
|
57
45
|
const context = await createPageEvent(event);
|
|
58
|
-
if (
|
|
46
|
+
if (typeof options === "function") options = await options(context);
|
|
47
|
+
const mode = options.mode || "stream";
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
if (options.nonce) context.nonce = options.nonce;
|
|
50
|
+
if (mode === "sync" || !import.meta.env.START_SSR) {
|
|
59
51
|
const html = renderToString(() => {
|
|
60
52
|
(sharedConfig.context as any).event = context;
|
|
61
53
|
return fn(context);
|
|
@@ -115,7 +107,7 @@ function handleStreamCompleteRedirect(context: PageEvent) {
|
|
|
115
107
|
|
|
116
108
|
export function createHandler(
|
|
117
109
|
fn: (context: PageEvent) => unknown,
|
|
118
|
-
options:
|
|
110
|
+
options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>)
|
|
119
111
|
) {
|
|
120
|
-
return createBaseHandler(fn,
|
|
112
|
+
return createBaseHandler(fn, createPageEvent, options);
|
|
121
113
|
}
|
|
@@ -8,29 +8,44 @@ const docType = ssr("<!DOCTYPE html>");
|
|
|
8
8
|
|
|
9
9
|
export function StartServer(props: { document: Component<DocumentComponentProps> }) {
|
|
10
10
|
const context = getRequestEvent() as PageEvent;
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
const nonce = context.nonce;
|
|
11
13
|
return (
|
|
12
14
|
<NoHydration>
|
|
13
15
|
{docType as unknown as any}
|
|
14
16
|
<props.document
|
|
15
|
-
assets={
|
|
16
|
-
<>
|
|
17
|
-
{context.assets.map((m: any) => renderAsset(m))}
|
|
18
|
-
</>
|
|
19
|
-
}
|
|
17
|
+
assets={<>{context.assets.map((m: any) => renderAsset(m))}</>}
|
|
20
18
|
scripts={
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
nonce ? (
|
|
20
|
+
<>
|
|
21
|
+
<script
|
|
22
|
+
nonce={nonce}
|
|
23
|
+
innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}
|
|
24
|
+
/>
|
|
25
|
+
<script
|
|
26
|
+
type="module"
|
|
27
|
+
src={
|
|
28
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
29
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
30
|
+
]!.output.path
|
|
31
|
+
}
|
|
32
|
+
/>
|
|
33
|
+
</>
|
|
34
|
+
) : (
|
|
35
|
+
<>
|
|
36
|
+
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`} />
|
|
37
|
+
<script
|
|
38
|
+
type="module"
|
|
39
|
+
src={
|
|
40
|
+
import.meta.env.MANIFEST["client"]!.inputs[
|
|
41
|
+
import.meta.env.MANIFEST["client"]!.handler
|
|
42
|
+
]!.output.path
|
|
43
|
+
}
|
|
44
|
+
/>
|
|
45
|
+
</>
|
|
46
|
+
)
|
|
32
47
|
}
|
|
33
|
-
|
|
48
|
+
/>
|
|
34
49
|
</NoHydration>
|
|
35
50
|
);
|
|
36
51
|
}
|
package/server/spa/handler.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createBaseHandler } from "../handler";
|
|
2
|
-
import { FetchEvent, PageEvent } from "../types";
|
|
2
|
+
import { FetchEvent, HandlerOptions, PageEvent } from "../types";
|
|
3
3
|
|
|
4
4
|
export function createHandler(
|
|
5
5
|
fn: (context: PageEvent) => unknown,
|
|
6
|
-
options?:
|
|
6
|
+
options?: HandlerOptions | ((context: PageEvent) => HandlerOptions)
|
|
7
7
|
) {
|
|
8
|
-
return createBaseHandler(fn,
|
|
8
|
+
return createBaseHandler(fn, createPageEvent, options);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export async function createPageEvent(ctx: FetchEvent) {
|
package/server/types.ts
CHANGED
|
@@ -22,6 +22,14 @@ export type Asset = {
|
|
|
22
22
|
attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> & { key?: string };
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
export type HandlerOptions = {
|
|
26
|
+
mode?: "sync" | "async" | "stream";
|
|
27
|
+
nonce?: string;
|
|
28
|
+
renderId?: string;
|
|
29
|
+
onCompleteAll?: (options: { write: (v: any) => void }) => void;
|
|
30
|
+
onCompleteShell?: (options: { write: (v: any) => void }) => void;
|
|
31
|
+
};
|
|
32
|
+
|
|
25
33
|
export type ContextMatches = {
|
|
26
34
|
originalPath: string;
|
|
27
35
|
pattern: string;
|
package/shared/ErrorBoundary.tsx
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { ErrorBoundary as DefaultErrorBoundary, type ParentProps } from "solid-js";
|
|
2
|
+
import { isServer } from "solid-js/web";
|
|
2
3
|
import { HttpStatusCode } from "./HttpStatusCode";
|
|
3
4
|
import { DevOverlay } from "./dev-overlay";
|
|
4
5
|
|
|
5
6
|
export function ErrorBoundary(props: ParentProps) {
|
|
6
|
-
if (import.meta.env.DEV) {
|
|
7
|
+
if (import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY) {
|
|
7
8
|
return <DevOverlay>{props.children}</DevOverlay>;
|
|
8
9
|
}
|
|
10
|
+
const message = isServer ? "500 | Internal Server Error" : "Error | Uncaught Client Exception";
|
|
9
11
|
return (
|
|
10
|
-
<DefaultErrorBoundary
|
|
12
|
+
<DefaultErrorBoundary
|
|
13
|
+
fallback={
|
|
14
|
+
<>
|
|
15
|
+
<span style="font-size:1.5em;text-align:center;position:fixed;left:0px;bottom:55%;width:100%;">{message}</span>
|
|
16
|
+
<HttpStatusCode code={500} />
|
|
17
|
+
</>
|
|
18
|
+
}
|
|
19
|
+
>
|
|
11
20
|
{props.children}
|
|
12
21
|
</DefaultErrorBoundary>
|
|
13
22
|
);
|