@solidjs/start 2.0.0-rc.2 → 2.0.0-rc.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @solidjs/start
2
2
 
3
+ ## 2.0.0-rc.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d9018d6: fix(types): add missing properties to `SolidStartOptions` and expose them via Vite plugin configuration
8
+ - e26cef0: Fix TS2883/TS2742 when emitting declarations for `entry-server.tsx`. `createHandler` now returns `StartHandler`, a type owned by `@solidjs/start`, instead of h3's `H3`, so the inferred type of `export default createHandler(...)` no longer has to be named through a nested `node_modules/@solidjs/start/node_modules/h3` path.
9
+ - 7c8dbe6: keep TypeScript namespace members in route files during production builds
10
+ - b3c7aaf: Update `h3` to `2.0.1-rc.26`.
11
+ - b3c7aaf: Fixed event response status and headers set during server-side rendering with deferred async resources, not being applied on the outgoing response.
12
+
3
13
  ## 2.0.0-rc.2
4
14
 
5
15
  ### Minor Changes
@@ -133,6 +133,11 @@ function treeShakeTransform({ types: t }) {
133
133
  if (!state.opts.pick) {
134
134
  return;
135
135
  }
136
+ // Only module-level exports are route exports; `export` inside a
137
+ // TS namespace/module block is unrelated to the pick list.
138
+ if (!exportNamedPath.parentPath.isProgram()) {
139
+ return;
140
+ }
136
141
  const specifiers = exportNamedPath.get("specifiers");
137
142
  if (specifiers.length) {
138
143
  specifiers.forEach(s => {
@@ -2,24 +2,99 @@ import type { PluginOption } from "vite";
2
2
  import { type Options as SolidOptions } from "vite-plugin-solid";
3
3
  import { type ServerFunctionsOptions } from "../directives/index.ts";
4
4
  import { type EnvPluginOptions } from "./env.ts";
5
+ /**
6
+ * Configuration options for SolidStart. (previously in `app.config.ts`)
7
+ *
8
+ * @see https://docs.solidjs.com/solid-start/v2/migrating-from-v1#move-framework-configuration-into-viteconfigts
9
+ */
5
10
  export interface SolidStartOptions {
11
+ /**
12
+ * Path to the root of the application (where `app.tsx` / `app.jsx` lives).
13
+ *
14
+ * @default "./src"
15
+ */
16
+ appRoot?: string;
17
+ /**
18
+ * Options forwarded to `vite-plugin-solid`.
19
+ *
20
+ * @see https://github.com/solidjs/vite-plugin-solid#api
21
+ */
6
22
  solid?: Partial<SolidOptions>;
23
+ /**
24
+ * Enable or disable server-side rendering.
25
+ *
26
+ * - `true` — SSR (default)
27
+ * - `false` — client-side rendering only (SPA mode)
28
+ *
29
+ * @default true
30
+ */
7
31
  ssr?: boolean;
32
+ /**
33
+ * Show the SolidStart development overlay (error overlay, etc.) in development.
34
+ *
35
+ * @default true
36
+ */
37
+ devOverlay?: boolean;
38
+ /**
39
+ * Experimental features.
40
+ */
41
+ experimental?: {
42
+ /**
43
+ * Enable islands architecture mode.
44
+ *
45
+ * Currently fixed to `false` (not yet fully supported).
46
+ *
47
+ * @default false
48
+ */
49
+ islands?: false;
50
+ };
51
+ /**
52
+ * Directory containing file-system routes, relative to {@link appRoot}.
53
+ *
54
+ * @default "./routes"
55
+ */
8
56
  routeDir?: string;
57
+ /**
58
+ * File extensions that should be treated as routes.
59
+ *
60
+ * @default ["js", "jsx", "ts", "tsx"]
61
+ */
9
62
  extensions?: string[];
63
+ /**
64
+ * Path to an optional middleware module.
65
+ *
66
+ * The module should export a middleware created with `createMiddleware`
67
+ * from `@solidjs/start/middleware`.
68
+ *
69
+ * @example "src/middleware/index.ts"
70
+ */
10
71
  middleware?: string;
72
+ /**
73
+ * Serialization settings for server-function / action payloads
74
+ * that cross the server-client boundary.
75
+ */
11
76
  serialization?: {
12
77
  /**
13
78
  * The serialization mode to use for server functions/actions.
14
- * The "js" mode uses a custom binary format that is more efficient than JSON, but requires a custom deserializer (with `eval()`) on the client.
15
- * A strong CSP should block `eval()` executions, which would prevent the "js" mode from working.
16
- * The "json" mode uses JSON for serialization, which is less efficient but can be deserialized with `JSON.parse` on the client.
79
+ *
80
+ * - `"js"` — Uses a custom binary format (Seroval) that is more efficient
81
+ * than JSON, but requires a custom deserializer (with `eval()`) on the client.
82
+ * A strong CSP that blocks `eval()` will prevent this mode from working.
83
+ * - `"json"` — Uses JSON for serialization. Less efficient / larger payloads,
84
+ * but can be deserialized with `JSON.parse` on the client and is CSP-friendly.
17
85
  *
18
86
  * @default "json"
19
87
  */
20
88
  mode?: "js" | "json";
21
89
  };
90
+ /**
91
+ * Configures plugin behavior per build environment
92
+ */
22
93
  env?: EnvPluginOptions;
94
+ /**
95
+ * Options controlling which files are processed as server functions
96
+ * (inclusion / exclusion filters for the `"use server"` transform).
97
+ */
23
98
  serverFunctions?: Pick<ServerFunctionsOptions, "filter">;
24
99
  }
25
100
  export declare function solidStart(options?: SolidStartOptions): Array<PluginOption>;
@@ -1,6 +1,5 @@
1
- import { H3 } from "h3/generic";
2
1
  import type { JSX } from "solid-js";
3
- import type { FetchEvent, HandlerOptions, PageEvent } from "./types.ts";
4
- export declare function createBaseHandler(createPageEvent: (e: FetchEvent) => Promise<PageEvent>, fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): H3;
5
- export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): H3;
2
+ import type { FetchEvent, HandlerOptions, PageEvent, StartHandler } from "./types.ts";
3
+ export declare function createBaseHandler(createPageEvent: (e: FetchEvent) => Promise<PageEvent>, fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): StartHandler;
4
+ export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>), routerLoad?: (event: FetchEvent) => Promise<void>): StartHandler;
6
5
  export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
@@ -1,5 +1,5 @@
1
1
  import middleware from "solid-start:middleware";
2
- import { defineHandler, getCookie, H3, redirect, setCookie } from "h3/generic";
2
+ import { defineHandler, getCookie, H3, iterable, redirect, setCookie, } from "h3/generic";
3
3
  import { sharedConfig } from "solid-js";
4
4
  import { getRequestEvent, renderToStream, renderToString } from "solid-js/web";
5
5
  import { createRoutes } from "../router.jsx";
@@ -19,12 +19,7 @@ export function createBaseHandler(createPageEvent, fn, options = {}, routerLoad)
19
19
  const url = new URL(event.request.url);
20
20
  const pathname = stripBaseUrl(url.pathname);
21
21
  if (pathname.startsWith(SERVER_FN_BASE)) {
22
- const serverFnResponse = await handleServerFunction(e);
23
- if (serverFnResponse instanceof Response)
24
- return produceResponseWithEventHeaders(serverFnResponse);
25
- return new Response(serverFnResponse, {
26
- headers: e.res.headers,
27
- });
22
+ return await handleServerFunction(e);
28
23
  }
29
24
  const match = matchAPIRoute(pathname, event.request.method);
30
25
  if (match) {
@@ -36,8 +31,6 @@ export function createBaseHandler(createPageEvent, fn, options = {}, routerLoad)
36
31
  sharedConfig.context = { event };
37
32
  const res = await fn(event);
38
33
  if (res !== undefined) {
39
- if (res instanceof Response)
40
- return produceResponseWithEventHeaders(res);
41
34
  return res;
42
35
  }
43
36
  if (event.request.method !== "GET") {
@@ -96,10 +89,9 @@ export function createBaseHandler(createPageEvent, fn, options = {}, routerLoad)
96
89
  }
97
90
  if (mode === "async")
98
91
  return await stream;
99
- delete stream.then;
100
92
  // h3 expects a standard web ReadableStream across runtimes. The adapter
101
93
  // also tolerates cancellation while Solid finishes outstanding work.
102
- return toWebReadableStream(stream);
94
+ return iterable(toWebReadableStream(stream));
103
95
  }),
