@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
@@ -0,0 +1,129 @@
1
+ import * as h3 from "h3";
2
+ import { getRequestEvent } from "solid-js/web";
3
+ function _setContext(event, key, value) {
4
+ event.context[key] = value;
5
+ }
6
+ function _getContext(event, key) {
7
+ return event.context[key];
8
+ }
9
+ function getEvent() {
10
+ return getRequestEvent().nativeEvent;
11
+ }
12
+ export function getWebRequest() {
13
+ return getEvent().req;
14
+ }
15
+ export const HTTPEventSymbol = Symbol("$HTTPEvent");
16
+ export function isEvent(obj) {
17
+ return (typeof obj === "object" &&
18
+ (obj instanceof h3.H3Event ||
19
+ obj?.[HTTPEventSymbol] instanceof h3.H3Event ||
20
+ obj?.__is_event__ === true));
21
+ // Implement logic to check if obj is an H3Event
22
+ }
23
+ function createWrapperFunction(h3Function) {
24
+ return ((...args) => {
25
+ const event = args[0];
26
+ if (!isEvent(event)) {
27
+ args.unshift(getEvent());
28
+ }
29
+ else {
30
+ args[0] =
31
+ event instanceof h3.H3Event || event.__is_event__ ? event : event[HTTPEventSymbol];
32
+ }
33
+ return h3Function(...args);
34
+ });
35
+ }
36
+ export const readBody = createWrapperFunction(h3.readBody);
37
+ export const getQuery = createWrapperFunction(h3.getQuery);
38
+ export const isMethod = createWrapperFunction(h3.isMethod);
39
+ export const isPreflightRequest = createWrapperFunction(h3.isPreflightRequest);
40
+ export const getValidatedQuery = createWrapperFunction(h3.getValidatedQuery);
41
+ export const getRouterParams = createWrapperFunction(h3.getRouterParams);
42
+ export const getRouterParam = createWrapperFunction(h3.getRouterParam);
43
+ export const getValidatedRouterParams = createWrapperFunction(h3.getValidatedRouterParams);
44
+ export const assertMethod = createWrapperFunction(h3.assertMethod);
45
+ export const getRequestHeaders = createWrapperFunction(h3.getRequestHeaders);
46
+ export const getRequestHeader = createWrapperFunction(h3.getRequestHeader);
47
+ export const getRequestURL = createWrapperFunction(h3.getRequestURL);
48
+ export const getRequestHost = createWrapperFunction(h3.getRequestHost);
49
+ export const getRequestProtocol = createWrapperFunction(h3.getRequestProtocol);
50
+ export const getRequestIP = createWrapperFunction(h3.getRequestIP);
51
+ export const setResponseStatus = (code, text) => {
52
+ const e = getEvent();
53
+ if (e.res.status !== undefined)
54
+ e.res.status = code;
55
+ if (e.res.statusText !== undefined)
56
+ e.res.statusText = text;
57
+ };
58
+ export const getResponseStatus = () => getEvent().res.status;
59
+ export const getResponseStatusText = () => getEvent().res.statusText;
60
+ export const getResponseHeaders = () => Object.fromEntries(getEvent().res.headers.entries());
61
+ export const getResponseHeader = (name) => getEvent().res.headers.get(name);
62
+ export const setResponseHeaders = (values) => {
63
+ const headers = getEvent().res.headers;
64
+ for (const [name, value] of Object.entries(values)) {
65
+ headers.set(name, value);
66
+ }
67
+ };
68
+ export const setResponseHeader = (name, value) => {
69
+ const headers = getEvent().res.headers;
70
+ (Array.isArray(value) ? value : [value]).forEach(value => {
71
+ headers.set(name, value);
72
+ });
73
+ };
74
+ export const appendResponseHeaders = (values) => {
75
+ const headers = getEvent().res.headers;
76
+ for (const [name, value] of Object.entries(values)) {
77
+ headers.append(name, value);
78
+ }
79
+ };
80
+ export const appendResponseHeader = (name, value) => {
81
+ const headers = getEvent().res.headers;
82
+ (Array.isArray(value) ? value : [value]).forEach(value => {
83
+ headers.append(name, value);
84
+ });
85
+ };
86
+ export const defaultContentType = (type) => getEvent().res.headers.set("content-type", type);
87
+ export const proxyRequest = createWrapperFunction(h3.proxyRequest);
88
+ export const fetchWithEvent = createWrapperFunction(h3.fetchWithEvent);
89
+ export const getProxyRequestHeaders = createWrapperFunction(h3.getProxyRequestHeaders);
90
+ export const parseCookies = createWrapperFunction(h3.parseCookies);
91
+ export const getCookie = createWrapperFunction(h3.getCookie);
92
+ export const setCookie = createWrapperFunction(h3.setCookie);
93
+ export const deleteCookie = createWrapperFunction(h3.deleteCookie);
94
+ export const useSession = createWrapperFunction(h3.useSession);
95
+ export const getSession = createWrapperFunction(h3.getSession);
96
+ export const updateSession = createWrapperFunction(h3.updateSession);
97
+ export const sealSession = createWrapperFunction(h3.sealSession);
98
+ export const unsealSession = createWrapperFunction(h3.unsealSession);
99
+ export const clearSession = createWrapperFunction(h3.clearSession);
100
+ export const handleCacheHeaders = createWrapperFunction(h3.handleCacheHeaders);
101
+ export const handleCors = createWrapperFunction(h3.handleCors);
102
+ export const appendCorsHeaders = createWrapperFunction(h3.appendCorsHeaders);
103
+ export const appendCorsPreflightHeaders = createWrapperFunction(h3.appendCorsPreflightHeaders);
104
+ export const appendHeader = appendResponseHeader;
105
+ export const appendHeaders = appendResponseHeaders;
106
+ export const setHeader = setResponseHeader;
107
+ export const setHeaders = setResponseHeaders;
108
+ export const getHeader = getRequestHeader;
109
+ export const getHeaders = getRequestHeaders;
110
+ export const getRequestFingerprint = createWrapperFunction(h3.getRequestFingerprint);
111
+ export const getRequestWebStream = () => getEvent().req.body;
112
+ export const readFormData = () => getEvent().req.formData();
113
+ export const readValidatedBody = createWrapperFunction(h3.readValidatedBody);
114
+ export const getContext = createWrapperFunction(_getContext);
115
+ export const setContext = createWrapperFunction(_setContext);
116
+ export const removeResponseHeader = (name) => getEvent().res.headers.delete(name);
117
+ export const clearResponseHeaders = (headerNames) => {
118
+ const headers = getEvent().res.headers;
119
+ if (headerNames && headerNames.length > 0) {
120
+ for (const name of headerNames) {
121
+ headers.delete(name);
122
+ }
123
+ }
124
+ else {
125
+ for (const name of headers.keys()) {
126
+ headers.delete(name);
127
+ }
128
+ }
129
+ };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { default as clientOnly } from "./shared/clientOnly";
2
- export { GET } from "./shared/GET";
3
- export { HttpHeader } from "./shared/HttpHeader";
4
- export { HttpStatusCode } from "./shared/HttpStatusCode";
5
- export { getServerFunctionMeta } from "./shared/serverFunction";
1
+ export { default as clientOnly } from "./shared/clientOnly.ts";
2
+ export { GET } from "./shared/GET.ts";
3
+ export { HttpHeader } from "./shared/HttpHeader.tsx";
4
+ export { HttpStatusCode } from "./shared/HttpStatusCode.ts";
5
+ export { getServerFunctionMeta } from "./shared/serverFunction.ts";
package/dist/index.jsx CHANGED
@@ -1,6 +1,6 @@
1
1
  // @refresh skip
