@solidjs/start 1.1.7 → 2.0.0-alpha.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.
Files changed (185) hide show
  1. package/README.md +88 -8
  2. package/dist/client/StartClient.d.ts +0 -1
  3. package/dist/client/StartClient.jsx +2 -4
  4. package/dist/client/index.d.ts +2 -3
  5. package/dist/client/index.jsx +2 -4
  6. package/dist/client/mount.js +10 -2
  7. package/dist/client/spa/index.d.ts +1 -2
  8. package/dist/client/spa/index.jsx +1 -2
  9. package/dist/config/constants.d.ts +16 -0
  10. package/dist/config/constants.js +16 -0
  11. package/dist/config/dev-server.d.ts +2 -0
  12. package/dist/config/dev-server.js +108 -0
  13. package/dist/config/fs-router.d.ts +37 -0
  14. package/dist/config/fs-router.js +153 -0
  15. package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
  16. package/dist/config/fs-routes/fs-watcher.js +49 -0
  17. package/dist/config/fs-routes/index.d.ts +7 -0
  18. package/dist/config/fs-routes/index.js +109 -0
  19. package/dist/config/fs-routes/router.d.ts +37 -0
  20. package/dist/config/fs-routes/router.js +136 -0
  21. package/dist/config/fs-routes/tree-shake.d.ts +2 -0
  22. package/dist/config/fs-routes/tree-shake.js +357 -0
  23. package/dist/config/index.d.ts +10 -0
  24. package/dist/config/index.js +217 -0
  25. package/dist/config/lazy.d.ts +3 -0
  26. package/dist/config/lazy.js +82 -0
  27. package/dist/config/manifest.d.ts +3 -0
  28. package/dist/config/manifest.js +74 -0
  29. package/dist/config/utils.d.ts +4 -0
  30. package/dist/config/utils.js +6 -0
  31. package/dist/config/vite-utils.d.ts +16 -0
  32. package/dist/config/vite-utils.js +81 -0
  33. package/dist/http/index.d.ts +84 -0
  34. package/dist/http/index.js +131 -0
  35. package/dist/index.d.ts +6 -5
  36. package/dist/index.jsx +5 -5
  37. package/dist/middleware/index.d.ts +6 -6
  38. package/dist/middleware/index.js +39 -0
  39. package/dist/{router/FileRoutes.js → router.jsx} +5 -6
  40. package/dist/server/StartServer.d.ts +3 -3
  41. package/dist/server/StartServer.jsx +9 -63
  42. package/dist/server/assets/index.d.ts +2 -0
  43. package/dist/server/assets/index.js +52 -0
  44. package/dist/server/assets/render.d.ts +19 -0
  45. package/dist/server/{renderAsset.jsx → assets/render.jsx} +1 -1
  46. package/dist/server/collect-styles.d.ts +3 -0
  47. package/dist/server/collect-styles.js +69 -0
  48. package/dist/server/fetchEvent.d.ts +4 -3
  49. package/dist/server/fetchEvent.js +12 -74
  50. package/dist/server/fetchEvent.spec.d.ts +1 -0
  51. package/dist/server/fetchEvent.spec.js +65 -0
  52. package/dist/server/handler.d.ts +6 -12
  53. package/dist/server/handler.js +180 -95
  54. package/dist/server/index.d.ts +8 -6
  55. package/dist/server/index.jsx +14 -6
  56. package/dist/server/manifest/client-manifest.d.ts +9 -0
  57. package/dist/server/manifest/client-manifest.js +6 -0
  58. package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
  59. package/dist/server/manifest/dev-client-manifest.js +24 -0
  60. package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
  61. package/dist/server/manifest/dev-ssr-manifest.js +23 -0
  62. package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
  63. package/dist/server/manifest/prod-client-manifest.js +26 -0
  64. package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
  65. package/dist/server/manifest/prod-ssr-manifest.js +90 -0
  66. package/dist/server/manifest/ssr-manifest.d.ts +4 -0
  67. package/dist/server/manifest/ssr-manifest.js +6 -0
  68. package/dist/{router → server}/routes.d.ts +6 -10
  69. package/dist/{router → server}/routes.js +35 -27
  70. package/dist/{runtime → server}/server-fns-runtime.d.ts +1 -1
  71. package/dist/{runtime → server}/server-fns-runtime.js +7 -6
  72. package/dist/server/server-functions-handler.d.ts +2 -0
  73. package/dist/{runtime/server-handler.js → server/server-functions-handler.js} +76 -103
  74. package/dist/server/server-runtime.d.ts +3 -0
  75. package/dist/{runtime → server}/server-runtime.js +9 -16
  76. package/dist/server/spa/StartServer.d.ts +1 -1
  77. package/dist/server/spa/StartServer.jsx +7 -9
  78. package/dist/server/spa/handler.d.ts +3 -3
  79. package/dist/server/spa/handler.js +9 -11
  80. package/dist/server/spa/index.d.ts +4 -3
  81. package/dist/server/spa/index.jsx +4 -3
  82. package/dist/server/types.d.ts +7 -9
  83. package/dist/server/util.d.ts +2 -0
  84. package/dist/server/util.js +8 -0
  85. package/dist/shared/ErrorBoundary.jsx +2 -2
  86. package/dist/shared/HttpHeader.jsx +4 -2
  87. package/dist/shared/{HttpStatusCode.jsx → HttpStatusCode.js} +3 -1
  88. package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +2 -2
  89. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +75 -66
  90. package/dist/shared/dev-overlay/createStackFrame.js +3 -3
  91. package/dist/shared/dev-overlay/index.jsx +5 -8
  92. package/dist/shared/lazy.d.ts +3 -0
  93. package/dist/shared/lazy.js +40 -0
  94. package/dist/shared/serverFunction.d.ts +1 -1
  95. package/package.json +47 -65
  96. package/scripts/build.js +15 -0
  97. package/scripts/validate-imports.js +316 -0
  98. package/src/client/StartClient.tsx +34 -0
  99. package/src/client/index.tsx +2 -0
  100. package/src/client/mount.ts +114 -0
  101. package/src/client/spa/index.tsx +9 -0
  102. package/src/config/constants.ts +19 -0
  103. package/src/config/dev-server.ts +149 -0
  104. package/src/config/fs-router.ts +177 -0
  105. package/src/config/fs-routes/fs-watcher.ts +81 -0
  106. package/src/config/fs-routes/index.ts +138 -0
  107. package/src/config/fs-routes/router.ts +169 -0
  108. package/src/config/fs-routes/tree-shake.ts +392 -0
  109. package/src/config/index.ts +236 -0
  110. package/src/config/lazy.ts +100 -0
  111. package/src/config/manifest.ts +84 -0
  112. package/src/config/utils.ts +5 -0
  113. package/src/config/vite-utils.ts +113 -0
  114. package/src/env.d.ts +35 -0
  115. package/src/http/index.ts +253 -0
  116. package/src/index.tsx +19 -0
  117. package/src/internal.d.ts +14 -0
  118. package/src/middleware/index.ts +82 -0
  119. package/src/router.tsx +36 -0
  120. package/src/server/StartServer.tsx +62 -0
  121. package/src/server/assets/index.ts +70 -0
  122. package/src/server/assets/render.tsx +42 -0
  123. package/src/server/collect-styles.ts +94 -0
  124. package/src/server/fetchEvent.spec.ts +89 -0
  125. package/src/server/fetchEvent.ts +36 -0
  126. package/src/server/handler.ts +250 -0
  127. package/src/server/index.tsx +16 -0
  128. package/src/server/manifest/client-manifest.ts +8 -0
  129. package/src/server/manifest/dev-client-manifest.ts +19 -0
  130. package/src/server/manifest/dev-ssr-manifest.ts +21 -0
  131. package/src/server/manifest/prod-client-manifest.ts +18 -0
  132. package/src/server/manifest/prod-ssr-manifest.ts +125 -0
  133. package/src/server/manifest/ssr-manifest.ts +8 -0
  134. package/src/server/routes.ts +138 -0
  135. package/src/server/server-fns-runtime.ts +31 -0
  136. package/src/server/server-functions-handler.ts +364 -0
  137. package/src/server/server-runtime.ts +240 -0
  138. package/src/server/spa/StartServer.tsx +40 -0
  139. package/src/server/spa/handler.ts +29 -0
  140. package/src/server/spa/index.tsx +5 -0
  141. package/src/server/types.ts +82 -0
  142. package/src/server/util.ts +12 -0
  143. package/src/shared/ErrorBoundary.tsx +52 -0
  144. package/src/shared/GET.ts +8 -0
  145. package/src/shared/HttpHeader.tsx +42 -0
  146. package/src/shared/HttpStatusCode.ts +27 -0
  147. package/src/shared/clientOnly.ts +44 -0
  148. package/src/shared/dev-overlay/CodeView.tsx +95 -0
  149. package/src/shared/dev-overlay/DevOverlayDialog.tsx +316 -0
  150. package/src/shared/dev-overlay/createStackFrame.ts +77 -0
  151. package/src/shared/dev-overlay/download.ts +6 -0
  152. package/src/shared/dev-overlay/env.d.ts +4 -0
  153. package/src/shared/dev-overlay/get-source-map.ts +35 -0
  154. package/src/shared/dev-overlay/icons.tsx +288 -0
  155. package/src/shared/dev-overlay/index.tsx +63 -0
  156. package/src/shared/dev-overlay/styles.css +292 -0
  157. package/src/shared/lazy.ts +51 -0
  158. package/src/shared/serverFunction.ts +10 -0
  159. package/src/virtual.d.ts +27 -0
  160. package/tsconfig.json +23 -0
  161. package/vitest.config.ts +9 -0
  162. package/config/fs-router.js +0 -142
  163. package/config/index.d.ts +0 -39
  164. package/config/index.js +0 -303
  165. package/config/server-components.js +0 -106
  166. package/dist/client/islands.d.ts +0 -7
  167. package/dist/client/islands.jsx +0 -10
  168. package/dist/middleware/index.jsx +0 -35
  169. package/dist/router/index.d.ts +0 -1
  170. package/dist/router/index.jsx +0 -2
  171. package/dist/router/lazyRoute.d.ts +0 -6
  172. package/dist/router/lazyRoute.js +0 -53
  173. package/dist/runtime/server-handler.d.ts +0 -2
  174. package/dist/runtime/server-runtime.d.ts +0 -3
  175. package/dist/server/islands/index.d.ts +0 -19
  176. package/dist/server/islands/index.jsx +0 -62
  177. package/dist/server/islands/utils.d.ts +0 -1
  178. package/dist/server/islands/utils.jsx +0 -85
  179. package/dist/server/pageEvent.d.ts +0 -2
  180. package/dist/server/pageEvent.js +0 -56
  181. package/dist/server/renderAsset.d.ts +0 -2
  182. package/env.d.ts +0 -26
  183. /package/dist/{router/FileRoutes.d.ts → router.d.ts} +0 -0
  184. /package/dist/shared/{clientOnly.jsx → clientOnly.js} +0 -0
  185. /package/dist/shared/{serverFunction.jsx → serverFunction.js} +0 -0