104
96
  });
105
97
  const app = new H3();
@@ -182,38 +174,6 @@ function handleStreamCompleteRedirect(context) {
182
174
  to && write(`<script>window.location=${JSON.stringify(to).replace(/</g, "\\u003c")}</script>`);
183
175
  };
184
176
  }
185
- function produceResponseWithEventHeaders(res) {
186
- const event = getRequestEvent();
187
- let ret = res;
188
- // Response.redirect returns an immutable value, so we clone on any redirect just in case
189
- if (300 <= res.status && res.status < 400) {
190
- const cookies = res.headers.getSetCookie?.() ?? [];
191
- const headers = new Headers();
192
- res.headers.forEach((value, key) => {
193
- if (key.toLowerCase() !== "set-cookie") {
194
- headers.set(key, value);
195
- }
196
- });
197
- for (const cookie of cookies) {
198
- headers.append("Set-Cookie", cookie);
199
- }
200
- ret = new Response(res.body, {
201
- status: res.status,
202
- statusText: res.statusText,
203
- headers,
204
- });
205
- }
206
- const eventCookies = event.response.headers.getSetCookie?.() ?? [];
207
- for (const cookie of eventCookies) {
208
- ret.headers.append("Set-Cookie", cookie);
209
- }
210
- for (const [name, value] of event.response.headers) {
211
- if (name.toLowerCase() !== "set-cookie") {
212
- ret.headers.set(name, value);
213
- }
214
- }
215
- return ret;
216
- }
217
177
  function stripBaseUrl(path) {
218
178
  const base = import.meta.env.SERVER_BASE_URL || import.meta.env.BASE_URL || "/";
219
179
  return stripPathBase(path, base);
@@ -3,7 +3,7 @@ export { getServerFunctionMeta } from "../shared/serverFunction.ts";
3
3
  export { StartServer } from "./StartServer.tsx";
4
4
  export { decorateHandler, decorateMiddleware } from "./fetchEvent.ts";
5
5
  export { createHandler } from "./handler.ts";
6
- export type { APIEvent, APIHandler, Asset, ContextMatches, DocumentComponentProps, FetchEvent, HandlerOptions, PageEvent, ResponseStub, ServerFunctionMeta, } from "./types.ts";
6
+ export type { APIEvent, APIHandler, Asset, ContextMatches, DocumentComponentProps, FetchEvent, HandlerOptions, PageEvent, ResponseStub, ServerFunctionMeta, StartHandler, } from "./types.ts";
7
7
  /**
8
8
  * Checks if user has set a redirect status in the response.
9
9
  * If not, falls back to the 302 (temporary redirect)
@@ -1,8 +1,7 @@
1
- import type { H3 } from "h3/generic";
2
1
  import type { JSX } from "solid-js";
3
- import type { FetchEvent, HandlerOptions, PageEvent } from "../types.ts";
2
+ import type { FetchEvent, HandlerOptions, PageEvent, StartHandler } from "../types.ts";
4
3
  /**
5
4
  *
6
5
  * Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
7
6
  */
8
- export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions), routerLoad?: (event: FetchEvent) => Promise<void>): H3;
7
+ export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions), routerLoad?: (event: FetchEvent) => Promise<void>): StartHandler;
@@ -1,6 +1,17 @@
1
- import type { H3Event } from "h3";
1
+ import type { H3, H3Event } from "h3";
2
2
  import type { JSX } from "solid-js";