2
- export { default as clientOnly } from "./shared/clientOnly";
3
- export { GET } from "./shared/GET";
4
- export { HttpHeader } from "./shared/HttpHeader";
5
- export { HttpStatusCode } from "./shared/HttpStatusCode";
6
- export { getServerFunctionMeta } from "./shared/serverFunction";
2
+ export { default as clientOnly } from "./shared/clientOnly.js";
3
+ export { GET } from "./shared/GET.js";
4
+ export { HttpHeader } from "./shared/HttpHeader.jsx";
5
+ export { HttpStatusCode } from "./shared/HttpStatusCode.js";
6
+ export { getServerFunctionMeta } from "./shared/serverFunction.js";
@@ -1,4 +1,5 @@
1
- import type { FetchEvent } from "../server/types";
1
+ import type { Middleware } from "h3";
2
+ import type { FetchEvent } from "../server/types.ts";
2
3
  /** Function responsible for receiving an observable [operation]{@link Operation} and returning a [result]{@link OperationResult}. */
3
4
  export type MiddlewareFn = (event: FetchEvent) => Promise<unknown> | unknown;
4
5
  /** This composes an array of Exchanges into a single ExchangeIO function */
@@ -8,11 +9,10 @@ type ResponseMiddlewareResponseParam = {
8
9
  body?: Awaited<EventHandlerResponse>;
9
10
  };