@@ -1,3 +1,4 @@
1
+ import type { FetchEvent } from "./types.ts";
1
2
  interface Route {
2
3
  path: string;
3
4
  id: string;
@@ -11,17 +12,12 @@ interface Route {
11
12
  $PATCH?: any;
12
13
  $DELETE?: any;
13
14
  }
14
- declare module "vinxi/routes" {
15
- interface Register {
16
- route: {
17
- path: string;
18
- children?: Route[];
19
- };
20
- }
21
- }
22
15
  export declare const pageRoutes: Route[];
23
16
  export declare function matchAPIRoute(path: string, method: string): {
24
- handler: any;
25
- params: Record<string, any> | undefined;
17
+ params?: Record<string, any>;
18
+ handler: {
19
+ import: () => Promise<Record<string, (e: FetchEvent) => Promise<any>>>;
20
+ };
21
+ isPage: boolean;
26
22
  } | undefined;
27
23
  export {};
@@ -1,16 +1,17 @@
1
+ // @ts-expect-error
2
+ import fileRoutes from "solid-start:routes";
1
3
  import { createRouter } from "radix3";
2
- import fileRoutes from "vinxi/routes";
3
- export const pageRoutes = defineRoutes(fileRoutes.filter(o => o.page));
4
+ export const pageRoutes = defineRoutes(fileRoutes.filter((o) => o.page));
4
5
  function defineRoutes(fileRoutes) {
5
6
  function processRoute(routes, route, id, full) {
6
- const parentRoute = Object.values(routes).find(o => {
7
+ const parentRoute = Object.values(routes).find((o) => {
7
8
  return id.startsWith(o.id + "/");
8
9
  });
9
10
  if (!parentRoute) {
10
11
  routes.push({
11
12
  ...route,
12
13
  id,
13
- path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/")
14
+ path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/"),
14
15
  });
15
16
  return routes;
16
17
  }
@@ -23,36 +24,16 @@ function defineRoutes(fileRoutes) {
23
24
  return processRoute(prevRoutes, route, route.path, route.path);
24
25
  }, []);
25
26
  }
26
- export function matchAPIRoute(path, method) {
27
- const match = router.lookup(path);
28
- if (match && match.route) {
29
- const handler = method === "HEAD" ? match.route["$HEAD"] || match.route["$GET"] : match.route[`$${method}`];
30
- if (handler === undefined)
31
- return;
32
- return {
33
- handler,
34
- params: match.params
35
- };
36
- }
37
- }
38
- function containsHTTP(route) {
39
- return (route["$HEAD"] ||
40
- route["$GET"] ||
41
- route["$POST"] ||
42
- route["$PUT"] ||
43
- route["$PATCH"] ||
44
- route["$DELETE"]);
45
- }
46
27
  const router = createRouter({
47
28
  routes: fileRoutes.reduce((memo, route) => {
48
29
  if (!containsHTTP(route))
49
30
  return memo;
50
- let path = route.path
31
+ const path = route.path
51
32
  .replace(/\([^)/]+\)/g, "")
52
33
  .replace(/\/+/g, "/")
53
34
  .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
54
35
  .split("/")
55
- .map(s => (s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s)))
36
+ .map((s) => s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s))
56
37
  .join("/");
57
38
  if (/:[^/]*\?/g.test(path)) {
58
39
  throw new Error(`Optional parameters are not supported in API routes: ${path}`);
@@ -62,5 +43,32 @@ const router = createRouter({
62
43
  }
63
44
  memo[path] = { route };
64
45
  return memo;
65
- }, {})
46
+ }, {}),
66
47
  });