3
3
  import type { RequestEvent } from "solid-js/web";
4
+ /**
5
+ * The h3 app instance returned by `createHandler`.
6
+ *
7
+ * Structurally identical to h3's `H3`, but declared here so that `export default
8
+ * createHandler(...)` in `entry-server.tsx` can be named through `@solidjs/start`.
9
+ * Referring to `H3` directly makes TypeScript emit a reference to h3's internal
10
+ * `H3$1` class, which is not portable when h3 is nested inside
11
+ * `node_modules/@solidjs/start/node_modules` (TS2742 / TS2883).
12
+ */
13
+ export interface StartHandler extends H3 {
14
+ }
4
15
  export type DocumentComponentProps = {
5
16
  assets?: JSX.Element;
6
17
  scripts: JSX.Element;
@@ -5,5 +5,5 @@ type PipeableStream = {
5
5
  }): void;
6
6
  };
7
7
  /** Convert Solid's streaming SSR result into a cancellation-safe web stream. */
8
- export declare function toWebReadableStream(stream: PipeableStream): ReadableStream<Uint8Array>;
8
+ export declare function toWebReadableStream(stream: PipeableStream): ReadableStream<Uint8Array<ArrayBufferLike>>;
9
9
  export {};
@@ -6,8 +6,11 @@ export function toWebReadableStream(stream) {
6
6
  start(controller) {
7
7
  stream.pipe({
8
8
  write(payload) {
9
- if (active)
10
- controller.enqueue(encoder.encode(payload));
9
+ if (!active)
10
+ return;
11
+ // Encoding string to Uint8Array makes sure that
12
+ // the stream can be consumed as Response body
13
+ controller.enqueue(encoder.encode(payload));
11
14
  },
12
15
  end() {
13
16
  if (!active)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/start",
3
- "version": "2.0.0-rc.2",
3
+ "version": "2.0.0-rc.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -40,7 +40,7 @@
40
40
  "defu": "^6.1.4",
41
41
  "error-stack-parser": "^2.1.4",
42
42
  "fast-glob": "^3.3.3",
43
- "h3": "^2.0.1-rc.25",
43
+ "h3": "^2.0.1-rc.26",
44
44
  "html-to-image": "^1.11.13",
45
45
  "micromatch": "^4.0.8",
46
46
  "oxc-parser": "^0.139.0",