10
11
  export type ResponseMiddleware = (event: FetchEvent, response: ResponseMiddlewareResponseParam) => Response | Promise<Response> | void | Promise<void>;
11
- export declare function createMiddleware({ onRequest, onBeforeResponse }: {
12
+ export declare function createMiddleware(args: {
13
+ /** @deprecated Use H3 `Middleware` */
12
14
  onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
15
+ /** @deprecated Use H3 `Middleware` */
13
16
  onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined;
14
- }): {
15
- onRequest?: import("vinxi/http")._RequestMiddleware | import("vinxi/http")._RequestMiddleware[] | undefined;
16
- onBeforeResponse?: import("vinxi/http")._ResponseMiddleware | import("vinxi/http")._ResponseMiddleware[] | undefined;
17
- };
17
+ } | Middleware[]): Middleware[];
18
18
  export {};
@@ -0,0 +1,39 @@
1
+ // @refresh skip
2
+ import { getFetchEvent } from "../server/fetchEvent.js";
3
+ function wrapRequestMiddleware(onRequest) {
4
+ return async (h3Event) => {
5
+ const fetchEvent = getFetchEvent(h3Event);
6
+ const response = await onRequest(fetchEvent);
7
+ if (response)
8
+ return response;
9
+ };
10
+ }
11
+ function wrapResponseMiddleware(onBeforeResponse) {
12
+ return async (h3Event, next) => {
13
+ const resp = await next();
14
+ const fetchEvent = getFetchEvent(h3Event);
15
+ const mwResponse = await onBeforeResponse(fetchEvent, {
16
+ body: resp?.body,
17
+ });
18
+ if (mwResponse)
19
+ return mwResponse;
20
+ };
21
+ }
22
+ export function createMiddleware(args) {
23
+ if (Array.isArray(args))
24
+ return args;
25
+ const mw = [];
26
+ if (typeof args.onRequest === "function") {
27
+ mw.push(wrapRequestMiddleware(args.onRequest));
28
+ }
29
+ else if (Array.isArray(args.onRequest)) {
30
+ mw.push(...args.onRequest.map(wrapRequestMiddleware));
31
+ }
32
+ if (typeof args.onBeforeResponse === "function") {
33
+ mw.push(wrapResponseMiddleware(args.onBeforeResponse));
34
+ }
35
+ else if (Array.isArray(args.onBeforeResponse)) {
36
+ mw.push(...args.onBeforeResponse.map(wrapResponseMiddleware));
37
+ }
38
+ return mw;
39
+ }
@@ -1,20 +1,19 @@
1
+ import { lazy } from "solid-js";
1
2
  import { getRequestEvent, isServer } from "solid-js/web";
