@solidjs/start 2.0.0-alpha.2 → 2.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/config/constants.d.ts +1 -1
  3. package/dist/config/constants.js +1 -1
  4. package/dist/config/dev-server.js +9 -1
  5. package/dist/config/env.d.ts +19 -0
  6. package/dist/config/env.js +81 -0
  7. package/dist/config/fs-routes/fs-watcher.js +14 -20
  8. package/dist/config/fs-routes/index.js +2 -2
  9. package/dist/config/fs-routes/router.js +2 -2
  10. package/dist/config/index.d.ts +16 -1
  11. package/dist/config/index.js +25 -27
  12. package/dist/config/lazy.js +2 -2
  13. package/dist/config/manifest.js +37 -4
  14. package/dist/config/vite-utils.d.ts +1 -1
  15. package/dist/directives/bubble-function-declaration.d.ts +3 -0
  16. package/dist/directives/bubble-function-declaration.js +23 -0
  17. package/dist/directives/compile.d.ts +9 -0
  18. package/dist/directives/compile.js +40 -0
  19. package/dist/directives/generate-unique-name.d.ts +3 -0
  20. package/dist/directives/generate-unique-name.js +16 -0
  21. package/dist/directives/get-descriptive-name.d.ts +2 -0
  22. package/dist/directives/get-descriptive-name.js +37 -0
  23. package/dist/directives/get-import-identifier.d.ts +4 -0
  24. package/dist/directives/get-import-identifier.js +19 -0
  25. package/dist/directives/get-root-statement-path.d.ts +2 -0
  26. package/dist/directives/get-root-statement-path.js +12 -0
  27. package/dist/directives/index.d.ts +14 -0
  28. package/dist/directives/index.js +169 -0
  29. package/dist/directives/is-statement-top-level.d.ts +3 -0
  30. package/dist/directives/is-statement-top-level.js +9 -0
  31. package/dist/directives/paths.d.ts +9 -0
  32. package/dist/directives/paths.js +36 -0
  33. package/dist/directives/plugin.d.ts +21 -0
  34. package/dist/directives/plugin.js +302 -0
  35. package/dist/directives/remove-unused-variables.d.ts +3 -0
  36. package/dist/directives/remove-unused-variables.js +53 -0
  37. package/dist/directives/types.d.ts +10 -0
  38. package/dist/directives/xxhash32.d.ts +6 -0
  39. package/dist/directives/xxhash32.js +193 -0
  40. package/dist/{server/server-runtime.d.ts → fns/client.d.ts} +1 -1
  41. package/dist/fns/client.js +106 -0
  42. package/dist/fns/handler.d.ts +5 -0
  43. package/dist/{server/server-functions-handler.js → fns/handler.js} +55 -96
  44. package/dist/fns/registration.d.ts +2 -0
  45. package/dist/fns/registration.js +12 -0
  46. package/dist/fns/serialization.d.ts +6 -0
  47. package/dist/fns/serialization.js +208 -0
  48. package/dist/fns/server.d.ts +7 -0
  49. package/dist/{server/server-fns-runtime.js → fns/server.js} +7 -1
  50. package/dist/fns/shared.d.ts +17 -0
  51. package/dist/fns/shared.js +105 -0
  52. package/dist/http/index.d.ts +1 -1
  53. package/dist/middleware/index.d.ts +17 -0
  54. package/dist/middleware/index.js +15 -0
  55. package/dist/server/handler.d.ts +61 -3
  56. package/dist/server/handler.js +17 -15
  57. package/dist/server/spa/handler.d.ts +30 -1
  58. package/dist/server/types.d.ts +1 -1
  59. package/dist/shared/dev-overlay/CodeView.jsx +4 -4
  60. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +34 -34
  61. package/dist/shared/dev-overlay/index.jsx +2 -2
  62. package/dist/shared/dev-overlay/styles.css +40 -40
  63. package/package.json +27 -20
  64. package/src/config/constants.ts +1 -1
  65. package/src/config/env.ts +105 -0
  66. package/src/config/fs-routes/fs-watcher.ts +17 -24
  67. package/src/config/fs-routes/index.ts +2 -2
  68. package/src/config/fs-routes/router.ts +2 -2
  69. package/src/config/index.ts +39 -37
  70. package/src/config/lazy.ts +2 -2
  71. package/src/config/manifest.ts +37 -7
  72. package/src/config/vite-utils.ts +1 -1
  73. package/src/directives/bubble-function-declaration.ts +33 -0
  74. package/src/directives/compile.ts +54 -0
  75. package/src/directives/generate-unique-name.ts +22 -0
  76. package/src/directives/get-descriptive-name.ts +39 -0
  77. package/src/directives/get-import-identifier.ts +34 -0
  78. package/src/directives/get-root-statement-path.ts +14 -0
  79. package/src/directives/index.ts +232 -0
  80. package/src/directives/is-statement-top-level.ts +13 -0
  81. package/src/directives/paths.ts +63 -0
  82. package/src/directives/plugin.ts +389 -0
  83. package/src/directives/remove-unused-variables.ts +55 -0
  84. package/src/directives/types.ts +12 -0
  85. package/src/directives/xxhash32.ts +214 -0
  86. package/src/env.d.ts +1 -1
  87. package/src/fns/client.ts +141 -0
  88. package/src/fns/handler.spec.ts +85 -0
  89. package/src/{server/server-functions-handler.ts → fns/handler.ts} +65 -117
  90. package/src/fns/registration.ts +19 -0
  91. package/src/fns/serialization.ts +250 -0
  92. package/src/{server/server-fns-runtime.ts → fns/server.ts} +17 -2
  93. package/src/fns/shared.ts +116 -0
  94. package/src/middleware/index.ts +17 -0
  95. package/src/server/handler.ts +18 -16
  96. package/src/server/types.ts +1 -1
  97. package/src/shared/dev-overlay/CodeView.tsx +5 -7
  98. package/src/shared/dev-overlay/DevOverlayDialog.tsx +34 -34
  99. package/src/shared/dev-overlay/get-source-map.ts +1 -1
  100. package/src/shared/dev-overlay/index.tsx +4 -4
  101. package/src/shared/dev-overlay/styles.css +40 -40
  102. package/tsconfig.json +1 -0
  103. package/dist/server/fetchEvent.spec.js +0 -65
  104. package/dist/server/server-fns-runtime.d.ts +0 -1
  105. package/dist/server/server-functions-handler.d.ts +0 -2
  106. package/dist/server/server-runtime.js +0 -194
  107. package/src/server/server-runtime.ts +0 -240
  108. /package/dist/{server/fetchEvent.spec.d.ts → directives/types.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @solidjs/start
2
2
 
3
+ ## 2.0.0-alpha.3
4
+
5
+ ### Minor Changes
6
+
7
+ - 798b285: Updated dependencies.
8
+ - f6f0452: seroval json mode
9
+ - d4be1b6: Add new directives plugin with shorter function IDs and inner declaration support
10
+ - b9c4ade: feat: add `env:*` runtime environment variables support
11
+
12
+ ### Patch Changes
13
+
14
+ - ff9607c: import DevEnvironment and Rollup as type from vite
15
+ - 6da636b: The server function directives runtime is now internally accessed via package.json exports instead of relative paths, fixing inconsistencies in the file resolution. Also the server functions file inclusion/exclusion patterns can now be configured in the start plugin options via `serverFunctions`.
16
+ - 2885905: fix: clone request headers in single-flight to avoid mutating immutable headers
17
+ - abe3979: reload ssr server when new route files are created in dev
18
+ - 7c288f6: Sanitize Location header value in streaming redirect script
19
+ - 6c83886: update seroval to 1.5.4
20
+ - 9d5d783: Add support for Vite 8 asset manifest loading
21
+
3
22
  ## 2.0.0-alpha.2
4
23
 
5
24
  ### Minor Changes
@@ -5,7 +5,7 @@ export declare const VIRTUAL_MODULES: {
5
5
  readonly getClientManifest: "solid-start:get-client-manifest";
6
6
  readonly getManifest: "solid-start:get-manifest";
7
7
  readonly middleware: "solid-start:middleware";
8
- readonly serverFnManifest: "solidstart:server-fn-manifest";
8
+ readonly serverFnManifest: "solid-start:server-fn-manifest";
9
9
  readonly clientEntry: "solid-start:client-entry";
10
10
  readonly serverEntry: "solid-start:server-entry";
11
11
  readonly app: "solid-start:app";
@@ -5,7 +5,7 @@ export const VIRTUAL_MODULES = {
5
5
  getClientManifest: "solid-start:get-client-manifest",
6
6
  getManifest: "solid-start:get-manifest",
7
7
  middleware: "solid-start:middleware",
8
- serverFnManifest: "solidstart:server-fn-manifest",
8
+ serverFnManifest: "solid-start:server-fn-manifest",
9
9
  clientEntry: "solid-start:client-entry",
10
10
  serverEntry: "solid-start:server-entry",
11
11
  app: "solid-start:app",
@@ -1,3 +1,11 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
1
9
  import { NodeRequest, sendNodeResponse } from "srvx/node";
2
10
  import { isRunnableDevEnvironment, } from "vite";
3
11
  import { VITE_ENVIRONMENTS } from "./constants.js";
@@ -10,7 +18,7 @@ export function devServer() {
10
18
  server.middlewares.use(async (req, res) => {
11
19
  res.setHeader("content-encoding", "identity");
12
20
  const webReq = new NodeRequest({ req, res });
13
- const def = await import(process.cwd() + "/dist/server/entry-server.js");
21
+ const def = await import(__rewriteRelativeImportExtension(process.cwd() + "/dist/server/entry-server.js", true));
14
22
  sendNodeResponse(res, await def.default.fetch(webReq));
15
23
  });
16
24
  };
@@ -0,0 +1,19 @@
1
+ import { type Plugin } from "vite";
2
+ declare const LOADERS: {
3
+ node: string;
4
+ "cloudflare-workers": string;
5
+ "netlify-edge": string;
6
+ };
7
+ export interface EnvPluginOptions {
8
+ server?: {
9
+ runtime?: keyof typeof LOADERS | (string & {});
10
+ load?: (mode: string) => Record<string, string>;
11
+ prefix?: string;
12
+ };
13
+ client?: {
14
+ load?: (mode: string) => Record<string, string>;
15
+ prefix?: string;
16
+ };
17
+ }
18
+ export declare function envPlugin(options?: EnvPluginOptions): Plugin;
19
+ export {};
@@ -0,0 +1,81 @@
1
+ import { loadEnv } from "vite";
2
+ const LOADERS = {
3
+ node: `export default key => process.env[key];`,
4
+ "cloudflare-workers": `import { env } from 'cloudflare:workers';export default key => env[key];`,
5
+ "netlify-edge": `export default key => Netlify.env.get(key);`,
6
+ };
7
+ const SERVER_ENV = "env:server";
8
+ const CLIENT_ENV = "env:client";
9
+ const SERVER_RUNTIME_ENV = `${SERVER_ENV}/runtime`;
10
+ const SERVER_RUNTIME_LOADER = `${SERVER_RUNTIME_ENV}/loader`;
11
+ const DEFAULT_SERVER_PREFIX = "SERVER_";
12
+ const DEFAULT_CLIENT_PREFIX = "CLIENT_";
13
+ const SERVER_ONLY_MODULE = `throw new Error('Attempt to load server-only environment variables in client runtime.');`;
14
+ const SERVER_RUNTIME_CODE = `import load from '${SERVER_RUNTIME_LOADER}';
15
+
16
+ export default new Proxy({}, {
17
+ get(_, key) {
18
+ return load(key);
19
+ },
20
+ })`;
21
+ function convertObjectToModule(object) {
22
+ let result = "";
23
+ for (const key in object) {
24
+ result += `export const ${key} = ${JSON.stringify(object[key])};`;
25
+ }
26
+ return result;
27
+ }
28
+ export function envPlugin(options) {
29
+ const currentOptions = options ?? {};
30
+ let env;
31
+ const serverPrefix = currentOptions.server?.prefix ?? DEFAULT_SERVER_PREFIX;
32
+ const clientPrefix = currentOptions.client?.prefix ?? DEFAULT_CLIENT_PREFIX;
33
+ const runtime = options?.server?.runtime ?? "node";
34
+ const runtimeCode = runtime in LOADERS ? LOADERS[runtime] : runtime;
35
+ return {
36
+ name: "solid-start:env",
37
+ enforce: "pre",
38
+ configResolved(config) {
39
+ env = config.mode !== "production" ? "development" : "production";
40
+ },
41
+ resolveId(id) {
42
+ if (id === SERVER_ENV ||
43
+ id === CLIENT_ENV ||
44
+ id === SERVER_RUNTIME_ENV ||
45
+ id === SERVER_RUNTIME_LOADER) {
46
+ return id;
47
+ }
48
+ return undefined;
49
+ },
50
+ load(id, opts) {
51
+ if (id === SERVER_ENV) {
52
+ if (!opts?.ssr) {
53
+ return SERVER_ONLY_MODULE;
54
+ }
55
+ const vars = currentOptions.server?.load
56
+ ? currentOptions.server.load(env)
57
+ : loadEnv(env, '.', serverPrefix);
58
+ return convertObjectToModule(vars);
59
+ }
60
+ if (id === CLIENT_ENV) {
61
+ const vars = currentOptions.client?.load
62
+ ? currentOptions.client.load(env)
63
+ : loadEnv(env, '.', clientPrefix);
64
+ return convertObjectToModule(vars);
65
+ }
66
+ if (id === SERVER_RUNTIME_LOADER) {
67
+ if (!opts?.ssr) {
68
+ return SERVER_ONLY_MODULE;
69
+ }
70
+ return runtimeCode;
71
+ }
72
+ if (id === SERVER_RUNTIME_ENV) {
73
+ if (!opts?.ssr) {
74
+ return SERVER_ONLY_MODULE;
75
+ }
76
+ return SERVER_RUNTIME_CODE;
77
+ }
78
+ return undefined;
79
+ },
80
+ };
81
+ }
@@ -1,3 +1,4 @@
1
+ import { VITE_ENVIRONMENTS } from "../constants.js";
1
2
  import { moduleId } from "./index.js";
2
3
  function setupWatcher(watcher, routes) {
3
4
  watcher.on("unlink", path => routes.removeRoute(path));
@@ -8,29 +9,22 @@ function createRoutesReloader(server, routes, environment) {
8
9
  routes.addEventListener("reload", handleRoutesReload);
9
10
  return () => routes.removeEventListener("reload", handleRoutesReload);
10
11
  function handleRoutesReload() {
11
- if (environment === "ssr") {
12
- // Handle server environment HMR reload
13
- const serverEnv = server.environments.server;
14
- if (serverEnv && serverEnv.moduleGraph) {
15
- const mod = serverEnv.moduleGraph.getModuleById(moduleId);
16
- if (mod) {
17
- const seen = new Set();
18
- serverEnv.moduleGraph.invalidateModule(mod, seen);
19
- }
20
- }
12
+ const envName = environment === "ssr" ? VITE_ENVIRONMENTS.server : VITE_ENVIRONMENTS.client;
13
+ const devEnv = server.environments[envName];
14
+ if (!devEnv?.moduleGraph)
15
+ return;
16
+ const mod = devEnv.moduleGraph.getModuleById(moduleId);
17
+ if (mod) {
18
+ const seen = new Set();
19
+ devEnv.moduleGraph.invalidateModule(mod, seen);
21
20
  }
22
- else {
23
- // Handle client environment HMR reload
24
- const { moduleGraph } = server;
25
- const mod = moduleGraph.getModuleById(moduleId);
21
+ if (environment !== "ssr") {
26
22
  if (mod) {
27
- const seen = new Set();
28
- moduleGraph.invalidateModule(mod, seen);
29
- server.reloadModule(mod);
23
+ devEnv.reloadModule(mod);
24
+ }
25
+ else if (devEnv.hot) {
26
+ devEnv.hot.send({ type: "full-reload" });
30
27
  }
31
- }
32
- if (!server.hot) {
33
- server.ws.send({ type: "full-reload" });
34
28
  }
35
29
  }
36
30
  }
@@ -43,8 +43,8 @@ export function fsRoutes({ routers }) {
43
43
  const buildId = `${v.src}?${v.pick.map((p) => `pick=${p}`).join("&")}`;
44
44
  return {
45
45
  src: relative(root, buildId),
46
- build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined,
47
- import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`,
46
+ build: isBuild ? `_$() => import('${buildId}')$_` : undefined,
47
+ import: `_$() => import('${buildId}')$_`,
48
48
  };
49
49
  }
50
50
  return v;
@@ -1,9 +1,9 @@
1
1
  import { init, parse } from "es-module-lexer";
2
2
  import esbuild from "esbuild";
3
3
  import fg from "fast-glob";
4
- import fs from "fs";
4
+ import fs from "node:fs";
5
5
  import micromatch from "micromatch";
6
- import { posix } from "path";
6
+ import { posix } from "node:path";
7
7
  import { pathToRegexp } from "path-to-regexp";
8
8
  import { normalizePath } from "vite";
9
9
  export { pathToRegexp };
@@ -1,10 +1,25 @@
1
- import { type PluginOption } from "vite";
1
+ import type { PluginOption } from "vite";
2
2
  import { type Options as SolidOptions } from "vite-plugin-solid";
3
+ import { type ServerFunctionsOptions } from "../directives/index.ts";
4
+ import { type EnvPluginOptions } from "./env.ts";
3
5
  export interface SolidStartOptions {
4
6
  solid?: Partial<SolidOptions>;
5
7
  ssr?: boolean;
6
8
  routeDir?: string;
7
9
  extensions?: string[];
8
10
  middleware?: string;
11
+ serialization?: {
12
+ /**
13
+ * The serialization mode to use for server functions/actions.
14
+ * The "js" mode uses a custom binary format that is more efficient than JSON, but requires a custom deserializer (with `eval()`) on the client.
15
+ * A strong CSP should block `eval()` executions, which would prevent the "js" mode from working.
16
+ * The "json" mode uses JSON for serialization, which is less efficient but can be deserialized with `JSON.parse` on the client.
17
+ *
18
+ * @default "json"
19
+ */
20
+ mode?: "js" | "json";
21
+ };
22
+ env?: EnvPluginOptions;
23
+ serverFunctions?: Pick<ServerFunctionsOptions, "filter">;
9
24
  }
10
25
  export declare function solidStart(options?: SolidStartOptions): Array<PluginOption>;
@@ -1,12 +1,11 @@
1
- import { TanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
2
1
  import { defu } from "defu";
3
2
  import { globSync } from "node:fs";
4
3
  import { extname, isAbsolute, join } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { normalizePath } from "vite";
7
4
  import solid from "vite-plugin-solid";
5
+ import { serverFunctionsPlugin } from "../directives/index.js";
8
6
  import { DEFAULT_EXTENSIONS, VIRTUAL_MODULES, VITE_ENVIRONMENTS } from "./constants.js";
9
7
  import { devServer } from "./dev-server.js";
8
+ import { envPlugin } from "./env.js";
10
9
  import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js";
11
10
  import { fsRoutes } from "./fs-routes/index.js";
12
11
  import lazy from "./lazy.js";
@@ -67,6 +66,16 @@ export function solidStart(options) {
67
66
  return {
68
67
  appType: "custom",
69
68
  build: { assetsDir: "_build/assets" },
69
+ optimizeDeps: {
70
+ // Suppress TS errors from Vite 7 types when configuring Vite 8's Rolldown
71
+ ...{
72
+ rolldownOptions: {
73
+ transform: {
74
+ jsx: "react",
75
+ },
76
+ },
77
+ },
78
+ },
70
79
  environments: {
71
80
  [VITE_ENVIRONMENTS.client]: {
72
81
  consumer: "client",
@@ -109,6 +118,9 @@ export function solidStart(options) {
109
118
  }
110
119
  : {}),
111
120
  },
121
+ // Depending on the package manager and dependency structure Vite externalizes @solidjs/start
122
+ // This makes sure that @solidjs/start goes through the Vite build process
123
+ noExternal: ["@solidjs/start"],
112
124
  },
113
125
  define: {
114
126
  "import.meta.env.MANIFEST": `globalThis.MANIFEST`,
@@ -118,6 +130,7 @@ export function solidStart(options) {
118
130
  "import.meta.env.START_APP_ENTRY": JSON.stringify(appEntryPath),
119
131
  "import.meta.env.START_CLIENT_ENTRY": JSON.stringify(handlers.client),
120
132
  "import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
133
+ "import.meta.env.SEROVAL_MODE": JSON.stringify(start.serialization?.mode || "json"),
121
134
  },
122
135
  builder: {
123
136
  sharedPlugins: true,
@@ -152,32 +165,16 @@ export function solidStart(options) {
152
165
  },
153
166
  }),
154
167
  lazy(),
168
+ envPlugin(options?.env),
155
169
  // Must be placed after fsRoutes, as treeShake will remove the
156
170
  // server fn exports added in by this plugin
157
- TanStackServerFnPlugin({
158
- // This is the ID that will be available to look up and import
159
- // our server function manifest and resolve its module
160
- manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,
161
- directive: "use server",
162
- callers: [
163
- {
164
- envConsumer: "client",
165
- envName: VITE_ENVIRONMENTS.client,
166
- getRuntimeCode: () => `import { createServerReference } from "${normalizePath(fileURLToPath(new URL("../server/server-runtime", import.meta.url)))}"`,
167
- replacer: opts => `createServerReference('${opts.functionId}')`,
168
- },
169
- {
170
- envConsumer: "server",
171
- envName: VITE_ENVIRONMENTS.server,
172
- getRuntimeCode: () => `import { createServerReference } from '${normalizePath(fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)))}'`,
173
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
174
- },
175
- ],
176
- provider: {
177
- envName: VITE_ENVIRONMENTS.server,
178
- getRuntimeCode: () => `import { createServerReference } from '${normalizePath(fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)))}'`,
179
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
171
+ serverFunctionsPlugin({
172
+ manifest: VIRTUAL_MODULES.serverFnManifest,
173
+ runtime: {
174
+ server: '@solidjs/start/fns/server',
175
+ client: '@solidjs/start/fns/client',
180
176
  },
177
+ filter: options?.serverFunctions?.filter,
181
178
  }),
182
179
  {
183
180
  name: "solid-start:virtual-modules",
@@ -203,8 +200,9 @@ export function solidStart(options) {
203
200
  {
204
201
  name: "solid-start:capture-client-bundle",
205
202
  enforce: "post",
206
- generateBundle(_options, bundle) {
203
+ generateBundle(options, bundle) {
207
204
  globalThis.START_CLIENT_BUNDLE = bundle;
205
+ globalThis.START_CLIENT_OUT_DIR = options.dir;
208
206
  },
209
207
  },
210
208
  devServer(),
@@ -1,7 +1,7 @@
1
1
  import babel from "@babel/core";
2
2
  import * as t from "@babel/types";
3
- import { sep as osSep } from "path";
4
- import { basename, relative, sep } from "path/posix";
3
+ import { sep as osSep } from "node:path";
4
+ import { basename, relative, sep } from "node:path/posix";
5
5
  import { VITE_ENVIRONMENTS } from "./constants.js";
6
6
  const idTransform = (id) => {
7
7
  return {
@@ -1,3 +1,6 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { version as viteVersion } from "vite";
1
4
  import { findStylesInModuleGraph } from "../server/collect-styles.js";
2
5
  import { VIRTUAL_MODULES } from "./constants.js";
3
6
  import { wrapId } from "./vite-utils.js";
@@ -35,7 +38,37 @@ export function manifest(start) {
35
38
  const entry = Object.values(globalThis.START_CLIENT_BUNDLE).find(v => "isEntry" in v && v.isEntry);
36
39
  if (!entry)
37
40
  throw new Error("No client entry found");
38
- clientViteManifest = JSON.parse(globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"].source);
41
+ let rawManifest;
42
+ const viteMajor = parseInt(viteVersion.split('.')[0], 10);
43
+ const manifestKey = Object.keys(globalThis.START_CLIENT_BUNDLE).find(k => k.endsWith("manifest.json"));
44
+ if (manifestKey && viteMajor < 8) {
45
+ const manifestAsset = globalThis.START_CLIENT_BUNDLE[manifestKey];
46
+ rawManifest = manifestAsset.source;
47
+ }
48
+ else {
49
+ try {
50
+ const appRoot = start.appRoot || "./src";
51
+ let outDir = ".solid-start/client";
52
+ if (devServer?.environments?.client?.config?.build?.outDir) {
53
+ outDir = devServer.environments.client.config.build.outDir;
54
+ }
55
+ else if (this.environment?.config?.build?.outDir && this.environment?.config?.consumer === "client") {
56
+ outDir = this.environment.config.build.outDir;
57
+ }
58
+ else if (globalThis.START_CLIENT_OUT_DIR) {
59
+ outDir = globalThis.START_CLIENT_OUT_DIR;
60
+ }
61
+ const manifestPath = path.resolve(appRoot, "..", outDir, ".vite/manifest.json");
62
+ rawManifest = fs.readFileSync(manifestPath, "utf-8");
63
+ }
64
+ catch (e) {
65
+ throw new Error(`Manifest asset not found in bundle and could not be read from disk. Keys: ${Object.keys(globalThis.START_CLIENT_BUNDLE).join(", ")}. Error: ${e}`);
66
+ }
67
+ }
68
+ if (!rawManifest) {
69
+ throw new Error("Failed to extract or read raw manifest.");
70
+ }
71
+ clientViteManifest = JSON.parse(rawManifest);
39
72
  }
40
73
  return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`;
41
74
  }
@@ -44,12 +77,12 @@ export function manifest(start) {
44
77
  else if (id.startsWith("/@manifest")) {
45
78
  if (this.environment.mode !== "dev")
46
79
  throw new Error("@manifest queries are only allowed in dev");
47
- const [path, query] = id.split("?");
80
+ const [urlPath, query] = id.split("?");
48
81
  const target = id.split("/")[2];
49
82
  const params = new URLSearchParams(query);
50
- if (!path || !query)
83
+ if (!urlPath || !query)
51
84
  return;
52
- if (path.endsWith("assets")) {
85
+ if (urlPath.endsWith("assets")) {
53
86
  const id = params.get("id");
54
87
  if (!id) {
55
88
  throw new Error("Missing id to get assets.");
@@ -1,4 +1,4 @@
1
- import { DevEnvironment, Rollup } from "vite";
1
+ import type { DevEnvironment, Rollup } from "vite";
2
2
  export declare function cleanUrl(url: string): string;
3
3
  export declare const FS_PREFIX = "/@fs/";
4
4
  export declare const VALID_ID_PREFIX = "/@id/";
@@ -0,0 +1,3 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ export declare function bubbleFunctionDeclaration(path: babel.NodePath<t.FunctionDeclaration>): void;
@@ -0,0 +1,23 @@
1
+ import * as t from "@babel/types";
2
+ export function bubbleFunctionDeclaration(path) {
3
+ const decl = path.node;
4
+ // Check if declaration is FunctionDeclaration
5
+ if (decl.id) {
6
+ const block = (path.findParent(current => current.isBlockStatement()) ||
7
+ path.scope.getProgramParent().path);
8
+ if (path.parentPath.isExportNamedDeclaration()) {
9
+ path.parentPath.replaceWith(t.exportNamedDeclaration(undefined, [t.exportSpecifier(decl.id, decl.id)]));
10
+ }
11
+ else if (path.parentPath.isExportDefaultDeclaration()) {
12
+ path.replaceWith(decl.id);
13
+ }
14
+ else {
15
+ path.remove();
16
+ }
17
+ const [tmp] = block.unshiftContainer("body", t.variableDeclaration("const", [
18
+ t.variableDeclarator(decl.id, t.functionExpression(decl.id, decl.params, decl.body, decl.generator, decl.async)),
19
+ ]));
20
+ block.scope.registerDeclaration(tmp);
21
+ tmp.skip();
22
+ }
23
+ }
@@ -0,0 +1,9 @@
1
+ import * as babel from "@babel/core";
2
+ import { type StateContext } from "./plugin.ts";
3
+ export interface CompileResult {
4
+ valid: boolean;
5
+ code: string;
6
+ map: babel.BabelFileResult["map"];
7
+ }
8
+ export type CompileOptions = Omit<StateContext, "count" | "hash" | "imports" | "valid">;
9
+ export declare function compile(id: string, code: string, options: CompileOptions): Promise<CompileResult>;
@@ -0,0 +1,40 @@
1
+ import * as babel from "@babel/core";
2
+ import path from "node:path";
3
+ import { directivesPlugin } from "./plugin.js";
4
+ import xxHash32 from "./xxhash32.js";
5
+ export async function compile(id, code, options) {
6
+ const context = {
7
+ ...options,
8
+ valid: false,
9
+ hash: xxHash32(id).toString(16),
10
+ count: 0,
11
+ imports: new Map(),
12
+ };
13
+ const pluginOption = [directivesPlugin, context];
14
+ const plugins = [
15
+ "jsx",
16
+ ];
17
+ if (/\.[mc]?tsx?$/i.test(id)) {
18
+ plugins.push("typescript");
19
+ }
20
+ const result = await babel.transformAsync(code, {
21
+ plugins: [pluginOption],
22
+ parserOpts: {
23
+ plugins,
24
+ },
25
+ filename: path.basename(id),
26
+ ast: false,
27
+ sourceMaps: true,
28
+ configFile: false,
29
+ babelrc: false,
30
+ sourceFileName: id,
31
+ });
32
+ if (result) {
33
+ return {
34
+ valid: context.valid,
35
+ code: result.code || "",
36
+ map: result.map,
37
+ };
38
+ }
39
+ throw new Error("invariant");
40
+ }
@@ -0,0 +1,3 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ export declare function generateUniqueName(path: babel.NodePath, name: string): t.Identifier;
@@ -0,0 +1,16 @@
1
+ import * as t from "@babel/types";
2
+ export function generateUniqueName(path, name) {
3
+ let uid;
4
+ let i = 1;
5
+ do {
6
+ uid = name + "_" + i;
7
+ i++;
8
+ } while (path.scope.hasLabel(uid) ||
9
+ path.scope.hasBinding(uid) ||
10
+ path.scope.hasGlobal(uid) ||
11
+ path.scope.hasReference(uid));
12
+ const program = path.scope.getProgramParent();
13
+ program.references[uid] = true;
14
+ program.uids[uid] = true;
15
+ return t.identifier(uid);
16
+ }
@@ -0,0 +1,2 @@
1
+ import type { NodePath } from "@babel/core";
2
+ export declare function getDescriptiveName(path: NodePath, defaultName: string): string;
@@ -0,0 +1,37 @@
1
+ export function getDescriptiveName(path, defaultName) {
2
+ let current = path;
3
+ while (current) {
4
+ switch (current.node.type) {
5
+ case "FunctionDeclaration":
6
+ case "FunctionExpression": {
7
+ if (current.node.id) {
8
+ return current.node.id.name;
9
+ }
10
+ break;
11
+ }
12
+ case "VariableDeclarator": {
13
+ if (current.node.id.type === "Identifier") {
14
+ return current.node.id.name;
15
+ }
16
+ break;
17
+ }
18
+ case "ClassPrivateMethod":
19
+ case "ClassMethod":
20
+ case "ObjectMethod": {
21
+ switch (current.node.key.type) {
22
+ case "Identifier":
23
+ return current.node.key.name;
24
+ case "PrivateName":
25
+ return current.node.key.id.name;
26
+ default:
27
+ break;
28
+ }
29
+ break;
30
+ }
31
+ default:
32
+ break;
33
+ }
34
+ current = current.parentPath;
35
+ }
36
+ return defaultName;
37
+ }
@@ -0,0 +1,4 @@
1
+ import type * as babel from "@babel/core";
2
+ import * as t from "@babel/types";
3
+ import type { ImportDefinition } from "./types.ts";
4
+ export declare function getImportIdentifier(imports: Map<string, t.Identifier>, path: babel.NodePath, registration: ImportDefinition): t.Identifier;
@@ -0,0 +1,19 @@
1
+ import * as t from "@babel/types";
2
+ import { generateUniqueName } from "./generate-unique-name.js";
3
+ export function getImportIdentifier(imports, path, registration) {
4
+ const name = registration.kind === "named" ? registration.name : "default";
5
+ const target = `${registration.source}[${name}]`;
6
+ const current = imports.get(target);
7
+ if (current) {
8
+ return current;
9
+ }
10
+ const programParent = path.scope.getProgramParent();
11
+ const uid = generateUniqueName(programParent.path, name);
12
+ programParent.registerDeclaration(programParent.path.unshiftContainer("body", t.importDeclaration([
13
+ registration.kind === "named"
14
+ ? t.importSpecifier(uid, t.identifier(registration.name))
15
+ : t.importDefaultSpecifier(uid),
16
+ ], t.stringLiteral(registration.source)))[0]);
17
+ imports.set(target, uid);
18
+ return uid;
19
+ }
@@ -0,0 +1,2 @@
1
+ import type * as babel from "@babel/core";
2
+ export declare function getRootStatementPath(path: babel.NodePath): babel.NodePath;
@@ -0,0 +1,12 @@
1
+ import * as t from "@babel/types";
2
+ export function getRootStatementPath(path) {
3
+ let current = path.parentPath;
4
+ while (current) {
5
+ const next = current.parentPath;
6
+ if (next && t.isProgram(next.node)) {
7
+ return current;
8
+ }
9
+ current = next;
10
+ }
11
+ return path;
12
+ }