48
+ function containsHTTP(route) {
49
+ return (route["$HEAD"] ||
50
+ route["$GET"] ||
51
+ route["$POST"] ||
52
+ route["$PUT"] ||
53
+ route["$PATCH"] ||
54
+ route["$DELETE"]);
55
+ }
56
+ export function matchAPIRoute(path, method) {
57
+ const match = router.lookup(path);
58
+ if (match && match.route) {
59
+ const route = match.route;
60
+ // Find the appropriate handler for the HTTP method
61
+ const handler = method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
62
+ if (handler === undefined)
63
+ return;
64
+ // Check if this is a page route
65
+ const isPage = route.page === true && route.$component !== undefined;
66
+ // Return comprehensive route information
67
+ return {
68
+ handler,
69
+ params: match.params,
70
+ isPage,
71
+ };
72
+ }
73
+ return undefined;
74
+ }
@@ -1 +1 @@
1
- export declare function createServerReference(fn: Function, id: string, name: string): Function;
1
+ export declare function createServerReference(fn: Function, id: string): Function;
@@ -1,14 +1,15 @@
1
1
  import { getRequestEvent } from "solid-js/web";
2
2
  import { provideRequestEvent } from "solid-js/web/storage";
3
- import { cloneEvent } from "../server/fetchEvent";
4
- export function createServerReference(fn, id, name) {
3
+ export function createServerReference(fn, id) {
5
4
  if (typeof fn !== "function")
6
5
  throw new Error("Export from a 'use server' module must be a function");
7
- const baseURL = import.meta.env.SERVER_BASE_URL;
6
+ let baseURL = import.meta.env.BASE_URL ?? "/";
7
+ if (!baseURL.endsWith("/"))
8
+ baseURL += "/";
8
9
  return new Proxy(fn, {
9
10
  get(target, prop, receiver) {
10
11
  if (prop === "url") {
11
- return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
12
+ return `${baseURL}_server?id=${encodeURIComponent(id)}`;
12
13
  }
13
14
  if (prop === "GET")
14
15
  return receiver;
@@ -18,9 +19,9 @@ export function createServerReference(fn, id, name) {
18
19
  const ogEvt = getRequestEvent();
19
20
  if (!ogEvt)
20
21
  throw new Error("Cannot call server function outside of a request");
21
- const evt = cloneEvent(ogEvt);
22
+ const evt = { ...ogEvt };
22
23
  evt.locals.serverFunctionMeta = {
23
- id: id + "#" + name,
24
+ id
24
25
  };
25
26
  evt.serverOnly = true;
26
27
  return provideRequestEvent(evt, () => {
@@ -0,0 +1,2 @@
1
+ import { type H3Event } from "h3";
2
+ export declare function handleServerFunction(h3Event: H3Event): Promise<unknown>;
@@ -1,17 +1,14 @@
1
- /// <reference types="vinxi/types/server" />
2
- import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
3
- // @ts-ignore
4
- import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
1
+ import { getServerFnById } from "solidstart:server-fn-manifest";
2
+ import { parseSetCookie } from "cookie-es";
3
+ import { parseCookies } from "h3";
4
+ import { crossSerializeStream, fromJSON, getCrossReferenceHeader, } from "seroval";
5
+ import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin, } from "seroval-plugins/web";
5
6
  import { sharedConfig } from "solid-js";
6
7
  import { renderToString } from "solid-js/web";
7
8
  import { provideRequestEvent } from "solid-js/web/storage";
8
- import { eventHandler, parseCookies, setHeader, setResponseStatus } from "vinxi/http";
9
- import invariant from "vinxi/lib/invariant";
10
- import { cloneEvent, getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
11
- import { getExpectedRedirectStatus } from "../server/handler";
12
- import { createPageEvent } from "../server/pageEvent";
13
- // @ts-ignore
14
- import serverFnManifest from "solidstart:server-fn-manifest";
9
+ import { getFetchEvent, mergeResponseHeaders } from "./fetchEvent.js";
10
+ import { createPageEvent } from "./handler.js";
11
+ import { getExpectedRedirectStatus } from "./util.js";
15
12
  function createChunk(data) {
16
13
  const encodeData = new TextEncoder().encode(data);
17
14
  const bytes = encodeData.length;
@@ -38,7 +35,7 @@ function serializeToStream(id, value) {
38
35
  RequestPlugin,
39
36
  ResponsePlugin,
40
37
  URLSearchParamsPlugin,
41
- URLPlugin
38
+ URLPlugin,
42
39
  ],
43
40
  onSerialize(data, initial) {
44
41
  controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
@@ -48,52 +45,32 @@ function serializeToStream(id, value) {
48
45
  },
49
46
  onError(error) {
50
47
  controller.error(error);
51
- }
48
+ },
52
49
  });
53
- }
50
+ },
54
51
  });
55
52
  }
56
- async function handleServerFunction(h3Event) {
53
+ export async function handleServerFunction(h3Event) {
57
54
  const event = getFetchEvent(h3Event);
58
55
  const request = event.request;
59
56
  const serverReference = request.headers.get("X-Server-Id");
60
57
  const instance = request.headers.get("X-Server-Instance");
61
58
  const singleFlight = request.headers.has("X-Single-Flight");
62
59
  const url = new URL(request.url);
63
- let functionId, name;
60
+ let functionId;
64
61
  if (serverReference) {
65
- invariant(typeof serverReference === "string", "Invalid server function");
66
- [functionId, name] = serverReference.split("#");
62
+ // invariant(typeof serverReference === "string", "Invalid server function");
63
+ [functionId] = serverReference.split("#");
67
64
  }
68
65
  else {
69
66
  functionId = url.searchParams.get("id");
70
- name = url.searchParams.get("name");
71
- if (!functionId || !name) {
67
+ if (!functionId) {
72
68
  return process.env.NODE_ENV === "development"
73
69
  ? new Response("Server function not found", { status: 404 })
74
70
  : new Response(null, { status: 404 });
75
71
  }
76
72
  }
77
- const serverFnInfo = serverFnManifest[functionId];
78
- let fnModule;
79
- if (!serverFnInfo) {
80
- return process.env.NODE_ENV === "development"
81
- ? new Response("Server function not found", { status: 404 })
82
- : new Response(null, { status: 404 });
83
- }
84
- if (process.env.NODE_ENV === "development") {
85
- // In dev, we use Vinxi to get the "server" server-side router
86
- // Then we use that router's devServer.ssrLoadModule to get the serverFn
87
- // This code comes from:
88
- // https://github.com/TanStack/router/blob/266f5cc863cd1a99809d1af2669e58b6b6db9a67/packages/start-server-functions-handler/src/index.tsx#L83-L87
89
- fnModule = await globalThis.app
90
- .getRouter("server-fns")
91
- .internals.devServer.ssrLoadModule(serverFnInfo.extractedFilename);
92
- }
93
- else {
94
- fnModule = await serverFnInfo.importer();
95
- }
96
- const serverFunction = fnModule[serverFnInfo.functionName];
73
+ const serverFunction = await getServerFnById(functionId);
97
74
  let parsed = [];
98
75
  // grab bound arguments from url when no JS
99
76
  if (!instance || h3Event.method === "GET") {
@@ -112,41 +89,22 @@ async function handleServerFunction(h3Event) {
112
89
  RequestPlugin,
113
90
  ResponsePlugin,
114
91
  URLSearchParamsPlugin,
115
- URLPlugin
116
- ]
92
+ URLPlugin,
93
+ ],
117
94
  })
118
- : json).forEach((arg) => parsed.push(arg));
95
+ : json).forEach((arg) => {
96
+ parsed.push(arg);
97
+ });
119
98
  }
