@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 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
- // atleast until we sort which server options are good to use
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?: InlineConfig["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>;
@@ -12,6 +12,7 @@ export function createServerReference(fn, id, name) {
12
12
  }
13
13
  if (prop === "GET")
14
14
  return receiver;
15
+ return target[prop];
15
16
  },
16
17
  apply(target, thisArg, args) {
17
18
  const ogEvt = getRequestEvent();
@@ -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 new Request(request, { ...request, body: h3Event.node.req.body }).formData());
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 = new Request(request, { ...request, body: h3Event.node.req.body });
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 && instance) {
143
- // forward headers
144
- if (result.headers)
145
- mergeResponseHeaders(h3Event, result.headers);
146
- // forward non-redirect statuses
147
- if (result.status && (result.status < 300 || result.status >= 400))
148
- setResponseStatus(h3Event, result.status);
149
- if (result.customBody) {
150
- result = await result.customBody();
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
- const isError = result instanceof Error;
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
- : createRequest(base, id, instance, {
123
- ...options,
124
- body: JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))),
125
- headers: { ...options.headers, "Content-Type": "application/json" }
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 + (args.length ? `&args=${encodeURIComponent(JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))))}` : "")
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
  };
@@ -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.error ? new Error(param.result) : param.result,
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;
@@ -1,9 +1,8 @@
1
+ // @refresh skip
1
2
  /**
2
3
  *
3
4
  * Read more: https://docs.solidjs.com/solid-start/reference/server/get
4
5
  */
5
6
  export function GET(fn) {
6
- return (...args) => {
7
- return fn.GET(...args);
8
- };
7
+ return fn.GET;
9
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/start",
3
- "version": "1.0.1",
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.17",
59
- "vinxi": "^0.3.11",
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.2",
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",