2
- import lazyRoute from "./lazyRoute";
3
- import { pageRoutes as routeConfigs } from "./routes";
3
+ import { pageRoutes as routeConfigs } from "./server/routes.js";
4
+ const components = {};
4
5
  export function createRoutes() {
5
6
  function createRoute(route) {
7
+ const component = route.$component && (components[route.$component.src] ??= lazy(route.$component.import));
6
8
  return {
7
9
  ...route,
8
10
  ...(route.$$route ? route.$$route.require().route : undefined),
9
11
  info: {
10
12
  ...(route.$$route ? route.$$route.require().route.info : {}),
11
- filesystem: true
13
+ filesystem: true,
12
14
  },
13
- component: route.$component &&
14
- lazyRoute(route.$component, import.meta.env.START_ISLANDS
15
- ? import.meta.env.MANIFEST["ssr"]
16
- : import.meta.env.MANIFEST["client"], import.meta.env.MANIFEST["ssr"]),
17
- children: route.children ? route.children.map(createRoute) : undefined
15
+ component,
16
+ children: route.children ? route.children.map(createRoute) : undefined,
18
17
  };
19
18
  }
20
19
  const routes = routeConfigs.map(createRoute);
@@ -1,9 +1,9 @@
1
- import type { Component, JSX } from "solid-js";
2
- import type { DocumentComponentProps } from "./types";
1
+ import type { Component } from "solid-js";
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
6
6
  */
7
7
  export declare function StartServer(props: {
8
8
  document: Component<DocumentComponentProps>;
9
- }): JSX.Element;
9
+ }): import("solid-js").JSX.Element;
@@ -1,27 +1,9 @@
1
- // @refresh skip
2
- // @ts-ignore
3
- import App from "#start/app";
4
- import { Hydration, HydrationScript, NoHydration, getRequestEvent, ssr, useAssets } from "solid-js/web";
5
- import { ErrorBoundary, TopErrorBoundary } from "../shared/ErrorBoundary";
6
- import { renderAsset } from "./renderAsset";
1
+ import { Hydration, HydrationScript, NoHydration, getRequestEvent, ssr } from "solid-js/web";
2
+ import App from "solid-start:app";
3
+ import { ErrorBoundary, TopErrorBoundary } from "../shared/ErrorBoundary.jsx";
4
+ import { useAssets } from "./assets/index.js";
5
+ import { getSsrManifest } from "./manifest/ssr-manifest.js";
7
6
  const docType = ssr("<!DOCTYPE html>");
