@solidjs/start 1.2.1 → 2.0.0-alpha.1

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 (191) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -2
  3. package/dist/client/StartClient.d.ts +0 -1
  4. package/dist/client/StartClient.jsx +2 -4
  5. package/dist/client/index.d.ts +2 -3
  6. package/dist/client/index.jsx +2 -4
  7. package/dist/client/mount.d.ts +1 -7
  8. package/dist/client/mount.js +1 -91
  9. package/dist/client/spa/index.d.ts +1 -2
  10. package/dist/client/spa/index.jsx +1 -2
  11. package/dist/config/constants.d.ts +16 -0
  12. package/dist/config/constants.js +16 -0
  13. package/dist/config/dev-server.d.ts +2 -0
  14. package/dist/config/dev-server.js +108 -0
  15. package/dist/config/fs-router.d.ts +37 -0
  16. package/dist/config/fs-router.js +141 -0
  17. package/dist/config/fs-routes/fs-watcher.d.ts +3 -0
  18. package/dist/config/fs-routes/fs-watcher.js +49 -0
  19. package/dist/config/fs-routes/index.d.ts +7 -0
  20. package/dist/config/fs-routes/index.js +107 -0
  21. package/dist/config/fs-routes/router.d.ts +37 -0
  22. package/dist/config/fs-routes/router.js +136 -0
  23. package/dist/config/fs-routes/tree-shake.d.ts +2 -0
  24. package/dist/config/fs-routes/tree-shake.js +348 -0
  25. package/dist/config/index.d.ts +10 -0
  26. package/dist/config/index.js +214 -0
  27. package/dist/config/lazy.d.ts +3 -0
  28. package/dist/config/lazy.js +82 -0
  29. package/dist/config/manifest.d.ts +3 -0
  30. package/dist/config/manifest.js +74 -0
  31. package/dist/config/utils.d.ts +4 -0
  32. package/dist/config/utils.js +6 -0
  33. package/dist/config/vite-utils.d.ts +16 -0
  34. package/dist/config/vite-utils.js +81 -0
  35. package/dist/http/index.d.ts +81 -0
  36. package/dist/http/index.js +129 -0
  37. package/dist/index.d.ts +5 -5
  38. package/dist/index.jsx +5 -5
  39. package/dist/middleware/index.d.ts +6 -6
  40. package/dist/middleware/index.js +39 -0
  41. package/dist/{router/FileRoutes.js → router.jsx} +7 -8
  42. package/dist/server/StartServer.d.ts +3 -3
  43. package/dist/server/StartServer.jsx +9 -63
  44. package/dist/server/assets/index.d.ts +2 -0
  45. package/dist/server/assets/index.js +52 -0
  46. package/dist/server/assets/render.d.ts +19 -0
  47. package/dist/server/{renderAsset.jsx → assets/render.jsx} +1 -1
  48. package/dist/server/collect-styles.d.ts +3 -0
  49. package/dist/server/collect-styles.js +69 -0
  50. package/dist/server/fetchEvent.d.ts +4 -3
  51. package/dist/server/fetchEvent.js +12 -74
  52. package/dist/server/fetchEvent.spec.js +18 -197
  53. package/dist/server/handler.d.ts +6 -12
  54. package/dist/server/handler.js +193 -96
  55. package/dist/server/index.d.ts +9 -6
  56. package/dist/server/index.jsx +14 -6
  57. package/dist/server/manifest/client-manifest.d.ts +9 -0
  58. package/dist/server/manifest/client-manifest.js +6 -0
  59. package/dist/server/manifest/dev-client-manifest.d.ts +4 -0
  60. package/dist/server/manifest/dev-client-manifest.js +24 -0
  61. package/dist/server/manifest/dev-ssr-manifest.d.ts +5 -0
  62. package/dist/server/manifest/dev-ssr-manifest.js +23 -0
  63. package/dist/server/manifest/prod-client-manifest.d.ts +5 -0
  64. package/dist/server/manifest/prod-client-manifest.js +26 -0
  65. package/dist/server/manifest/prod-ssr-manifest.d.ts +6 -0
  66. package/dist/server/manifest/prod-ssr-manifest.js +85 -0
  67. package/dist/server/manifest/ssr-manifest.d.ts +4 -0
  68. package/dist/server/manifest/ssr-manifest.js +6 -0
  69. package/dist/{router → server}/routes.d.ts +5 -10
  70. package/dist/{router → server}/routes.js +32 -33
  71. package/dist/{runtime → server}/server-fns-runtime.d.ts +1 -1
  72. package/dist/{runtime → server}/server-fns-runtime.js +8 -7
  73. package/dist/server/server-functions-handler.d.ts +2 -0
  74. package/dist/{runtime/server-handler.js → server/server-functions-handler.js} +57 -97
  75. package/dist/server/server-runtime.d.ts +3 -0
  76. package/dist/{runtime → server}/server-runtime.js +17 -24
  77. package/dist/server/spa/StartServer.d.ts +1 -1
  78. package/dist/server/spa/StartServer.jsx +7 -9
  79. package/dist/server/spa/handler.d.ts +3 -3
  80. package/dist/server/spa/handler.js +9 -11
  81. package/dist/server/spa/index.d.ts +4 -3
  82. package/dist/server/spa/index.jsx +4 -3
  83. package/dist/server/types.d.ts +7 -9
  84. package/dist/server/util.d.ts +2 -0
  85. package/dist/server/util.js +8 -0
  86. package/dist/shared/ErrorBoundary.jsx +2 -2
  87. package/dist/shared/HttpHeader.jsx +4 -2
  88. package/dist/shared/{HttpStatusCode.jsx → HttpStatusCode.js} +3 -1
  89. package/dist/shared/dev-overlay/CodeView.d.ts +1 -1
  90. package/dist/shared/dev-overlay/CodeView.jsx +23 -34
  91. package/dist/shared/dev-overlay/DevOverlayDialog.d.ts +2 -2
  92. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +73 -64
  93. package/dist/shared/dev-overlay/createStackFrame.js +3 -3
  94. package/dist/shared/dev-overlay/get-source-map.d.ts +1 -1
  95. package/dist/shared/dev-overlay/get-source-map.js +5 -5
  96. package/dist/shared/dev-overlay/icons.d.ts +10 -10
  97. package/dist/shared/dev-overlay/icons.jsx +91 -91
  98. package/dist/shared/dev-overlay/index.jsx +6 -9
  99. package/dist/shared/lazy.d.ts +3 -0
  100. package/dist/shared/lazy.js +42 -0
  101. package/dist/shared/serverFunction.d.ts +1 -1
  102. package/env.d.ts +2 -19
  103. package/package.json +44 -65
  104. package/scripts/build.js +15 -0
  105. package/scripts/validate-imports.js +316 -0
  106. package/src/client/StartClient.tsx +34 -0
  107. package/src/client/index.tsx +2 -0
  108. package/src/client/mount.ts +1 -0
  109. package/src/client/spa/index.tsx +9 -0
  110. package/src/config/constants.ts +19 -0
  111. package/src/config/dev-server.ts +145 -0
  112. package/{config/fs-router.js → src/config/fs-router.ts} +49 -29
  113. package/src/config/fs-routes/fs-watcher.ts +77 -0
  114. package/src/config/fs-routes/index.ts +136 -0
  115. package/src/config/fs-routes/router.ts +169 -0
  116. package/src/config/fs-routes/tree-shake.ts +371 -0
  117. package/src/config/index.ts +233 -0
  118. package/src/config/lazy.ts +100 -0
  119. package/src/config/manifest.ts +84 -0
  120. package/src/config/utils.ts +5 -0
  121. package/src/config/vite-utils.ts +109 -0
  122. package/src/env.d.ts +17 -0
  123. package/src/http/index.ts +216 -0
  124. package/src/index.tsx +7 -0
  125. package/src/internal.d.ts +14 -0
  126. package/src/middleware/index.ts +72 -0
  127. package/src/router.tsx +37 -0
  128. package/src/server/StartServer.tsx +56 -0
  129. package/src/server/assets/index.ts +70 -0
  130. package/src/server/assets/render.tsx +46 -0
  131. package/src/server/collect-styles.ts +87 -0
  132. package/src/server/fetchEvent.spec.ts +85 -0
  133. package/src/server/fetchEvent.ts +36 -0
  134. package/src/server/handler.ts +257 -0
  135. package/src/server/index.tsx +29 -0
  136. package/src/server/manifest/client-manifest.ts +8 -0
  137. package/src/server/manifest/dev-client-manifest.ts +21 -0
  138. package/src/server/manifest/dev-ssr-manifest.ts +23 -0
  139. package/src/server/manifest/prod-client-manifest.ts +21 -0
  140. package/src/server/manifest/prod-ssr-manifest.ts +109 -0
  141. package/src/server/manifest/ssr-manifest.ts +10 -0
  142. package/src/server/routes.ts +126 -0
  143. package/src/server/server-fns-runtime.ts +31 -0
  144. package/src/server/server-functions-handler.ts +339 -0
  145. package/src/server/server-runtime.ts +240 -0
  146. package/src/server/spa/StartServer.tsx +40 -0
  147. package/src/server/spa/handler.ts +29 -0
  148. package/src/server/spa/index.tsx +5 -0
  149. package/src/server/types.ts +82 -0
  150. package/src/server/util.ts +12 -0
  151. package/src/shared/ErrorBoundary.tsx +52 -0
  152. package/src/shared/GET.ts +8 -0
  153. package/src/shared/HttpHeader.tsx +42 -0
  154. package/src/shared/HttpStatusCode.ts +27 -0
  155. package/src/shared/clientOnly.ts +44 -0
  156. package/src/shared/dev-overlay/CodeView.tsx +92 -0
  157. package/src/shared/dev-overlay/DevOverlayDialog.tsx +316 -0
  158. package/src/shared/dev-overlay/createStackFrame.ts +74 -0
  159. package/src/shared/dev-overlay/download.ts +6 -0
  160. package/src/shared/dev-overlay/env.d.ts +4 -0
  161. package/src/shared/dev-overlay/get-source-map.ts +33 -0
  162. package/src/shared/dev-overlay/icons.tsx +456 -0
  163. package/src/shared/dev-overlay/index.tsx +63 -0
  164. package/src/shared/dev-overlay/styles.css +292 -0
  165. package/src/shared/lazy.ts +52 -0
  166. package/src/shared/serverFunction.ts +10 -0
  167. package/src/virtual.d.ts +27 -0
  168. package/tsconfig.json +23 -0
  169. package/vitest.config.ts +9 -0
  170. package/config/index.d.ts +0 -40
  171. package/config/index.js +0 -304
  172. package/config/server-components.js +0 -106
  173. package/dist/client/islands.d.ts +0 -7
  174. package/dist/client/islands.jsx +0 -10
  175. package/dist/middleware/index.jsx +0 -35
  176. package/dist/router/index.d.ts +0 -1
  177. package/dist/router/index.jsx +0 -2
  178. package/dist/router/lazyRoute.d.ts +0 -6
  179. package/dist/router/lazyRoute.js +0 -53
  180. package/dist/runtime/server-handler.d.ts +0 -2
  181. package/dist/runtime/server-runtime.d.ts +0 -3
  182. package/dist/server/islands/index.d.ts +0 -19
  183. package/dist/server/islands/index.jsx +0 -62
  184. package/dist/server/islands/utils.d.ts +0 -1
  185. package/dist/server/islands/utils.jsx +0 -85
  186. package/dist/server/pageEvent.d.ts +0 -2
  187. package/dist/server/pageEvent.js +0 -56
  188. package/dist/server/renderAsset.d.ts +0 -2
  189. /package/dist/{router/FileRoutes.d.ts → router.d.ts} +0 -0
  190. /package/dist/shared/{clientOnly.jsx → clientOnly.js} +0 -0
  191. /package/dist/shared/{serverFunction.jsx → serverFunction.js} +0 -0
