@solidjs/start 2.0.0-alpha.1 → 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.
- package/CHANGELOG.md +33 -0
- package/dist/config/constants.d.ts +1 -1
- package/dist/config/constants.js +1 -1
- package/dist/config/dev-server.js +18 -0
- package/dist/config/env.d.ts +19 -0
- package/dist/config/env.js +81 -0
- package/dist/config/fs-routes/fs-watcher.js +14 -20
- package/dist/config/fs-routes/index.js +2 -2
- package/dist/config/fs-routes/router.js +7 -8
- package/dist/config/index.d.ts +16 -1
- package/dist/config/index.js +30 -29
- package/dist/config/lazy.js +35 -5
- package/dist/config/manifest.js +40 -6
- package/dist/config/vite-utils.d.ts +6 -1
- package/dist/config/vite-utils.js +7 -3
- package/dist/directives/bubble-function-declaration.d.ts +3 -0
- package/dist/directives/bubble-function-declaration.js +23 -0
- package/dist/directives/compile.d.ts +9 -0
- package/dist/directives/compile.js +40 -0
- package/dist/directives/generate-unique-name.d.ts +3 -0
- package/dist/directives/generate-unique-name.js +16 -0
- package/dist/directives/get-descriptive-name.d.ts +2 -0
- package/dist/directives/get-descriptive-name.js +37 -0
- package/dist/directives/get-import-identifier.d.ts +4 -0
- package/dist/directives/get-import-identifier.js +19 -0
- package/dist/directives/get-root-statement-path.d.ts +2 -0
- package/dist/directives/get-root-statement-path.js +12 -0
- package/dist/directives/index.d.ts +14 -0
- package/dist/directives/index.js +169 -0
- package/dist/directives/is-statement-top-level.d.ts +3 -0
- package/dist/directives/is-statement-top-level.js +9 -0
- package/dist/directives/paths.d.ts +9 -0
- package/dist/directives/paths.js +36 -0
- package/dist/directives/plugin.d.ts +21 -0
- package/dist/directives/plugin.js +302 -0
- package/dist/directives/remove-unused-variables.d.ts +3 -0
- package/dist/directives/remove-unused-variables.js +53 -0
- package/dist/directives/types.d.ts +10 -0
- package/dist/directives/xxhash32.d.ts +6 -0
- package/dist/directives/xxhash32.js +193 -0
- package/dist/{server/server-runtime.d.ts → fns/client.d.ts} +1 -1
- package/dist/fns/client.js +106 -0
- package/dist/fns/handler.d.ts +5 -0
- package/dist/{server/server-functions-handler.js → fns/handler.js} +55 -96
- package/dist/fns/registration.d.ts +2 -0
- package/dist/fns/registration.js +12 -0
- package/dist/fns/serialization.d.ts +6 -0
- package/dist/fns/serialization.js +208 -0
- package/dist/fns/server.d.ts +7 -0
- package/dist/{server/server-fns-runtime.js → fns/server.js} +7 -1
- package/dist/fns/shared.d.ts +17 -0
- package/dist/fns/shared.js +105 -0
- package/dist/http/index.d.ts +1 -1
- package/dist/middleware/index.d.ts +20 -0
- package/dist/middleware/index.js +21 -1
- package/dist/server/StartServer.jsx +2 -0
- package/dist/server/assets/PatchVirtualDevStyles.d.ts +4 -0
- package/dist/server/assets/PatchVirtualDevStyles.jsx +28 -0
- package/dist/server/collect-styles.js +9 -21
- package/dist/server/handler.d.ts +61 -3
- package/dist/server/handler.js +18 -15
- package/dist/server/spa/StartServer.jsx +2 -0
- package/dist/server/spa/handler.d.ts +30 -1
- package/dist/server/types.d.ts +1 -1
- package/dist/shared/dev-overlay/CodeView.jsx +4 -4
- package/dist/shared/dev-overlay/DevOverlayDialog.jsx +34 -34
- package/dist/shared/dev-overlay/index.jsx +2 -2
- package/dist/shared/dev-overlay/styles.css +40 -40
- package/package.json +27 -20
- package/src/config/constants.ts +1 -1
- package/src/config/dev-server.ts +12 -0
- package/src/config/env.ts +105 -0
- package/src/config/fs-routes/fs-watcher.ts +17 -24
- package/src/config/fs-routes/index.ts +2 -2
- package/src/config/fs-routes/router.ts +7 -8
- package/src/config/index.ts +44 -40
- package/src/config/lazy.ts +36 -5
- package/src/config/manifest.ts +40 -9
- package/src/config/vite-utils.ts +8 -4
- package/src/directives/bubble-function-declaration.ts +33 -0
- package/src/directives/compile.ts +54 -0
- package/src/directives/generate-unique-name.ts +22 -0
- package/src/directives/get-descriptive-name.ts +39 -0
- package/src/directives/get-import-identifier.ts +34 -0
- package/src/directives/get-root-statement-path.ts +14 -0
- package/src/directives/index.ts +232 -0
- package/src/directives/is-statement-top-level.ts +13 -0
- package/src/directives/paths.ts +63 -0
- package/src/directives/plugin.ts +389 -0
- package/src/directives/remove-unused-variables.ts +55 -0
- package/src/directives/types.ts +12 -0
- package/src/directives/xxhash32.ts +214 -0
- package/src/env.d.ts +1 -1
- package/src/fns/client.ts +141 -0
- package/src/fns/handler.spec.ts +85 -0
- package/src/{server/server-functions-handler.ts → fns/handler.ts} +65 -117
- package/src/fns/registration.ts +19 -0
- package/src/fns/serialization.ts +250 -0
- package/src/{server/server-fns-runtime.ts → fns/server.ts} +17 -2
- package/src/fns/shared.ts +116 -0
- package/src/middleware/index.ts +21 -1
- package/src/server/StartServer.tsx +2 -0
- package/src/server/assets/PatchVirtualDevStyles.tsx +31 -0
- package/src/server/collect-styles.ts +9 -26
- package/src/server/handler.ts +20 -16
- package/src/server/spa/StartServer.tsx +2 -0
- package/src/server/types.ts +1 -1
- package/src/shared/dev-overlay/CodeView.tsx +5 -7
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +34 -34
- package/src/shared/dev-overlay/get-source-map.ts +1 -1
- package/src/shared/dev-overlay/index.tsx +4 -4
- package/src/shared/dev-overlay/styles.css +40 -40
- package/tsconfig.json +1 -0
- package/dist/server/fetchEvent.spec.js +0 -65
- package/dist/server/server-fns-runtime.d.ts +0 -1
- package/dist/server/server-functions-handler.d.ts +0 -2
- package/dist/server/server-runtime.js +0 -194
- package/src/server/server-runtime.ts +0 -240
- /package/dist/{server/fetchEvent.spec.d.ts → directives/types.js} +0 -0
package/src/config/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { TanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
|
|
2
1
|
import { defu } from "defu";
|
|
3
2
|
import { globSync } from "node:fs";
|
|
4
|
-
import { extname, isAbsolute, join
|
|
5
|
-
import {
|
|
6
|
-
import { type PluginOption } from "vite";
|
|
3
|
+
import { extname, isAbsolute, join } from "node:path";
|
|
4
|
+
import type { PluginOption } from "vite";
|
|
7
5
|
import solid, { type Options as SolidOptions } from "vite-plugin-solid";
|
|
8
|
-
|
|
6
|
+
import { type ServerFunctionsOptions, serverFunctionsPlugin } from "../directives/index.ts";
|
|
9
7
|
import { DEFAULT_EXTENSIONS, VIRTUAL_MODULES, VITE_ENVIRONMENTS } from "./constants.ts";
|
|
10
8
|
import { devServer } from "./dev-server.ts";
|
|
9
|
+
import { envPlugin, type EnvPluginOptions } from "./env.ts";
|
|
11
10
|
import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.ts";
|
|
12
11
|
import { fsRoutes } from "./fs-routes/index.ts";
|
|
13
12
|
import type { BaseFileSystemRouter } from "./fs-routes/router.ts";
|
|
@@ -21,6 +20,19 @@ export interface SolidStartOptions {
|
|
|
21
20
|
routeDir?: string;
|
|
22
21
|
extensions?: string[];
|
|
23
22
|
middleware?: string;
|
|
23
|
+
serialization?: {
|
|
24
|
+
/**
|
|
25
|
+
* The serialization mode to use for server functions/actions.
|
|
26
|
+
* The "js" mode uses a custom binary format that is more efficient than JSON, but requires a custom deserializer (with `eval()`) on the client.
|
|
27
|
+
* A strong CSP should block `eval()` executions, which would prevent the "js" mode from working.
|
|
28
|
+
* The "json" mode uses JSON for serialization, which is less efficient but can be deserialized with `JSON.parse` on the client.
|
|
29
|
+
*
|
|
30
|
+
* @default "json"
|
|
31
|
+
*/
|
|
32
|
+
mode?: "js" | "json";
|
|
33
|
+
};
|
|
34
|
+
env?: EnvPluginOptions;
|
|
35
|
+
serverFunctions?: Pick<ServerFunctionsOptions, "filter">;
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
const absolute = (path: string, root: string) =>
|
|
@@ -80,6 +92,16 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
|
|
|
80
92
|
return {
|
|
81
93
|
appType: "custom",
|
|
82
94
|
build: { assetsDir: "_build/assets" },
|
|
95
|
+
optimizeDeps: {
|
|
96
|
+
// Suppress TS errors from Vite 7 types when configuring Vite 8's Rolldown
|
|
97
|
+
...({
|
|
98
|
+
rolldownOptions: {
|
|
99
|
+
transform: {
|
|
100
|
+
jsx: "react",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
} as any),
|
|
104
|
+
},
|
|
83
105
|
environments: {
|
|
84
106
|
[VITE_ENVIRONMENTS.client]: {
|
|
85
107
|
consumer: "client",
|
|
@@ -122,13 +144,19 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
|
|
|
122
144
|
}
|
|
123
145
|
: {}),
|
|
124
146
|
},
|
|
147
|
+
// Depending on the package manager and dependency structure Vite externalizes @solidjs/start
|
|
148
|
+
// This makes sure that @solidjs/start goes through the Vite build process
|
|
149
|
+
noExternal: ["@solidjs/start"],
|
|
125
150
|
},
|
|
126
151
|
define: {
|
|
127
152
|
"import.meta.env.MANIFEST": `globalThis.MANIFEST`,
|
|
128
153
|
"import.meta.env.START_SSR": JSON.stringify(start.ssr),
|
|
129
|
-
|
|
130
|
-
|
|
154
|
+
// Use JSON.stringify so backslashes on Windows are escaped and
|
|
155
|
+
// esbuild receives a valid JS string literal for the define value
|
|
156
|
+
"import.meta.env.START_APP_ENTRY": JSON.stringify(appEntryPath),
|
|
157
|
+
"import.meta.env.START_CLIENT_ENTRY": JSON.stringify(handlers.client),
|
|
131
158
|
"import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
|
|
159
|
+
"import.meta.env.SEROVAL_MODE": JSON.stringify(start.serialization?.mode || "json"),
|
|
132
160
|
},
|
|
133
161
|
builder: {
|
|
134
162
|
sharedPlugins: true,
|
|
@@ -161,41 +189,16 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
|
|
|
161
189
|
},
|
|
162
190
|
}),
|
|
163
191
|
lazy(),
|
|
192
|
+
envPlugin(options?.env),
|
|
164
193
|
// Must be placed after fsRoutes, as treeShake will remove the
|
|
165
194
|
// server fn exports added in by this plugin
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
callers: [
|
|
172
|
-
{
|
|
173
|
-
envConsumer: "client",
|
|
174
|
-
envName: VITE_ENVIRONMENTS.client,
|
|
175
|
-
getRuntimeCode: () =>
|
|
176
|
-
`import { createServerReference } from "${normalize(
|
|
177
|
-
fileURLToPath(new URL("../server/server-runtime", import.meta.url)),
|
|
178
|
-
)}"`,
|
|
179
|
-
replacer: opts => `createServerReference('${opts.functionId}')`,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
envConsumer: "server",
|
|
183
|
-
envName: VITE_ENVIRONMENTS.server,
|
|
184
|
-
getRuntimeCode: () =>
|
|
185
|
-
`import { createServerReference } from '${normalize(
|
|
186
|
-
fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)),
|
|
187
|
-
)}'`,
|
|
188
|
-
replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
|
|
189
|
-
},
|
|
190
|
-
],
|
|
191
|
-
provider: {
|
|
192
|
-
envName: VITE_ENVIRONMENTS.server,
|
|
193
|
-
getRuntimeCode: () =>
|
|
194
|
-
`import { createServerReference } from '${normalize(
|
|
195
|
-
fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)),
|
|
196
|
-
)}'`,
|
|
197
|
-
replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
|
|
195
|
+
serverFunctionsPlugin({
|
|
196
|
+
manifest: VIRTUAL_MODULES.serverFnManifest,
|
|
197
|
+
runtime: {
|
|
198
|
+
server: '@solidjs/start/fns/server',
|
|
199
|
+
client: '@solidjs/start/fns/client',
|
|
198
200
|
},
|
|
201
|
+
filter: options?.serverFunctions?.filter,
|
|
199
202
|
}),
|
|
200
203
|
{
|
|
201
204
|
name: "solid-start:virtual-modules",
|
|
@@ -219,8 +222,9 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
|
|
|
219
222
|
{
|
|
220
223
|
name: "solid-start:capture-client-bundle",
|
|
221
224
|
enforce: "post",
|
|
222
|
-
generateBundle(
|
|
225
|
+
generateBundle(options, bundle) {
|
|
223
226
|
globalThis.START_CLIENT_BUNDLE = bundle;
|
|
227
|
+
(globalThis as any).START_CLIENT_OUT_DIR = options.dir;
|
|
224
228
|
},
|
|
225
229
|
},
|
|
226
230
|
devServer(),
|
package/src/config/lazy.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { PluginItem } from "@babel/core";
|
|
2
2
|
import babel from "@babel/core";
|
|
3
3
|
import * as t from "@babel/types";
|
|
4
|
-
import { sep as osSep } from "path";
|
|
5
|
-
import { basename, relative, sep } from "path/posix";
|
|
4
|
+
import { sep as osSep } from "node:path";
|
|
5
|
+
import { basename, relative, sep } from "node:path/posix";
|
|
6
6
|
import type { PluginOption } from "vite";
|
|
7
7
|
import { VITE_ENVIRONMENTS } from "./constants.ts";
|
|
8
8
|
|
|
@@ -48,13 +48,43 @@ const fileEndingRegex = /(ts|js)x(\?.*)?$/;
|
|
|
48
48
|
|
|
49
49
|
const lazy = (): PluginOption => {
|
|
50
50
|
const cwd = process.cwd().replaceAll(osSep, sep);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Maps module ids to their client-specific shared chunk names.
|
|
54
|
+
* Modules in shared chunks need to find their assets via the chunk name, instead of their module id.
|
|
55
|
+
*
|
|
56
|
+
* Vite includes assets of such modules in the manifest via the chunk name:
|
|
57
|
+
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
|
|
58
|
+
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L319
|
|
59
|
+
*
|
|
60
|
+
* Rollup occassionally creates shared chunks automatically,
|
|
61
|
+
* but they can also be manually created by the user via:
|
|
62
|
+
* https://rollupjs.org/configuration-options/#output-manualchunks
|
|
63
|
+
*
|
|
64
|
+
* More infos on Rollup's logic:
|
|
65
|
+
* https://github.com/rollup/rollup/issues/3772#issuecomment-689955168
|
|
66
|
+
*/
|
|
67
|
+
const sharedChunkNames: Record<string, string> = {};
|
|
68
|
+
|
|
51
69
|
return {
|
|
52
70
|
name: "solid-lazy-css",
|
|
53
71
|
enforce: "pre",
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
generateBundle(_, bundle) {
|
|
73
|
+
if (this.environment.name !== VITE_ENVIRONMENTS.client) return;
|
|
74
|
+
|
|
75
|
+
for (const chunk of Object.values(bundle)) {
|
|
76
|
+
if (chunk.type !== "chunk" || !chunk.isDynamicEntry || chunk.facadeModuleId) continue;
|
|
77
|
+
|
|
78
|
+
// Has to follow Vites implementation:
|
|
79
|
+
// https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
|
|
80
|
+
const chunkName = `_${basename(chunk.fileName)}`;
|
|
81
|
+
for (const id of chunk.moduleIds) {
|
|
82
|
+
sharedChunkNames[id] = chunkName;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
56
85
|
},
|
|
57
86
|
async transform(src, id) {
|
|
87
|
+
if (this.environment.name !== VITE_ENVIRONMENTS.server) return;
|
|
58
88
|
if (!id.match(fileEndingRegex)) return;
|
|
59
89
|
|
|
60
90
|
// The transformed files either import "lazy" or css files
|
|
@@ -66,7 +96,8 @@ const lazy = (): PluginOption => {
|
|
|
66
96
|
const hasDefaultExport = src.indexOf("export default") !== -1;
|
|
67
97
|
if (hasDefaultExport) {
|
|
68
98
|
const localId = relative(cwd, id);
|
|
69
|
-
|
|
99
|
+
const chunkName = sharedChunkNames[id];
|
|
100
|
+
plugins.push(idTransform(chunkName ?? localId));
|
|
70
101
|
}
|
|
71
102
|
|
|
72
103
|
const hasLazy = src.indexOf("lazy(") !== -1;
|
package/src/config/manifest.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { type PluginOption, type ViteDevServer, version as viteVersion } from "vite";
|
|
2
4
|
|
|
3
5
|
import { findStylesInModuleGraph } from "../server/collect-styles.ts";
|
|
4
6
|
import { VIRTUAL_MODULES } from "./constants.ts";
|
|
5
7
|
import { type SolidStartOptions } from "./index.ts";
|
|
8
|
+
import { wrapId } from "./vite-utils.ts";
|
|
6
9
|
|
|
7
10
|
export function manifest(start: SolidStartOptions): PluginOption {
|
|
8
11
|
let devServer: ViteDevServer = undefined!;
|
|
@@ -39,9 +42,37 @@ export function manifest(start: SolidStartOptions): PluginOption {
|
|
|
39
42
|
v => "isEntry" in v && v.isEntry,
|
|
40
43
|
);
|
|
41
44
|
if (!entry) throw new Error("No client entry found");
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
+
let rawManifest: string | undefined;
|
|
46
|
+
|
|
47
|
+
const viteMajor = parseInt(viteVersion.split('.')[0]!, 10);
|
|
48
|
+
|
|
49
|
+
const manifestKey = Object.keys(globalThis.START_CLIENT_BUNDLE).find(k => k.endsWith("manifest.json"));
|
|
50
|
+
if (manifestKey && viteMajor < 8) {
|
|
51
|
+
const manifestAsset = globalThis.START_CLIENT_BUNDLE[manifestKey] as any;
|
|
52
|
+
rawManifest = manifestAsset.source as string;
|
|
53
|
+
} else {
|
|
54
|
+
try {
|
|
55
|
+
const appRoot = (start as any).appRoot || "./src";
|
|
56
|
+
let outDir = ".solid-start/client";
|
|
57
|
+
if (devServer?.environments?.client?.config?.build?.outDir) {
|
|
58
|
+
outDir = devServer.environments.client.config.build.outDir;
|
|
59
|
+
} else if (this.environment?.config?.build?.outDir && this.environment?.config?.consumer === "client") {
|
|
60
|
+
outDir = this.environment.config.build.outDir;
|
|
61
|
+
} else if ((globalThis as any).START_CLIENT_OUT_DIR) {
|
|
62
|
+
outDir = (globalThis as any).START_CLIENT_OUT_DIR;
|
|
63
|
+
}
|
|
64
|
+
const manifestPath = path.resolve(appRoot, "..", outDir, ".vite/manifest.json");
|
|
65
|
+
rawManifest = fs.readFileSync(manifestPath, "utf-8");
|
|
66
|
+
} catch (e) {
|
|
67
|
+
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}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!rawManifest) {
|
|
72
|
+
throw new Error("Failed to extract or read raw manifest.");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
clientViteManifest = JSON.parse(rawManifest);
|
|
45
76
|
}
|
|
46
77
|
return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`;
|
|
47
78
|
} else if (id === `\0${VIRTUAL_MODULES.middleware}`) return "export default {};";
|
|
@@ -49,11 +80,11 @@ export function manifest(start: SolidStartOptions): PluginOption {
|
|
|
49
80
|
if (this.environment.mode !== "dev")
|
|
50
81
|
throw new Error("@manifest queries are only allowed in dev");
|
|
51
82
|
|
|
52
|
-
const [
|
|
83
|
+
const [urlPath, query] = id.split("?");
|
|
53
84
|
const target = id.split("/")[2]!;
|
|
54
85
|
const params = new URLSearchParams(query);
|
|
55
|
-
if (!
|
|
56
|
-
if (
|
|
86
|
+
if (!urlPath || !query) return;
|
|
87
|
+
if (urlPath.endsWith("assets")) {
|
|
57
88
|
const id = params.get("id");
|
|
58
89
|
if (!id) {
|
|
59
90
|
throw new Error("Missing id to get assets.");
|
|
@@ -69,10 +100,10 @@ export function manifest(start: SolidStartOptions): PluginOption {
|
|
|
69
100
|
tag: "style",
|
|
70
101
|
attrs: {
|
|
71
102
|
type: "text/css",
|
|
72
|
-
"data-vite-dev-id": "${key}",
|
|
103
|
+
"data-vite-dev-id": "${wrapId(key)}",
|
|
73
104
|
"data-vite-ref": "0",
|
|
74
105
|
},
|
|
75
|
-
children: () => import("${value}?inline").then(mod => mod.default),
|
|
106
|
+
children: () => import("${wrapId(value)}?inline").then(mod => mod.default),
|
|
76
107
|
}`,
|
|
77
108
|
);
|
|
78
109
|
|
package/src/config/vite-utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DevEnvironment, Rollup } from "vite";
|
|
1
|
+
import type { DevEnvironment, Rollup } from "vite";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
@@ -12,6 +12,7 @@ export const FS_PREFIX = `/@fs/`;
|
|
|
12
12
|
export const VALID_ID_PREFIX = `/@id/`;
|
|
13
13
|
|
|
14
14
|
export const NULL_BYTE_PLACEHOLDER = `__x00__`;
|
|
15
|
+
const NULL_BYTE_REGEX = /^\0/;
|
|
15
16
|
|
|
16
17
|
export function normalizeResolvedIdToUrl(
|
|
17
18
|
environment: DevEnvironment,
|
|
@@ -52,10 +53,13 @@ export function normalizeResolvedIdToUrl(
|
|
|
52
53
|
return url;
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Inspired by:
|
|
58
|
+
* https://github.com/withastro/astro/blob/fddde5fad81007795eb263c7fd0cea096b8e2cba/packages/astro/src/core/util.ts#L115
|
|
59
|
+
* https://github.com/vitejs/vite/blob/130e7181a55c524383c63bbfb1749d0ff7185cad/packages/vite/src/shared/utils.ts#L11
|
|
60
|
+
*/
|
|
55
61
|
export function wrapId(id: string): string {
|
|
56
|
-
return id.
|
|
57
|
-
? id
|
|
58
|
-
: VALID_ID_PREFIX + id.replace("\0", NULL_BYTE_PLACEHOLDER);
|
|
62
|
+
return id.replace(NULL_BYTE_REGEX, `${VALID_ID_PREFIX}${NULL_BYTE_PLACEHOLDER}`);
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
export function unwrapId(id: string): string {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type * as babel from "@babel/core";
|
|
2
|
+
import * as t from "@babel/types";
|
|
3
|
+
|
|
4
|
+
export function bubbleFunctionDeclaration(path: babel.NodePath<t.FunctionDeclaration>): void {
|
|
5
|
+
const decl = path.node;
|
|
6
|
+
// Check if declaration is FunctionDeclaration
|
|
7
|
+
if (decl.id) {
|
|
8
|
+
const block = (path.findParent(current => current.isBlockStatement()) ||
|
|
9
|
+
path.scope.getProgramParent().path) as babel.NodePath<t.BlockStatement>;
|
|
10
|
+
|
|
11
|
+
if (path.parentPath.isExportNamedDeclaration()) {
|
|
12
|
+
path.parentPath.replaceWith(
|
|
13
|
+
t.exportNamedDeclaration(undefined, [t.exportSpecifier(decl.id, decl.id)]),
|
|
14
|
+
);
|
|
15
|
+
} else if (path.parentPath.isExportDefaultDeclaration()) {
|
|
16
|
+
path.replaceWith(decl.id);
|
|
17
|
+
} else {
|
|
18
|
+
path.remove();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const [tmp] = block.unshiftContainer(
|
|
22
|
+
"body",
|
|
23
|
+
t.variableDeclaration("const", [
|
|
24
|
+
t.variableDeclarator(
|
|
25
|
+
decl.id,
|
|
26
|
+
t.functionExpression(decl.id, decl.params, decl.body, decl.generator, decl.async),
|
|
27
|
+
),
|
|
28
|
+
]),
|
|
29
|
+
);
|
|
30
|
+
block.scope.registerDeclaration(tmp);
|
|
31
|
+
tmp.skip();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as babel from "@babel/core";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { directivesPlugin, type StateContext } from "./plugin.ts";
|
|
4
|
+
import xxHash32 from "./xxhash32.ts";
|
|
5
|
+
|
|
6
|
+
export interface CompileResult {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
code: string;
|
|
9
|
+
map: babel.BabelFileResult["map"];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type CompileOptions = Omit<StateContext, "count" | "hash" | "imports" | "valid">;
|
|
13
|
+
|
|
14
|
+
export async function compile(
|
|
15
|
+
id: string,
|
|
16
|
+
code: string,
|
|
17
|
+
options: CompileOptions,
|
|
18
|
+
): Promise<CompileResult> {
|
|
19
|
+
const context: StateContext = {
|
|
20
|
+
...options,
|
|
21
|
+
valid: false,
|
|
22
|
+
hash: xxHash32(id).toString(16),
|
|
23
|
+
count: 0,
|
|
24
|
+
imports: new Map(),
|
|
25
|
+
};
|
|
26
|
+
const pluginOption = [directivesPlugin, context];
|
|
27
|
+
const plugins: NonNullable<NonNullable<babel.TransformOptions["parserOpts"]>["plugins"]> = [
|
|
28
|
+
"jsx",
|
|
29
|
+
];
|
|
30
|
+
if (/\.[mc]?tsx?$/i.test(id)) {
|
|
31
|
+
plugins.push("typescript");
|
|
32
|
+
}
|
|
33
|
+
const result = await babel.transformAsync(code, {
|
|
34
|
+
plugins: [pluginOption],
|
|
35
|
+
parserOpts: {
|
|
36
|
+
plugins,
|
|
37
|
+
},
|
|
38
|
+
filename: path.basename(id),
|
|
39
|
+
ast: false,
|
|
40
|
+
sourceMaps: true,
|
|
41
|
+
configFile: false,
|
|
42
|
+
babelrc: false,
|
|
43
|
+
sourceFileName: id,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (result) {
|
|
47
|
+
return {
|
|
48
|
+
valid: context.valid,
|
|
49
|
+
code: result.code || "",
|
|
50
|
+
map: result.map,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
throw new Error("invariant");
|
|
54
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type * as babel from "@babel/core";
|
|
2
|
+
import * as t from "@babel/types";
|
|
3
|
+
|
|
4
|
+
export function generateUniqueName(path: babel.NodePath, name: string): t.Identifier {
|
|
5
|
+
let uid: string;
|
|
6
|
+
let i = 1;
|
|
7
|
+
do {
|
|
8
|
+
uid = name + "_" + i;
|
|
9
|
+
i++;
|
|
10
|
+
} while (
|
|
11
|
+
path.scope.hasLabel(uid) ||
|
|
12
|
+
path.scope.hasBinding(uid) ||
|
|
13
|
+
path.scope.hasGlobal(uid) ||
|
|
14
|
+
path.scope.hasReference(uid)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const program = path.scope.getProgramParent();
|
|
18
|
+
program.references[uid] = true;
|
|
19
|
+
program.uids[uid] = true;
|
|
20
|
+
|
|
21
|
+
return t.identifier(uid);
|
|
22
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/core";
|
|
2
|
+
|
|
3
|
+
export function getDescriptiveName(path: NodePath, defaultName: string): string {
|
|
4
|
+
let current: NodePath | null = path;
|
|
5
|
+
while (current) {
|
|
6
|
+
switch (current.node.type) {
|
|
7
|
+
case "FunctionDeclaration":
|
|
8
|
+
case "FunctionExpression": {
|
|
9
|
+
if (current.node.id) {
|
|
10
|
+
return current.node.id.name;
|
|
11
|
+
}
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
case "VariableDeclarator": {
|
|
15
|
+
if (current.node.id.type === "Identifier") {
|
|
16
|
+
return current.node.id.name;
|
|
17
|
+
}
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case "ClassPrivateMethod":
|
|
21
|
+
case "ClassMethod":
|
|
22
|
+
case "ObjectMethod": {
|
|
23
|
+
switch (current.node.key.type) {
|
|
24
|
+
case "Identifier":
|
|
25
|
+
return current.node.key.name;
|
|
26
|
+
case "PrivateName":
|
|
27
|
+
return current.node.key.id.name;
|
|
28
|
+
default:
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
default:
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
current = current.parentPath;
|
|
37
|
+
}
|
|
38
|
+
return defaultName;
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type * as babel from "@babel/core";
|
|
2
|
+
import * as t from "@babel/types";
|
|
3
|
+
import { generateUniqueName } from "./generate-unique-name.ts";
|
|
4
|
+
import type { ImportDefinition } from "./types.ts";
|
|
5
|
+
|
|
6
|
+
export function getImportIdentifier(
|
|
7
|
+
imports: Map<string, t.Identifier>,
|
|
8
|
+
path: babel.NodePath,
|
|
9
|
+
registration: ImportDefinition,
|
|
10
|
+
): t.Identifier {
|
|
11
|
+
const name = registration.kind === "named" ? registration.name : "default";
|
|
12
|
+
const target = `${registration.source}[${name}]`;
|
|
13
|
+
const current = imports.get(target);
|
|
14
|
+
if (current) {
|
|
15
|
+
return current;
|
|
16
|
+
}
|
|
17
|
+
const programParent = path.scope.getProgramParent();
|
|
18
|
+
const uid = generateUniqueName(programParent.path, name);
|
|
19
|
+
programParent.registerDeclaration(
|
|
20
|
+
(programParent.path as babel.NodePath<t.Program>).unshiftContainer(
|
|
21
|
+
"body",
|
|
22
|
+
t.importDeclaration(
|
|
23
|
+
[
|
|
24
|
+
registration.kind === "named"
|
|
25
|
+
? t.importSpecifier(uid, t.identifier(registration.name))
|
|
26
|
+
: t.importDefaultSpecifier(uid),
|
|
27
|
+
],
|
|
28
|
+
t.stringLiteral(registration.source),
|
|
29
|
+
),
|
|
30
|
+
)[0],
|
|
31
|
+
);
|
|
32
|
+
imports.set(target, uid);
|
|
33
|
+
return uid;
|
|
34
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type * as babel from "@babel/core";
|
|
2
|
+
import * as t from "@babel/types";
|
|
3
|
+
|
|
4
|
+
export function getRootStatementPath(path: babel.NodePath): babel.NodePath {
|
|
5
|
+
let current = path.parentPath;
|
|
6
|
+
while (current) {
|
|
7
|
+
const next = current.parentPath;
|
|
8
|
+
if (next && t.isProgram(next.node)) {
|
|
9
|
+
return current;
|
|
10
|
+
}
|
|
11
|
+
current = next;
|
|
12
|
+
}
|
|
13
|
+
return path;
|
|
14
|
+
}
|