8
- function matchRoute(matches, routes, matched = []) {
9
- for (let i = 0; i < routes.length; i++) {
10
- const segment = routes[i];
11
- if (segment.path !== matches[0].path)
12
- continue;
13
- let next = [...matched, segment];
14
- if (segment.children) {
15
- const nextMatches = matches.slice(1);
16
- if (nextMatches.length === 0)
17
- continue;
18
- next = matchRoute(nextMatches, segment.children, next);
19
- if (!next)
20
- continue;
21
- }
22
- return next;
23
- }
24
- }
25
7
  /**
26
8
  *
27
9
  * Read more: https://docs.solidjs.com/solid-start/reference/server/start-server
@@ -30,49 +12,13 @@ export function StartServer(props) {
30
12
  const context = getRequestEvent();
31
13
  // @ts-ignore
32
14
  const nonce = context.nonce;
33
- let assets = [];
34
- Promise.resolve().then(async () => {
35
- let assetPromises = [];
36
- // @ts-ignore
37
- if (context.router && context.router.matches) {
38
- // @ts-ignore
39
- const matches = [...context.router.matches];
40
- while (matches.length && (!matches[0].info || !matches[0].info.filesystem))
41
- matches.shift();
42
- const matched = matches.length && matchRoute(matches, context.routes);
43
- if (matched) {
44
- const inputs = import.meta.env.MANIFEST[import.meta.env.START_ISLANDS ? "ssr" : "client"]
45
- .inputs;
46
- for (let i = 0; i < matched.length; i++) {
47
- const segment = matched[i];
48
- const part = inputs[segment["$component"].src];
49
- assetPromises.push(part.assets());
50
- }
51
- }
52
- else if (import.meta.env.DEV)
53
- console.warn("No route matched for preloading js assets");
54
- }
55
- assets = await Promise.all(assetPromises).then(a =>
56
- // dedupe assets
57
- [...new Map(a.flat().map(item => [item.attrs.key, item])).values()].filter(asset => import.meta.env.START_ISLANDS
58
- ? false
59
- : asset.attrs.rel === "modulepreload" &&
60
- !context.assets.find((a) => a.attrs.key === asset.attrs.key)));
61
- });
62
- useAssets(() => (assets.length ? assets.map(m => renderAsset(m)) : undefined));
15
+ useAssets(context.assets, nonce);
63
16
  return (<NoHydration>
64
17
  {docType}
65
18
  <TopErrorBoundary>
66
- <props.document assets={<>
67
- <HydrationScript />
68
- {context.assets.map((m) => renderAsset(m, nonce))}
69
- </>} scripts={nonce ? (<>
70
- <script nonce={nonce} innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
71
- <script type="module" nonce={nonce} async src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
72
- </>) : (<>
73
- <script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}/>
74
- <script type="module" async src={import.meta.env.MANIFEST["client"].inputs[import.meta.env.MANIFEST["client"].handler].output.path}/>
75
- </>)}>
19
+ <props.document assets={<HydrationScript />} scripts={<>
20
+ <script type="module" nonce={nonce} async src={getSsrManifest("client").path(import.meta.env.START_CLIENT_ENTRY)}/>
21
+ </>}>
76
22
  {!import.meta.env.START_ISLANDS ? (<Hydration>
77
23
  <ErrorBoundary>
78
24
  <App />
@@ -0,0 +1,2 @@
1
+ import { type Asset } from "./render.tsx";
2
+ export declare const useAssets: (assets: Asset[], nonce?: string) => void;
@@ -0,0 +1,52 @@
1
+ import { onCleanup, sharedConfig } from "solid-js";
2
+ import { getRequestEvent, useAssets as useAssets_ } from "solid-js/web";
3
+ import { renderAsset } from "./render.jsx";
4
+ const REGISTRY = Symbol("assetRegistry");
5
+ const NOOP = () => "";
6
+ const keyAttrs = ["href", "rel", "data-vite-dev-id"];
7
+ const getEntity = (registry, asset) => {
8
+ let key = asset.tag;
9
+ for (const k of keyAttrs) {
10
+ if (!(k in asset.attrs))
11
+ continue;
12
+ key += `[${k}='${asset.attrs[k]}']`;
13
+ }
14
+ const entity = (registry[key] ??= {
15
+ key,
16
+ consumers: 0,
17
+ });
18
+ return entity;
19
+ };
20
+ export const useAssets = (assets, nonce) => {
21
+ if (!assets.length)
22
+ return;
23
+ const registry = (getRequestEvent().locals[REGISTRY] ??= {});
24
+ const ssrRequestAssets = sharedConfig.context?.assets;
25
+ const cssKeys = [];
26
+ for (const asset of assets) {
27
+ const entity = getEntity(registry, asset);
28
+ const isCSSLink = asset.tag === "link" && asset.attrs.rel === "stylesheet";
29
+ const isCSS = isCSSLink || asset.tag === "style";
30
+ if (isCSS) {
31
+ cssKeys.push(entity.key);
32
+ }
33
+ entity.consumers++;
34
+ if (entity.consumers > 1)
35
+ continue;
36
+ // Mounting logic
37
+ useAssets_(() => renderAsset(asset, nonce));
38
+ entity.ssrIdx = ssrRequestAssets.length - 1;
39
+ }
40
+ onCleanup(() => {
41
+ for (const key of cssKeys) {
42
+ const entity = registry[key];
43
+ entity.consumers--;
44
+ if (entity.consumers != 0) {
45
+ continue;
46
+ }
47
+ // Ideally this logic should be implemented directly in dom-expressions
48
+ ssrRequestAssets.splice(entity.ssrIdx, 1, NOOP);
49
+ delete registry[key];
50
+ }
51
+ });
52
+ };
@@ -0,0 +1,19 @@
1
+ import type { JSX } from "solid-js";
2
+ export declare function renderAsset(asset: Asset, nonce?: string): any;
3
+ export type Asset = {
4
+ tag: "style";
5
+ attrs: JSX.StyleHTMLAttributes<HTMLStyleElement> & {
6
+ key?: string;
7
+ };
8
+ children?: JSX.Element;
9
+ } | {
10
+ tag: "script";
11
+ attrs: JSX.ScriptHTMLAttributes<HTMLScriptElement> & {
12
+ key?: string;
13
+ };
14
+ } | {
15
+ tag: "link";
16
+ attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> & {
17
+ key?: string;
18
+ };
19
+ };
@@ -9,6 +9,6 @@ const assetMap = {
9
9
  noscript: (props) => (<noscript {...props.attrs}>{props.children}</noscript>),
10
10
  };
11
11
  export function renderAsset(asset, nonce) {
12
- let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset;
12
+ let { tag, attrs: { key, ...attrs } = { key: undefined }, children, } = asset;
13
13
  return assetMap[tag]({ attrs: { ...attrs, nonce }, key, children });
14
14
  }
@@ -0,0 +1,3 @@
1
+ import type { DevEnvironment } from "vite";
2
+ export declare const isCssModulesFile: (file: string) => boolean;
3
+ export declare function findStylesInModuleGraph(vite: DevEnvironment, id: string): Promise<Record<string, any>>;
@@ -0,0 +1,69 @@
1
+ import path from "node:path";
2
+ import { resolve } from "pathe";
3
+ async function getViteModuleNode(vite, file) {
4
+ let nodePath = file;
5
+ let node = vite.moduleGraph.getModuleById(file);
6
+ if (!node) {
7
+ const resolvedId = await vite.pluginContainer.resolveId(file, undefined);
8
+ if (!resolvedId)
9
+ return;
10
+ nodePath = resolvedId.id;
11
+ node = vite.moduleGraph.getModuleById(file);
12
+ }
13
+ if (!node) {
14
+ nodePath = resolve(nodePath);
15
+ node = await vite.moduleGraph.getModuleByUrl(file);
16
+ }
17
+ if (!node) {
18
+ await vite.moduleGraph.ensureEntryFromUrl(nodePath, false);
19
+ node = vite.moduleGraph.getModuleById(nodePath);
20
+ }
21
+ return node;
22
+ }
23
+ async function findModuleDependencies(vite, file, deps, crawledFiles = new Set()) {
24
+ crawledFiles.add(file);
25
+ const module = await getViteModuleNode(vite, file);
26
+ if (!module?.id || deps.has(module))
27
+ return;
28
+ deps.add(module);
29
+ if (module.url.endsWith(".css") || module.url.includes("node_modules"))
30
+ return;
31
+ if (!module.transformResult) {
32
+ await vite.transformRequest(module.id).catch(() => { });
33
+ }
34
+ if (!module.transformResult?.deps)
35
+ return;
36
+ // Relying on module.transformResult.deps instead of module.importedModules because:
37
+ // transformResult properly separates imports into deps and dynamicDeps, importedModules doesn't
38
+ // Style crawling has to skip dynamic imports as such modules load their styles themselves
39
+ for (const dep of module.transformResult.deps) {
40
+ if (crawledFiles.has(dep)) {
41
+ continue;
42
+ }
43
+ await findModuleDependencies(vite, dep, deps, crawledFiles);
44
+ }
45
+ }
46
+ // Vite doesn't expose these so we just copy the list for now
47
+ // https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/constants.ts#L49C23-L50
48
+ const cssFileRegExp = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
49
+ // https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/plugins/css.ts#L160
50
+ const cssModulesRegExp = new RegExp(`\\.module${cssFileRegExp.source}`);
51
+ const isCssFile = (file) => cssFileRegExp.test(file);
52
+ export const isCssModulesFile = (file) => cssModulesRegExp.test(file);
53
+ export async function findStylesInModuleGraph(vite, id) {
54
+ const absolute = path.resolve(process.cwd(), id);
55
+ const dependencies = new Set();
56
+ try {
57
+ await findModuleDependencies(vite, absolute, dependencies);
58
+ }
59
+ catch (e) {
60
+ console.error(e);
61
+ }
62
+ const styles = {};
63
+ for (const dep of dependencies) {
64
+ if (dep.id && isCssFile(dep.url)) {
65
+ styles[dep.id] = dep.url;
66
+ }
67
+ }
68
+ return styles;
69
+ }
@@ -1,6 +1,7 @@
1
- import { H3Event } from "vinxi/http";
2
- import type { FetchEvent } from "./types";
1
+ import { type EventHandler, type H3Event, type Middleware } from "h3";
2
+ import type { FetchEvent } from "./types.ts";
3
3
  export declare function createFetchEvent(event: H3Event): FetchEvent;
4
- export declare function cloneEvent<T extends FetchEvent>(fetchEvent: T): T;
5
4
  export declare function getFetchEvent(h3Event: H3Event): FetchEvent;
6
5
  export declare function mergeResponseHeaders(h3Event: H3Event, headers: Headers): void;
6
+ export declare const decorateHandler: <T extends EventHandler>(fn: T) => T;
7
+ export declare const decorateMiddleware: <T extends Middleware>(fn: T) => T;
@@ -1,88 +1,26 @@
1
- import { appendResponseHeader, getRequestIP, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getWebRequest, removeResponseHeader, setResponseHeader, setResponseStatus } from "vinxi/http";
2
- const fetchEventContext = "solidFetchEvent";
1
+ import { getRequestIP } from "h3";
2
+ import { provideRequestEvent } from "solid-js/web/storage";
3
+ const FETCH_EVENT_CONTEXT = "solidFetchEvent";
3
4
  export function createFetchEvent(event) {
4
5
  return {
5
- request: getWebRequest(event),
6
- response: createResponseStub(event),
6
+ request: event.req,
7
+ response: event.res,
7
8
  clientAddress: getRequestIP(event),
8
9
  locals: {},
9
- nativeEvent: event
10
- };
11
- }
12
- export function cloneEvent(fetchEvent) {
13
- return {
14
- ...fetchEvent
10
+ nativeEvent: event,
15
11
  };
16
12
  }
17
13
  export function getFetchEvent(h3Event) {
18
- if (!h3Event.context[fetchEventContext]) {
14
+ if (!h3Event.context[FETCH_EVENT_CONTEXT]) {
19
15
  const fetchEvent = createFetchEvent(h3Event);
20
- h3Event.context[fetchEventContext] = fetchEvent;
16
+ h3Event.context[FETCH_EVENT_CONTEXT] = fetchEvent;
21
17
  }
22
- return h3Event.context[fetchEventContext];
18
+ return h3Event.context[FETCH_EVENT_CONTEXT];
23
19
  }
24
20
  export function mergeResponseHeaders(h3Event, headers) {
25
21
  for (const [key, value] of headers.entries()) {
26
- appendResponseHeader(h3Event, key, value);
27
- }
28
- }
29
- class HeaderProxy {
30
- event;
31
- constructor(event) {
32
- this.event = event;
33
- }
34
- get(key) {
35
- const h = getResponseHeader(this.event, key);
36
- return Array.isArray(h) ? h.join(", ") : h || null;
37
- }
38
- has(key) {
39
- return this.get(key) !== null;
40
- }
41
- set(key, value) {
42
- return setResponseHeader(this.event, key, value);
43
- }
44
- delete(key) {
45
- return removeResponseHeader(this.event, key);
46
- }
47
- append(key, value) {
48
- appendResponseHeader(this.event, key, value);
22
+ h3Event.res.headers.append(key, value);
49
23
  }
50
- getSetCookie() {
51
- const cookies = getResponseHeader(this.event, "Set-Cookie");
52
- return Array.isArray(cookies) ? cookies : [cookies];
53
- }
54
- forEach(fn) {
55
- return Object.entries(getResponseHeaders(this.event)).forEach(([key, value]) => fn(Array.isArray(value) ? value.join(", ") : value, key, this));
56
- }
57
- entries() {
58
- return Object.entries(getResponseHeaders(this.event))
59
- .map(([key, value]) => [key, Array.isArray(value) ? value.join(", ") : value])[Symbol.iterator]();
60
- }
61
- keys() {
62
- return Object.keys(getResponseHeaders(this.event))[Symbol.iterator]();
63
- }
64
- values() {
65
- return Object.values(getResponseHeaders(this.event))
66
- .map(value => (Array.isArray(value) ? value.join(", ") : value))[Symbol.iterator]();
67
- }
68
- [Symbol.iterator]() {
69
- return this.entries()[Symbol.iterator]();
70
- }
71
- }
72
- function createResponseStub(event) {
73
- return {
74
- get status() {
75
- return getResponseStatus(event);
76
- },
77
- set status(v) {
78
- setResponseStatus(event, v);
79
- },
80
- get statusText() {
81
- return getResponseStatusText(event);
82
- },
83
- set statusText(v) {
84
- setResponseStatus(event, getResponseStatus(event), v);
85
- },
86
- headers: new HeaderProxy(event)
87
- };
88
24
  }
25
+ export const decorateHandler = (fn) => (event => provideRequestEvent(getFetchEvent(event), () => fn(event)));
26
+ export const decorateMiddleware = (fn) => ((event, next) => provideRequestEvent(getFetchEvent(event), () => fn(event, next)));