@@ -1,18 +1,14 @@
1
- /// <reference types="vinxi/types/server" />
1
+ import { getServerFnById } from "solidstart:server-fn-manifest";
2
2
  import { parseSetCookie } from "cookie-es";
3
+ import { parseCookies } from "h3";
3
4
  import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
4
- // @ts-ignore
5
- import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
5
+ import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin, } from "seroval-plugins/web";
6
6
  import { sharedConfig } from "solid-js";
7
7
  import { renderToString } from "solid-js/web";
8
8
  import { provideRequestEvent } from "solid-js/web/storage";
9
- import { eventHandler, parseCookies, setHeader, setResponseStatus } from "vinxi/http";
10
- import invariant from "vinxi/lib/invariant";
11
- import { cloneEvent, getFetchEvent, mergeResponseHeaders } from "../server/fetchEvent";
12
- import { getExpectedRedirectStatus } from "../server/handler";
13
- import { createPageEvent } from "../server/pageEvent";
14
- // @ts-ignore
15
- 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";
16
12
  function createChunk(data) {
17
13
  const encodeData = new TextEncoder().encode(data);
18
14
  const bytes = encodeData.length;
@@ -39,7 +35,7 @@ function serializeToStream(id, value) {
39
35
  RequestPlugin,
40
36
  ResponsePlugin,
41
37
  URLSearchParamsPlugin,
42
- URLPlugin
38
+ URLPlugin,
43
39
  ],
44
40
  onSerialize(data, initial) {
45
41
  controller.enqueue(createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data));
@@ -49,52 +45,32 @@ function serializeToStream(id, value) {
49
45
  },
50
46
  onError(error) {
51
47
  controller.error(error);
52
- }
48
+ },
53
49
  });