120
99
  }
121
100
  if (h3Event.method === "POST") {
122
101
  const contentType = request.headers.get("content-type");
123
- const h3Request = h3Event.node.req;
124
- // This should never be the case in "proper" Nitro presets since node.req has to be IncomingMessage,
125
- // But the new azure-functions preset for some reason uses a ReadableStream in node.req (#1521)
126
- const isReadableStream = h3Request instanceof ReadableStream;
127
- const hasReadableStream = h3Request.body instanceof ReadableStream;
128
- const isH3EventBodyStreamLocked = (isReadableStream && h3Request.locked) ||
129
- (hasReadableStream && h3Request.body.locked);
130
- const requestBody = isReadableStream ? h3Request : h3Request.body;
131
102
  if (contentType?.startsWith("multipart/form-data") ||
132
103
  contentType?.startsWith("application/x-www-form-urlencoded")) {
133
- // workaround for https://github.com/unjs/nitro/issues/1721
134
- // (issue only in edge runtimes and netlify preset)
135
- parsed.push(await (isH3EventBodyStreamLocked
136
- ? request
137
- : new Request(request, { ...request, body: requestBody })).formData());
138
- // what should work when #1721 is fixed
139
- // parsed.push(await request.formData);
104
+ parsed.push(await event.request.formData());
140
105
  }
141
106
  else if (contentType?.startsWith("application/json")) {
142
- // workaround for https://github.com/unjs/nitro/issues/1721
143
- // (issue only in edge runtimes and netlify preset)
144
- const tmpReq = isH3EventBodyStreamLocked
145
- ? request
146
- : new Request(request, { ...request, body: requestBody });
147
- // what should work when #1721 is fixed
148
- // just use request.json() here
149
- parsed = fromJSON(await tmpReq.json(), {
107
+ parsed = fromJSON(await event.request.json(), {
150
108
  plugins: [
151
109
  CustomEventPlugin,
152
110
  DOMExceptionPlugin,
@@ -157,17 +115,17 @@ async function handleServerFunction(h3Event) {
157
115
  RequestPlugin,
158
116
  ResponsePlugin,
159
117
  URLSearchParamsPlugin,
160
- URLPlugin
161
- ]
118
+ URLPlugin,
119
+ ],
162
120
  });
163
121
  }
164
122
  }
165
123
  try {
166
124
  let result = await provideRequestEvent(event, async () => {
167
- /* @ts-ignore */
125
+ /* @ts-expect-error */
168
126
  sharedConfig.context = { event };
169
127
  event.locals.serverFunctionMeta = {
170
- id: functionId + "#" + name
128
+ id: functionId
171
129
  };
172
130
  return serverFunction(...parsed);
173
131
  });
@@ -184,7 +142,7 @@ async function handleServerFunction(h3Event) {
184
142
  mergeResponseHeaders(h3Event, result.headers);
185
143
  // forward non-redirect statuses
186
144
  if (result.status && (result.status < 300 || result.status >= 400))
187
- setResponseStatus(h3Event, result.status);
145
+ h3Event.res.status = result.status;
188
146
  if (result.customBody) {
189
147
  result = await result.customBody();
190
148
  }
@@ -195,7 +153,7 @@ async function handleServerFunction(h3Event) {
195
153
  // handle no JS success case
196
154
  if (!instance)
197
155
  return handleNoJS(result, request, parsed);
198
- setHeader(h3Event, "content-type", "text/javascript");
156
+ h3Event.res.headers.set("content-type", "text/javascript");
199
157
  return serializeToStream(instance, result);
200
158
  }
201
159
  catch (x) {
@@ -207,24 +165,25 @@ async function handleServerFunction(h3Event) {
207
165
  if (x.headers)
208
166
  mergeResponseHeaders(h3Event, x.headers);
209
167
  // forward non-redirect statuses
210
- if (x.status && (!instance || x.status < 300 || x.status >= 400))
211
- setResponseStatus(h3Event, x.status);
168
+ if (x.status &&
169
+ (!instance || x.status < 300 || x.status >= 400))
170
+ h3Event.res.status = x.status;
212
171
  if (x.customBody) {
213
172
  x = x.customBody();
214
173
  }
215
- else if (x.body == undefined)
174
+ else if (x.body === undefined)
216
175
  x = null;
217
- setHeader(h3Event, "X-Error", "true");
176
+ h3Event.res.headers.set("X-Error", "true");
218
177
  }
219
178
  else if (instance) {
220
179
  const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
221
- setHeader(h3Event, "X-Error", error.replace(/[\r\n]+/g, ""));
180
+ h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
222
181
  }
223
182
  else {
224
183
  x = handleNoJS(x, request, parsed, true);
225
184
  }
226
185
  if (instance) {
227
- setHeader(h3Event, "content-type", "text/javascript");
186
+ h3Event.res.headers.set("content-type", "text/javascript");
228
187
  return serializeToStream(instance, x);
229
188
  }
230
189
  return x;
@@ -238,24 +197,29 @@ function handleNoJS(result, request, parsed, thrown) {
238
197
  if (result instanceof Response) {
239
198
  headers = new Headers(result.headers);
240
199
  if (result.headers.has("Location")) {
241
- headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.SERVER_BASE_URL).toString());
200
+ headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.BASE_URL).toString());
242
201
  statusCode = getExpectedRedirectStatus(result);
243
202
  }
244
203
  }
245
204
  else
246
- headers = new Headers({ Location: new URL(request.headers.get("referer")).toString() });
205
+ headers = new Headers({
206
+ Location: new URL(request.headers.get("referer")).toString(),
207
+ });
247
208
  if (result) {
248
209
  headers.append("Set-Cookie", `flash=${encodeURIComponent(JSON.stringify({
249
210
  url: url.pathname + url.search,
250
211
  result: isError ? result.message : result,
251
212
  thrown: thrown,
252
213
  error: isError,
253
- input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
214
+ input: [
215
+ ...parsed.slice(0, -1),
216
+ [...parsed[parsed.length - 1].entries()],
217
+ ],
254
218
  }))}; Secure; HttpOnly;`);
255
219
  }
256
220
  return new Response(null, {
257
221
  status: statusCode,
258
- headers
222
+ headers,
259
223
  });
260
224
  }
261
225
  let App;
@@ -263,25 +227,33 @@ function createSingleFlightHeaders(sourceEvent) {
263
227
  // cookie handling logic is pretty simplistic so this might be imperfect
264
228
  // unclear if h3 internals are available on all platforms but we need a way to
265
229
  // update request headers on the underlying H3 event.
266
- const headers = new Headers(sourceEvent.request.headers);
230
+ const headers = sourceEvent.request.headers;
267
231
  const cookies = parseCookies(sourceEvent.nativeEvent);
268
232
  const SetCookies = sourceEvent.response.headers.getSetCookie();
269
233
  headers.delete("cookie");
270
- let useH3Internals = false;
271
- if (sourceEvent.nativeEvent.node?.req) {
272
- useH3Internals = true;
273
- sourceEvent.nativeEvent.node.req.headers.cookie = "";
274
- }
275
- SetCookies.forEach(cookie => {
234
+ // let useH3Internals = false;
235
+ // if (sourceEvent.nativeEvent.node?.req) {
236
+ // useH3Internals = true;
237
+ // sourceEvent.nativeEvent.node.req.headers.cookie = "";
238
+ // }
239
+ SetCookies.forEach((cookie) => {
276
240
  if (!cookie)
277
241
  return;
278
- const keyValue = cookie.split(";")[0];
279
- const [key, value] = keyValue.split("=");
280
- key && value && (cookies[key] = value);
242
+ const { maxAge, expires, name, value } = parseSetCookie(cookie);
243
+ if (maxAge != null && maxAge <= 0) {
244
+ delete cookies[name];
245
+ return;
246
+ }
247
+ if (expires != null && expires.getTime() <= Date.now()) {
248
+ delete cookies[name];
249
+ return;
250
+ }
251
+ cookies[name] = value;
281
252
  });
282
253
  Object.entries(cookies).forEach(([key, value]) => {
283
254
  headers.append("cookie", `${key}=${value}`);
284
- useH3Internals && (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
255
+ // useH3Internals &&
256
+ // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
285
257
  });
286
258
  return headers;
287
259
  }
@@ -292,21 +264,23 @@ async function handleSingleFlight(sourceEvent, result) {
292
264
  if (result.headers.has("X-Revalidate"))
293
265
  revalidate = result.headers.get("X-Revalidate").split(",");
294
266
  if (result.headers.has("Location"))
295
- url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin + import.meta.env.SERVER_BASE_URL).toString();
267
+ url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin +
268
+ import.meta.env.BASE_URL).toString();
296
269
  }
297
- const event = cloneEvent(sourceEvent);
298
- event.request = new Request(url, { headers: createSingleFlightHeaders(sourceEvent) });
270
+ const event = { ...sourceEvent };
271
+ event.request = new Request(url, {
272
+ headers: createSingleFlightHeaders(sourceEvent),
273
+ });
299
274
  return await provideRequestEvent(event, async () => {
300
275
  await createPageEvent(event);
301
- /* @ts-ignore */
302
- App || (App = (await import("#start/app")).default);
303
- /* @ts-ignore */
276
+ App || (App = (await import("solid-start:app")).default);
277
+ /* @ts-expect-error */
304
278
  event.router.dataOnly = revalidate || true;
305
- /* @ts-ignore */
279
+ /* @ts-expect-error */
306
280
  event.router.previousUrl = sourceEvent.request.headers.get("referer");
307
281
  try {
308
282
  renderToString(() => {
309
- /* @ts-ignore */
283
+ /* @ts-expect-error */
310
284
  sharedConfig.context.event = event;
311
285
  App();
312
286
  });
@@ -314,7 +288,7 @@ async function handleSingleFlight(sourceEvent, result) {
314
288
  catch (e) {
315
289
  console.log(e);
316
290
  }
317
- /* @ts-ignore */
291
+ /* @ts-expect-error */
318
292
  const body = event.router.data;
319
293
  if (!body)
320
294
  return result;
@@ -339,4 +313,3 @@ async function handleSingleFlight(sourceEvent, result) {
339
313
  return result;
340
314
  });
341
315
  }
342
- export default eventHandler(handleServerFunction);
@@ -0,0 +1,3 @@
1
+ import { type Component } from "solid-js";
2
+ export declare function createServerReference(id: string): (...args: any[]) => Promise<any>;
3
+ export declare function createClientReference(Component: Component<any>, id: string): Component<any>;
@@ -1,6 +1,5 @@
1
1
  import { deserialize, toJSONAsync } from "seroval";
2
2
  import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
3
- import { createIslandReference } from "../server/islands/index";
4
3
  class SerovalChunkReader {
5
4
  reader;
6
5
  buffer;
@@ -44,9 +43,6 @@ class SerovalChunkReader {
44
43
  // deserialize the data
45
44
  const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
46
45
  const bytes = Number.parseInt(head, 16); // ;0x00000000;
47
- if (Number.isNaN(bytes)) {
48
- throw new Error(`Malformed server function stream header: ${head}`);
49
- }
50
46
  // Check if the buffer has enough bytes to be parsed
51
47
  while (bytes > this.buffer.length - 12) {
52
48
  // If it's not enough, and the reader is done
@@ -160,18 +156,21 @@ async function fetchServerFunction(base, id, options, args) {
160
156
  }
161
157
  return result;
162
158
  }
163
- export function createServerReference(fn, id, name) {
164
- const baseURL = import.meta.env.SERVER_BASE_URL;
159
+ export function createServerReference(id) {
160
+ let baseURL = import.meta.env.BASE_URL ?? "/";
161
+ if (!baseURL.endsWith("/"))
162
+ baseURL += "/";
163
+ const fn = (...args) => fetchServerFunction(`${baseURL}_server`, id, {}, args);
165
164
  return new Proxy(fn, {
166
165
  get(target, prop, receiver) {
167
166
  if (prop === "url") {
168
- return `${baseURL}/_server?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
167
+ return `${baseURL}_server?id=${encodeURIComponent(id)}`;
169
168
  }
170
169
  if (prop === "GET") {
171
170
  return receiver.withOptions({ method: "GET" });
172
171
  }
173
172
  if (prop === "withOptions") {
174
- const url = `${baseURL}/_server/?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
173
+ const url = `${baseURL}_server?id=${encodeURIComponent(id)}`;
175
174
  return (options) => {
176
175
  const fn = async (...args) => {
177
176
  const encodeArgs = options.method && options.method.toUpperCase() === "GET";
@@ -180,7 +179,7 @@ export function createServerReference(fn, id, name) {
180
179
  (args.length
181
180
  ? `&args=${encodeURIComponent(JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))))}`
182
181
  : "")
183
- : `${baseURL}/_server`, `${id}#${name}`, options, encodeArgs ? [] : args);
182
+ : `${baseURL}_server`, id, options, encodeArgs ? [] : args);
184
183
  };
185
184
  fn.url = url;
186
185
  return fn;
@@ -188,14 +187,8 @@ export function createServerReference(fn, id, name) {
188
187
  }
189
188
  return target[prop];
190
189
  },
191
- apply(target, thisArg, args) {
192
- return fetchServerFunction(`${baseURL}/_server`, `${id}#${name}`, {}, args);
193
- }
194
190
  });
195
191
  }
196
- export function createClientReference(Component, id, name) {
197
- if (typeof Component === "function") {
198
- return createIslandReference(Component, id, name);
199
- }
192
+ export function createClientReference(Component, id) {
200
193
  return Component;
201
194
  }
@@ -1,5 +1,5 @@
1
1
  import type { Component } from "solid-js";
2
- import type { DocumentComponentProps } from "../types";
2
+ import type { DocumentComponentProps } from "../types.ts";
3
3
  /**
4
4
  *
5
5
  * Read more: https://docs.solidjs.com/solid-start/reference/server/start-server
@@ -1,6 +1,7 @@
1
1
  import { NoHydration, getRequestEvent, ssr } from "solid-js/web";
2
- import { TopErrorBoundary } from "../../shared/ErrorBoundary";
3
- import { renderAsset } from "../renderAsset";
2
+ import { getSsrManifest } from "../manifest/ssr-manifest.js";
3
+ import { TopErrorBoundary } from "../../shared/ErrorBoundary.jsx";
4
+ import { useAssets } from "../assets/index.js";
4
5
  const docType = ssr("<!DOCTYPE html>");
5
6
  /**
6
7
  *
@@ -10,16 +11,13 @@ export function StartServer(props) {
10
11
  const context = getRequestEvent();
11
12
  // @ts-ignore
12
13
  const nonce = context.nonce;
14
+ useAssets(context.assets, nonce);
13
15
  return (<NoHydration>
14
16
  {docType}
15
17
  <TopErrorBoundary>
16
- <props.document assets={<>{context.assets.map((m) => renderAsset(m))}</>} scripts={nonce ? (<>
17
- <script nonce={nonce} innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
18
- <script type="module" src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
19
- </>) : (<>
20
- <script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
21
- <script type="module" src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
22
- </>)}/>
18
+ <props.document scripts={<>
19
+ <script type="module" src={getSsrManifest("client").path(import.meta.env.START_CLIENT_ENTRY)}/>
20
+ </>}/>
23
21
  </TopErrorBoundary>
24
22
  </NoHydration>);
25
23
  }
@@ -1,7 +1,7 @@
1
- import { FetchEvent, HandlerOptions, PageEvent } from "../types";
1
+ import type { JSX } from "solid-js";
2
+ import type { HandlerOptions, PageEvent } from "../types.ts";
2
3
  /**
3
4
  *
4
5
  * Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
5
6
  */
6
- export declare function createHandler(fn: (context: PageEvent) => unknown, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions), routerLoad?: (event: FetchEvent) => Promise<void>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
7
- export declare function createPageEvent(ctx: FetchEvent): Promise<PageEvent>;
7
+ export declare function createHandler(fn: (context: PageEvent) => JSX.Element, options?: HandlerOptions | ((context: PageEvent) => HandlerOptions)): import("h3").H3;