@solidjs/start 1.0.1 → 1.0.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.d.ts +7 -2
- package/config/index.js +1 -0
- package/dist/middleware/index.d.ts +1 -1
- package/dist/runtime/server-fns-runtime.js +1 -0
- package/dist/runtime/server-handler.js +59 -41
- package/dist/runtime/server-runtime.js +16 -6
- package/dist/server/fetchEvent.js +1 -1
- package/dist/server/pageEvent.js +3 -1
- package/dist/server/renderAsset.jsx +2 -1
- package/dist/shared/GET.js +2 -3
- package/package.json +4 -4
package/config/index.d.ts
CHANGED
|
@@ -3,9 +3,14 @@ import type { CustomizableConfig } from "vinxi/dist/types/lib/vite-dev";
|
|
|
3
3
|
import { InlineConfig } from "vite";
|
|
4
4
|
import type { Options } from "vite-plugin-solid";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// should probably be maintained by Vinxi
|
|
7
|
+
type VinxiViteServerOptions = Omit<
|
|
8
|
+
InlineConfig["server"],
|
|
9
|
+
"port" | "strictPort" | "host" | "middlewareMode" | "open"
|
|
10
|
+
>;
|
|
11
|
+
|
|
7
12
|
type ViteCustomizableConfig = CustomizableConfig & {
|
|
8
|
-
server?:
|
|
13
|
+
server?: VinxiViteServerOptions;
|
|
9
14
|
};
|
|
10
15
|
|
|
11
16
|
type SolidStartInlineConfig = {
|
package/config/index.js
CHANGED
|
@@ -252,6 +252,7 @@ export function defineConfig(baseConfig = {}) {
|
|
|
252
252
|
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
|
|
253
253
|
)
|
|
254
254
|
}),
|
|
255
|
+
start.experimental.islands ? serverComponents.server() : null,
|
|
255
256
|
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
|
|
256
257
|
config("app-server", {
|
|
257
258
|
resolve: {
|
|
@@ -2,7 +2,7 @@ import type { FetchEvent } from "../server/types";
|
|
|
2
2
|
/** Function responsible for receiving an observable [operation]{@link Operation} and returning a [result]{@link OperationResult}. */
|
|
3
3
|
export type MiddlewareFn = (event: FetchEvent) => Promise<unknown> | unknown;
|
|
4
4
|
/** This composes an array of Exchanges into a single ExchangeIO function */
|
|
5
|
-
export type RequestMiddleware = (event: FetchEvent) => Response | Promise<Response> | void | Promise<void>;
|
|
5
|
+
export type RequestMiddleware = (event: FetchEvent) => Response | Promise<Response> | void | Promise<void> | Promise<void | Response>;
|
|
6
6
|
type EventHandlerResponse<T = any> = T | Promise<T>;
|
|
7
7
|
type ResponseMiddlewareResponseParam = {
|
|
8
8
|
body?: Awaited<EventHandlerResponse>;
|
|
@@ -8,8 +8,8 @@ import { provideRequestEvent } from "solid-js/web/storage";
|
|
|
8
8
|
import { eventHandler, setHeader, setResponseStatus } from "vinxi/http";
|
|
9
9
|
import invariant from "vinxi/lib/invariant";
|
|
10
10
|
import { cloneEvent, getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
|
|
11
|
-
import { createPageEvent } from "../server/pageEvent";
|
|
12
11
|
import { getExpectedRedirectStatus } from "../server/handler";
|
|
12
|
+
import { createPageEvent } from "../server/pageEvent";
|
|
13
13
|
function createChunk(data) {
|
|
14
14
|
const encodeData = new TextEncoder().encode(data);
|
|
15
15
|
const bytes = encodeData.length;
|
|
@@ -96,18 +96,24 @@ async function handleServerFunction(h3Event) {
|
|
|
96
96
|
}
|
|
97
97
|
if (h3Event.method === "POST") {
|
|
98
98
|
const contentType = request.headers.get("content-type");
|
|
99
|
+
const h3EventBody = h3Event.node.req;
|
|
100
|
+
const isH3EventBodyStreamLocked = h3EventBody instanceof ReadableStream && h3EventBody.locked;
|
|
99
101
|
if (contentType?.startsWith("multipart/form-data") ||
|
|
100
102
|
contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
101
103
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
102
104
|
// (issue only in edge runtimes)
|
|
103
|
-
parsed.push(await
|
|
105
|
+
parsed.push(await (isH3EventBodyStreamLocked
|
|
106
|
+
? request
|
|
107
|
+
: new Request(request, { ...request, body: h3EventBody })).formData());
|
|
104
108
|
// what should work when #1721 is fixed
|
|
105
109
|
// parsed.push(await request.formData);
|
|
106
110
|
}
|
|
107
111
|
else if (contentType?.startsWith("application/json")) {
|
|
108
112
|
// workaround for https://github.com/unjs/nitro/issues/1721
|
|
109
113
|
// (issue only in edge runtimes)
|
|
110
|
-
const tmpReq =
|
|
114
|
+
const tmpReq = isH3EventBodyStreamLocked
|
|
115
|
+
? request
|
|
116
|
+
: new Request(request, { ...request, body: h3EventBody });
|
|
111
117
|
// what should work when #1721 is fixed
|
|
112
118
|
// just use request.json() here
|
|
113
119
|
parsed = fromJSON(await tmpReq.json(), {
|
|
@@ -139,45 +145,26 @@ async function handleServerFunction(h3Event) {
|
|
|
139
145
|
result = await handleSingleFlight(event, result);
|
|
140
146
|
}
|
|
141
147
|
// handle responses
|
|
142
|
-
if (result instanceof Response
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
result
|
|
148
|
+
if (result instanceof Response) {
|
|
149
|
+
if (result.headers && result.headers.has("X-Content-Raw"))
|
|
150
|
+
return result;
|
|
151
|
+
if (instance) {
|
|
152
|
+
// forward headers
|
|
153
|
+
if (result.headers)
|
|
154
|
+
mergeResponseHeaders(h3Event, result.headers);
|
|
155
|
+
// forward non-redirect statuses
|
|
156
|
+
if (result.status && (result.status < 300 || result.status >= 400))
|
|
157
|
+
setResponseStatus(h3Event, result.status);
|
|
158
|
+
if (result.customBody) {
|
|
159
|
+
result = await result.customBody();
|
|
160
|
+
}
|
|
161
|
+
else if (result.body == undefined)
|
|
162
|
+
result = null;
|
|
151
163
|
}
|
|
152
|
-
else if (result.body == undefined)
|
|
153
|
-
result = null;
|
|
154
164
|
}
|
|
155
165
|
// handle no JS success case
|
|
156
|
-
if (!instance)
|
|
157
|
-
|
|
158
|
-
let redirectUrl = new URL(request.headers.get("referer")).toString();
|
|
159
|
-
let statusCode = 302;
|
|
160
|
-
if (result instanceof Response && result.headers.has("Location")) {
|
|
161
|
-
redirectUrl = new URL(result.headers.get("Location"), new URL(request.url).origin + import.meta.env.SERVER_BASE_URL).toString();
|
|
162
|
-
statusCode = getExpectedRedirectStatus(result);
|
|
163
|
-
}
|
|
164
|
-
return new Response(null, {
|
|
165
|
-
status: statusCode,
|
|
166
|
-
headers: {
|
|
167
|
-
Location: redirectUrl,
|
|
168
|
-
...(result
|
|
169
|
-
? {
|
|
170
|
-
"Set-Cookie": `flash=${JSON.stringify({
|
|
171
|
-
url: url.pathname + encodeURIComponent(url.search),
|
|
172
|
-
result: isError ? result.message : result,
|
|
173
|
-
error: isError,
|
|
174
|
-
input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
|
|
175
|
-
})}; Secure; HttpOnly;`
|
|
176
|
-
}
|
|
177
|
-
: {})
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
}
|
|
166
|
+
if (!instance)
|
|
167
|
+
return handleNoJS(result, request, parsed);
|
|
181
168
|
setHeader(h3Event, "content-type", "text/javascript");
|
|
182
169
|
return serializeToStream(instance, result);
|
|
183
170
|
}
|
|
@@ -197,10 +184,14 @@ async function handleServerFunction(h3Event) {
|
|
|
197
184
|
}
|
|
198
185
|
else if (x.body == undefined)
|
|
199
186
|
x = null;
|
|
187
|
+
setHeader(h3Event, "X-Error", "true");
|
|
200
188
|
}
|
|
201
|
-
else {
|
|
189
|
+
else if (instance) {
|
|
202
190
|
const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
|
|
203
|
-
setHeader(h3Event, "X-Error", error);
|
|
191
|
+
setHeader(h3Event, "X-Error", error.replace(/[\r\n]+/g, ""));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
x = handleNoJS(x, request, parsed, true);
|
|
204
195
|
}
|
|
205
196
|
if (instance) {
|
|
206
197
|
setHeader(h3Event, "content-type", "text/javascript");
|
|
@@ -209,6 +200,33 @@ async function handleServerFunction(h3Event) {
|
|
|
209
200
|
return x;
|
|
210
201
|
}
|
|
211
202
|
}
|
|
203
|
+
function handleNoJS(result, request, parsed, thrown) {
|
|
204
|
+
const url = new URL(request.url);
|
|
205
|
+
const isError = result instanceof Error;
|
|
206
|
+
let redirectUrl = new URL(request.headers.get("referer")).toString();
|
|
207
|
+
let statusCode = 302;
|
|
208
|
+
if (result instanceof Response && result.headers.has("Location")) {
|
|
209
|
+
redirectUrl = new URL(result.headers.get("Location"), url.origin + import.meta.env.SERVER_BASE_URL).toString();
|
|
210
|
+
statusCode = getExpectedRedirectStatus(result);
|
|
211
|
+
}
|
|
212
|
+
return new Response(null, {
|
|
213
|
+
status: statusCode,
|
|
214
|
+
headers: {
|
|
215
|
+
Location: redirectUrl,
|
|
216
|
+
...(result
|
|
217
|
+
? {
|
|
218
|
+
"Set-Cookie": `flash=${JSON.stringify({
|
|
219
|
+
url: url.pathname + encodeURIComponent(url.search),
|
|
220
|
+
result: isError ? result.message : result,
|
|
221
|
+
thrown: thrown,
|
|
222
|
+
error: isError,
|
|
223
|
+
input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
|
|
224
|
+
})}; Secure; HttpOnly;`
|
|
225
|
+
}
|
|
226
|
+
: {})
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
212
230
|
let App;
|
|
213
231
|
async function handleSingleFlight(sourceEvent, result) {
|
|
214
232
|
let revalidate;
|
|
@@ -119,11 +119,17 @@ async function fetchServerFunction(base, id, options, args) {
|
|
|
119
119
|
? createRequest(base, id, instance, options)
|
|
120
120
|
: args.length === 1 && args[0] instanceof FormData
|
|
121
121
|
? createRequest(base, id, instance, { ...options, body: args[0] })
|
|
122
|
-
:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
: args.length === 1 && args[0] instanceof URLSearchParams
|
|
123
|
+
? createRequest(base, id, instance, {
|
|
124
|
+
...options,
|
|
125
|
+
body: args[0],
|
|
126
|
+
headers: { ...options.headers, "Content-Type": "application/x-www-form-urlencoded" }
|
|
127
|
+
})
|
|
128
|
+
: createRequest(base, id, instance, {
|
|
129
|
+
...options,
|
|
130
|
+
body: JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))),
|
|
131
|
+
headers: { ...options.headers, "Content-Type": "application/json" }
|
|
132
|
+
}));
|
|
127
133
|
if (response.headers.get("Location") ||
|
|
128
134
|
response.headers.get("X-Revalidate") ||
|
|
129
135
|
response.headers.get("X-Single-Flight")) {
|
|
@@ -167,13 +173,17 @@ export function createServerReference(fn, id, name) {
|
|
|
167
173
|
const fn = async (...args) => {
|
|
168
174
|
const encodeArgs = options.method && options.method.toUpperCase() === "GET";
|
|
169
175
|
return fetchServerFunction(encodeArgs
|
|
170
|
-
? url +
|
|
176
|
+
? url +
|
|
177
|
+
(args.length
|
|
178
|
+
? `&args=${encodeURIComponent(JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))))}`
|
|
179
|
+
: "")
|
|
171
180
|
: `${baseURL}/_server`, `${id}#${name}`, options, encodeArgs ? [] : args);
|
|
172
181
|
};
|
|
173
182
|
fn.url = url;
|
|
174
183
|
return fn;
|
|
175
184
|
};
|
|
176
185
|
}
|
|
186
|
+
return target[prop];
|
|
177
187
|
},
|
|
178
188
|
apply(target, thisArg, args) {
|
|
179
189
|
return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, {}, args);
|
|
@@ -81,7 +81,7 @@ function createResponseStub(event) {
|
|
|
81
81
|
return getResponseStatusText(event);
|
|
82
82
|
},
|
|
83
83
|
set statusText(v) {
|
|
84
|
-
setResponseStatus(event, getResponseStatus(), v);
|
|
84
|
+
setResponseStatus(event, getResponseStatus(event), v);
|
|
85
85
|
},
|
|
86
86
|
headers: new HeaderProxy(event)
|
|
87
87
|
};
|
package/dist/server/pageEvent.js
CHANGED
|
@@ -9,11 +9,13 @@ function initFromFlash(ctx) {
|
|
|
9
9
|
return;
|
|
10
10
|
const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
|
|
11
11
|
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
12
|
+
const result = param.error ? new Error(param.result) : param.result;
|
|
12
13
|
return {
|
|
13
14
|
input,
|
|
14
15
|
url: param.url,
|
|
15
16
|
pending: false,
|
|
16
|
-
result: param.
|
|
17
|
+
result: param.thrown ? undefined : result,
|
|
18
|
+
error: param.thrown ? result : undefined,
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
export async function createPageEvent(ctx) {
|
|
@@ -5,7 +5,8 @@ const assetMap = {
|
|
|
5
5
|
return props.attrs.src ? (<script {...props.attrs} id={props.key}>
|
|
6
6
|
{" "}
|
|
7
7
|
</script>) : null;
|
|
8
|
-
}
|
|
8
|
+
},
|
|
9
|
+
noscript: (props) => (<noscript {...props.attrs}>{props.children}</noscript>),
|
|
9
10
|
};
|
|
10
11
|
export function renderAsset(asset, nonce) {
|
|
11
12
|
let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset;
|
package/dist/shared/GET.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/start",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,14 +55,14 @@
|
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"solid-js": "^1.8.
|
|
59
|
-
"vinxi": "^0.3.
|
|
58
|
+
"solid-js": "^1.8.18",
|
|
59
|
+
"vinxi": "^0.3.14",
|
|
60
60
|
"typescript": "^5.4.2"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@vinxi/plugin-directives": "^0.3.1",
|
|
64
64
|
"@vinxi/server-components": "^0.3.3",
|
|
65
|
-
"@vinxi/server-functions": "^0.3.
|
|
65
|
+
"@vinxi/server-functions": "^0.3.3",
|
|
66
66
|
"defu": "^6.1.2",
|
|
67
67
|
"error-stack-parser": "^2.1.4",
|
|
68
68
|
"glob": "^10.3.10",
|