54
- }
50
+ },
55
51
  });
56
52
  }
57
- async function handleServerFunction(h3Event) {
53
+ export async function handleServerFunction(h3Event) {
58
54
  const event = getFetchEvent(h3Event);
59
55
  const request = event.request;
60
56
  const serverReference = request.headers.get("X-Server-Id");
61
57
  const instance = request.headers.get("X-Server-Instance");
62
58
  const singleFlight = request.headers.has("X-Single-Flight");
63
59
  const url = new URL(request.url);
64
- let functionId, name;
60
+ let functionId;
65
61
  if (serverReference) {
66
- invariant(typeof serverReference === "string", "Invalid server function");
67
- [functionId, name] = serverReference.split("#");
62
+ // invariant(typeof serverReference === "string", "Invalid server function");
63
+ [functionId] = serverReference.split("#");
68
64
  }
69
65
  else {
70
66
  functionId = url.searchParams.get("id");
71
- name = url.searchParams.get("name");
72
- if (!functionId || !name) {
67
+ if (!functionId) {
73
68
  return process.env.NODE_ENV === "development"
74
69
  ? new Response("Server function not found", { status: 404 })
75
70
  : new Response(null, { status: 404 });
76
71
  }
77
72
  }
78
- const serverFnInfo = serverFnManifest[functionId];
79
- let fnModule;
80
- if (!serverFnInfo) {
81
- return process.env.NODE_ENV === "development"
82
- ? new Response("Server function not found", { status: 404 })
83
- : new Response(null, { status: 404 });
84
- }
85
- if (process.env.NODE_ENV === "development") {
86
- // In dev, we use Vinxi to get the "server" server-side router
87
- // Then we use that router's devServer.ssrLoadModule to get the serverFn
88
- // This code comes from:
89
- // https://github.com/TanStack/router/blob/266f5cc863cd1a99809d1af2669e58b6b6db9a67/packages/start-server-functions-handler/src/index.tsx#L83-L87
90
- fnModule = await globalThis.app
91
- .getRouter("server-fns")
92
- .internals.devServer.ssrLoadModule(serverFnInfo.extractedFilename);
93
- }
94
- else {
95
- fnModule = await serverFnInfo.importer();
96
- }
97
- const serverFunction = fnModule[serverFnInfo.functionName];
73
+ const serverFunction = await getServerFnById(functionId);
98
74
  let parsed = [];
99
75
  // grab bound arguments from url when no JS
100
76
  if (!instance || h3Event.method === "GET") {
@@ -113,41 +89,22 @@ async function handleServerFunction(h3Event) {
113
89
  RequestPlugin,
114
90
  ResponsePlugin,
115
91
  URLSearchParamsPlugin,
116
- URLPlugin
117
- ]
92
+ URLPlugin,
93
+ ],
118
94
  })
119
- : json).forEach((arg) => parsed.push(arg));
95
+ : json).forEach((arg) => {
96
+ parsed.push(arg);
97
+ });
120
98
  }
121
99
  }
122
100
  if (h3Event.method === "POST") {
123
101
  const contentType = request.headers.get("content-type");
124
- const h3Request = h3Event.node.req;
125
- // This should never be the case in "proper" Nitro presets since node.req has to be IncomingMessage,
126
- // But the new azure-functions preset for some reason uses a ReadableStream in node.req (#1521)
127
- const isReadableStream = h3Request instanceof ReadableStream;
128
- const hasReadableStream = h3Request.body instanceof ReadableStream;
129
- const isH3EventBodyStreamLocked = (isReadableStream && h3Request.locked) ||
130
- (hasReadableStream && h3Request.body.locked);
131
- const requestBody = isReadableStream ? h3Request : h3Request.body;
132
102
  if (contentType?.startsWith("multipart/form-data") ||
133
103
  contentType?.startsWith("application/x-www-form-urlencoded")) {
134
- // workaround for https://github.com/unjs/nitro/issues/1721
135
- // (issue only in edge runtimes and netlify preset)
136
- parsed.push(await (isH3EventBodyStreamLocked
137
- ? request
138
- : new Request(request, { ...request, body: requestBody })).formData());
139
- // what should work when #1721 is fixed
140
- // parsed.push(await request.formData);
104
+ parsed.push(await event.request.formData());
141
105
  }
142
106
  else if (contentType?.startsWith("application/json")) {
143
- // workaround for https://github.com/unjs/nitro/issues/1721
144
- // (issue only in edge runtimes and netlify preset)
145
- const tmpReq = isH3EventBodyStreamLocked
146
- ? request
147
- : new Request(request, { ...request, body: requestBody });
148
- // what should work when #1721 is fixed
149
- // just use request.json() here
150
- parsed = fromJSON(await tmpReq.json(), {
107
+ parsed = fromJSON(await event.request.json(), {
151
108
  plugins: [
152
109
  CustomEventPlugin,
153
110
  DOMExceptionPlugin,
@@ -158,17 +115,17 @@ async function handleServerFunction(h3Event) {
158
115
  RequestPlugin,
159
116
  ResponsePlugin,
160
117
  URLSearchParamsPlugin,
161
- URLPlugin
162
- ]
118
+ URLPlugin,
119
+ ],
163
120
  });
164
121
  }
165
122
  }
166
123
  try {
167
124
  let result = await provideRequestEvent(event, async () => {
168
- /* @ts-ignore */
125
+ /* @ts-expect-error */
169
126
  sharedConfig.context = { event };
170
127
  event.locals.serverFunctionMeta = {
171
- id: functionId + "#" + name
128
+ id: functionId,
172
129
  };
173
130
  return serverFunction(...parsed);
174
131
  });
@@ -185,7 +142,7 @@ async function handleServerFunction(h3Event) {
185
142
  mergeResponseHeaders(h3Event, result.headers);
186
143
  // forward non-redirect statuses
187
144
  if (result.status && (result.status < 300 || result.status >= 400))
188
- setResponseStatus(h3Event, result.status);
145
+ h3Event.res.status = result.status;
189
146
  if (result.customBody) {
190
147
  result = await result.customBody();
191
148
  }
@@ -196,7 +153,7 @@ async function handleServerFunction(h3Event) {
196
153
  // handle no JS success case
197
154
  if (!instance)
198
155
  return handleNoJS(result, request, parsed);
199
- setHeader(h3Event, "content-type", "text/javascript");
156
+ h3Event.res.headers.set("content-type", "text/javascript");
200
157
  return serializeToStream(instance, result);
201
158
  }
202
159
  catch (x) {
@@ -209,23 +166,23 @@ async function handleServerFunction(h3Event) {
209
166
  mergeResponseHeaders(h3Event, x.headers);
210
167
  // forward non-redirect statuses
211
168
  if (x.status && (!instance || x.status < 300 || x.status >= 400))
212
- setResponseStatus(h3Event, x.status);
169
+ h3Event.res.status = x.status;
213
170
  if (x.customBody) {
214
171
  x = x.customBody();
215
172
  }
216
- else if (x.body == undefined)
173
+ else if (x.body === undefined)
217
174
  x = null;
218
- setHeader(h3Event, "X-Error", "true");
175
+ h3Event.res.headers.set("X-Error", "true");
219
176
  }
220
177
  else if (instance) {
221
178
  const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
222
- setHeader(h3Event, "X-Error", error.replace(/[\r\n]+/g, ""));
179
+ h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
223
180
  }
224
181
  else {
225
182
  x = handleNoJS(x, request, parsed, true);
226
183
  }
227
184
  if (instance) {
228
- setHeader(h3Event, "content-type", "text/javascript");
185
+ h3Event.res.headers.set("content-type", "text/javascript");
229
186
  return serializeToStream(instance, x);
230
187
  }
231
188
  return x;
@@ -239,24 +196,26 @@ function handleNoJS(result, request, parsed, thrown) {
239
196
  if (result instanceof Response) {
240
197
  headers = new Headers(result.headers);
241
198
  if (result.headers.has("Location")) {
242
- headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.SERVER_BASE_URL).toString());
199
+ headers.set(`Location`, new URL(result.headers.get("Location"), url.origin + import.meta.env.BASE_URL).toString());
243
200
  statusCode = getExpectedRedirectStatus(result);
244
201
  }
245
202
  }
246
203
  else
247
- headers = new Headers({ Location: new URL(request.headers.get("referer")).toString() });
204
+ headers = new Headers({
205
+ Location: new URL(request.headers.get("referer")).toString(),
206
+ });
248
207
  if (result) {
249
208
  headers.append("Set-Cookie", `flash=${encodeURIComponent(JSON.stringify({
250
209
  url: url.pathname + url.search,
251
210
  result: isError ? result.message : result,
252
211
  thrown: thrown,
253
212
  error: isError,
254
- input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
213
+ input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]],
255
214
  }))}; Secure; HttpOnly;`);
256
215
  }
257
216
  return new Response(null, {
258
217
  status: statusCode,
259
- headers
218
+ headers,
260
219
  });
261
220
  }
262
221
  let App;
@@ -264,15 +223,15 @@ function createSingleFlightHeaders(sourceEvent) {
264
223
  // cookie handling logic is pretty simplistic so this might be imperfect
265
224
  // unclear if h3 internals are available on all platforms but we need a way to
266
225
  // update request headers on the underlying H3 event.
267
- const headers = new Headers(sourceEvent.request.headers);
226
+ const headers = sourceEvent.request.headers;
268
227
  const cookies = parseCookies(sourceEvent.nativeEvent);
269
228
  const SetCookies = sourceEvent.response.headers.getSetCookie();
270
229
  headers.delete("cookie");
271
- let useH3Internals = false;
272
- if (sourceEvent.nativeEvent.node?.req) {
273
- useH3Internals = true;
274
- sourceEvent.nativeEvent.node.req.headers.cookie = "";
275
- }
230
+ // let useH3Internals = false;
231
+ // if (sourceEvent.nativeEvent.node?.req) {
232
+ // useH3Internals = true;
233
+ // sourceEvent.nativeEvent.node.req.headers.cookie = "";
234
+ // }
276
235
  SetCookies.forEach(cookie => {
277
236
  if (!cookie)
278
237
  return;
@@ -289,7 +248,8 @@ function createSingleFlightHeaders(sourceEvent) {
289
248
  });
290
249
  Object.entries(cookies).forEach(([key, value]) => {
291
250
  headers.append("cookie", `${key}=${value}`);
292
- useH3Internals && (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
251
+ // useH3Internals &&
252
+ // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
293
253
  });
294
254
  return headers;
295
255
  }
@@ -300,21 +260,22 @@ async function handleSingleFlight(sourceEvent, result) {
300
260
  if (result.headers.has("X-Revalidate"))
301
261
  revalidate = result.headers.get("X-Revalidate").split(",");
302
262
  if (result.headers.has("Location"))
303
- url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin + import.meta.env.SERVER_BASE_URL).toString();
263
+ url = new URL(result.headers.get("Location"), new URL(sourceEvent.request.url).origin + import.meta.env.BASE_URL).toString();
304
264
  }
305
- const event = cloneEvent(sourceEvent);
306
- event.request = new Request(url, { headers: createSingleFlightHeaders(sourceEvent) });
265
+ const event = { ...sourceEvent };
266
+ event.request = new Request(url, {
267
+ headers: createSingleFlightHeaders(sourceEvent),
268
+ });
307
269
  return await provideRequestEvent(event, async () => {
308
270
  await createPageEvent(event);
309
- /* @ts-ignore */
310
- App || (App = (await import("#start/app")).default);
311
- /* @ts-ignore */
271
+ App || (App = (await import("solid-start:app")).default);
272
+ /* @ts-expect-error */
312
273
  event.router.dataOnly = revalidate || true;
313
- /* @ts-ignore */
274
+ /* @ts-expect-error */
314
275
  event.router.previousUrl = sourceEvent.request.headers.get("referer");
315
276
  try {
316
277
  renderToString(() => {
317
- /* @ts-ignore */
278
+ /* @ts-expect-error */
318
279
  sharedConfig.context.event = event;
319
280
  App();
320
281
  });
@@ -322,7 +283,7 @@ async function handleSingleFlight(sourceEvent, result) {
322
283
  catch (e) {
323
284
  console.log(e);
324
285
  }
325
- /* @ts-ignore */
286
+ /* @ts-expect-error */
326
287
  const body = event.router.data;
327
288
  if (!body)
328
289
  return result;
@@ -347,4 +308,3 @@ async function handleSingleFlight(sourceEvent, result) {
347
308
  return result;
348
309
  });
349
310
  }
350
- 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
- import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin } from "seroval-plugins/web";
3
- import { createIslandReference } from "../server/islands/index";
2
+ import { CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLPlugin, URLSearchParamsPlugin, } from "seroval-plugins/web";
4
3
  class SerovalChunkReader {
5
4
  reader;
6
5
  buffer;
@@ -31,7 +30,7 @@ class SerovalChunkReader {
31
30
  if (this.done) {
32
31
  return {
33
32
  done: true,
34
- value: undefined
33
+ value: undefined,
35
34
  };
36
35
  }
37
36
  // Otherwise, read a new chunk
@@ -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
@@ -64,7 +60,7 @@ class SerovalChunkReader {
64
60
  // Deserialize the chunk
65
61
  return {
66
62
  done: false,
67
- value: deserialize(partial)
63
+ value: deserialize(partial),
68
64
  };
69
65
  }
70
66
  async drain() {
@@ -100,8 +96,8 @@ function createRequest(base, id, instance, options) {
100
96
  headers: {
101
97
  ...options.headers,
102
98
  "X-Server-Id": id,
103
- "X-Server-Instance": instance
104
- }
99
+ "X-Server-Instance": instance,
100
+ },
105
101
  });
106
102
  }
107
103
  const plugins = [
@@ -114,7 +110,7 @@ const plugins = [
114
110
  RequestPlugin,
115
111
  ResponsePlugin,
116
112
  URLSearchParamsPlugin,
117
- URLPlugin
113
+ URLPlugin,
118
114
  ];
119
115
  async function fetchServerFunction(base, id, options, args) {
120
116
  const instance = `server-fn:${INSTANCE++}`;
@@ -126,12 +122,12 @@ async function fetchServerFunction(base, id, options, args) {
126
122
  ? createRequest(base, id, instance, {
127
123
  ...options,
128
124
  body: args[0],
129
- headers: { ...options.headers, "Content-Type": "application/x-www-form-urlencoded" }
125
+ headers: { ...options.headers, "Content-Type": "application/x-www-form-urlencoded" },
130
126
  })
131
127
  : createRequest(base, id, instance, {
132
128
  ...options,
133
129
  body: JSON.stringify(await Promise.resolve(toJSONAsync(args, { plugins }))),
134
- headers: { ...options.headers, "Content-Type": "application/json" }
130
+ headers: { ...options.headers, "Content-Type": "application/json" },
135
131
  }));
136
132
  if (response.headers.has("Location") ||
137
133
  response.headers.has("X-Revalidate") ||
@@ -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("vinxi/http").EventHandler<import("vinxi/http").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;
@@ -1,22 +1,20 @@
1
- import { createBaseHandler } from "../handler";
1
+ import { createBaseHandler } from "../handler.js";
2
+ import { getSsrManifest } from "../manifest/ssr-manifest.js";
2
3
  /**
3
4
  *
4
5
  * Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
5
6
  */
6
- export function createHandler(fn, options, routerLoad) {
7
- return createBaseHandler(fn, createPageEvent, options, routerLoad);
7
+ export function createHandler(fn, options) {
8
+ return createBaseHandler(createPageEvent, fn, options);
8
9
  }
9
- export async function createPageEvent(ctx) {
10
- const clientManifest = import.meta.env.MANIFEST["client"];
10
+ async function createPageEvent(ctx) {
11
+ const manifest = getSsrManifest("ssr");
11
12
  const pageEvent = Object.assign(ctx, {
12
- manifest: await clientManifest.json(),
13
- assets: [...(await clientManifest.inputs[clientManifest.handler].assets())],
13
+ manifest: "json" in manifest ? await manifest.json() : {},
14
+ assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
14
15
  routes: [],
15
16
  complete: false,
16
- // prevUrl: "",
17
- // mutation: false,
18
- // $type: FETCH_EVENT,
19
- $islands: new Set()
17
+ $islands: new Set(),
20
18
  });
21
19
  return pageEvent;
22
20
  }
@@ -1,3 +1,4 @@
1
- export * from "../types";
2
- export { StartServer } from "./StartServer";
3
- export { createHandler } from "./handler";
1
+ export { default as lazy } from "../../shared/lazy.ts";
2
+ export * from "../types.ts";
3
+ export { StartServer } from "./StartServer.tsx";
4
+ export { createHandler } from "./handler.ts";
@@ -1,4 +1,5 @@
1
1
  // @refresh skip
2
- export * from "../types";
3
- export { StartServer } from "./StartServer";
4
- export { createHandler } from "./handler";
2
+ export { default as lazy } from "../../shared/lazy.js";
3
+ export * from "../types.js";
4
+ export { StartServer } from "./StartServer.jsx";
5
+ export { createHandler } from "./handler.js";
@@ -1,8 +1,8 @@
1
+ import type { H3Event } from "h3";
1
2
  import type { JSX } from "solid-js";
2
- import { RequestEvent } from "solid-js/web";
3
- import { HTTPEvent } from "vinxi/http";
3
+ import type { RequestEvent } from "solid-js/web";
4
4
  export type DocumentComponentProps = {
5
- assets: JSX.Element;
5
+ assets?: JSX.Element;
6
6
  scripts: JSX.Element;
7
7
  children?: JSX.Element;
8
8
  };
@@ -50,23 +50,21 @@ export interface FetchEvent {
50
50
  response: ResponseStub;
51
51
  clientAddress?: string;
52
52
  locals: App.RequestEventLocals;
53
- nativeEvent: HTTPEvent;
53
+ nativeEvent: H3Event;
54
54
  }
55
55
  export interface PageEvent extends RequestEvent {
56
- manifest: any;
57
- assets: any;
56
+ assets: any[];
58
57
  routes: any[];
59
58
  $islands: Set<string>;
60
59
  complete: boolean;
60
+ nonce?: string;
61
61
  }
62
62
  export interface APIEvent extends FetchEvent {
63
63
  params: {
64
64
  [key: string]: string;
65
65
  };
66
66
  }
67
- export interface APIHandler {
68
- (event: APIEvent): Promise<any>;
69
- }
67
+ export type APIHandler = (event: APIEvent) => Promise<any>;
70
68
  export interface ServerFunctionMeta {
71
69
  id: string;
72
70
  }
@@ -0,0 +1,2 @@
1
+ import type { ResponseStub } from "./types.ts";
2
+ export declare function getExpectedRedirectStatus(response: ResponseStub): number;
@@ -0,0 +1,8 @@
1
+ // according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages
2
+ const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
3
+ export function getExpectedRedirectStatus(response) {
4
+ if (response.status && validRedirectStatuses.has(response.status)) {
5
+ return response.status;
6
+ }
7
+ return 302;
8
+ }
@@ -1,8 +1,8 @@
1
1
  // @refresh skip
2
2
  import { ErrorBoundary as DefaultErrorBoundary, catchError } from "solid-js";
3
3
  import { isServer } from "solid-js/web";
4
- import { HttpStatusCode } from "./HttpStatusCode";
5
- import { DevOverlay } from "./dev-overlay";
4
+ import { HttpStatusCode } from "./HttpStatusCode.js";
5
+ import { DevOverlay } from "./dev-overlay/index.jsx";
6
6
  export const ErrorBoundary = import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY
7
7
  ? (props) => <DevOverlay>{props.children}</DevOverlay>
8
8
  : (props) => {
@@ -1,6 +1,7 @@
1
1
  // @refresh skip
2
2
  import { onCleanup } from "solid-js";
3
3
  import { getRequestEvent, isServer } from "solid-js/web";
4
+ import { appendHeader, setHeader } from "../http/index.js";
4
5
  /**
5
6
  *
6
7
  * Read more: https://docs.solidjs.com/solid-start/reference/server/http-header
@@ -9,10 +10,11 @@ export const HttpHeader = isServer
9
10
  ? (props) => {
10
11
  const event = getRequestEvent();
11
12
  if (props.append)
12
- event.response.headers.append(props.name, props.value);
13
+ appendHeader(props.name, props.value);
13
14
  else
14
- event.response.headers.set(props.name, props.value);
15
+ setHeader(props.name, props.value);
15
16
  onCleanup(() => {
17
+ // @ts-expect-error
16
18
  if (event.nativeEvent.handled || event.complete)
17
19
  return;
18
20
  const value = event.response.headers.get(props.name);
@@ -10,7 +10,9 @@ export const HttpStatusCode = isServer
10
10
  const event = getRequestEvent();
11
11
  event.response.status = props.code;
12
12
  event.response.statusText = props.text;
13
- onCleanup(() => !event.nativeEvent.handled && !event.complete && (event.response.status = 200));
13
+ onCleanup(() =>
14
+ // !event.nativeEvent.handled &&
15
+ !event.complete && (event.response.status = 200));
14
16
  return null;
15
17
  }
16
18
  : (_props) => null;
@@ -1,4 +1,4 @@
1
- import { type JSX } from 'solid-js';
1
+ import { type JSX } from "solid-js";
2
2
  export interface CodeViewProps {
3
3
  fileName: string;
4
4
  content: string;