@nasti-toolchain/nasti 2.5.0 → 2.5.2

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 (60) hide show
  1. package/README.md +34 -2
  2. package/dist/build-CENae4VM.js +748 -0
  3. package/dist/build-CENae4VM.js.map +1 -0
  4. package/dist/build-vjh6h7PB.cjs +786 -0
  5. package/dist/build-vjh6h7PB.cjs.map +1 -0
  6. package/dist/cli.cjs +166 -7608
  7. package/dist/cli.cjs.map +1 -1
  8. package/dist/cli.d.cts +1 -2
  9. package/dist/cli.d.ts +1 -2
  10. package/dist/cli.js +166 -7606
  11. package/dist/cli.js.map +1 -1
  12. package/dist/client/hmr.cjs +0 -19
  13. package/dist/client/hmr.d.cts +14 -12
  14. package/dist/client/hmr.d.cts.map +1 -0
  15. package/dist/client/hmr.d.ts +14 -12
  16. package/dist/client/hmr.d.ts.map +1 -0
  17. package/dist/client/hmr.js +1 -1
  18. package/dist/dev-engine-DJL9sfv5.cjs +473 -0
  19. package/dist/dev-engine-DJL9sfv5.cjs.map +1 -0
  20. package/dist/dev-engine-DapuTPIz.js +469 -0
  21. package/dist/dev-engine-DapuTPIz.js.map +1 -0
  22. package/dist/electron-Bj8H-BJ6.js +278 -0
  23. package/dist/electron-Bj8H-BJ6.js.map +1 -0
  24. package/dist/electron-D0PSXz-a.cjs +316 -0
  25. package/dist/electron-D0PSXz-a.cjs.map +1 -0
  26. package/dist/electron-dev-BzI2IFnR.cjs +272 -0
  27. package/dist/electron-dev-BzI2IFnR.cjs.map +1 -0
  28. package/dist/electron-dev-CM15gsFp.js +251 -0
  29. package/dist/electron-dev-CM15gsFp.js.map +1 -0
  30. package/dist/env-GY7K1zPK.js +833 -0
  31. package/dist/env-GY7K1zPK.js.map +1 -0
  32. package/dist/env-lOj3yw8v.cjs +924 -0
  33. package/dist/env-lOj3yw8v.cjs.map +1 -0
  34. package/dist/environment-B2jCrhY2.js +1361 -0
  35. package/dist/environment-B2jCrhY2.js.map +1 -0
  36. package/dist/environment-CjmvoHIG.cjs +1443 -0
  37. package/dist/environment-CjmvoHIG.cjs.map +1 -0
  38. package/dist/index.cjs +453 -7976
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +872 -817
  41. package/dist/index.d.cts.map +1 -0
  42. package/dist/index.d.ts +872 -817
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +418 -7939
  45. package/dist/index.js.map +1 -1
  46. package/dist/logger-BVZwdqqT.js +116 -0
  47. package/dist/logger-BVZwdqqT.js.map +1 -0
  48. package/dist/logger-M7AuVVTV.cjs +171 -0
  49. package/dist/logger-M7AuVVTV.cjs.map +1 -0
  50. package/dist/runnable-environment-BjoOvdDa.js +1345 -0
  51. package/dist/runnable-environment-BjoOvdDa.js.map +1 -0
  52. package/dist/runnable-environment-ByA3DHQ6.cjs +1351 -0
  53. package/dist/runnable-environment-ByA3DHQ6.cjs.map +1 -0
  54. package/dist/server-Bqgl25z0.js +1871 -0
  55. package/dist/server-Bqgl25z0.js.map +1 -0
  56. package/dist/server-BynlMdFc.cjs +1895 -0
  57. package/dist/server-BynlMdFc.cjs.map +1 -0
  58. package/package.json +20 -10
  59. package/dist/client/hmr.cjs.map +0 -1
  60. package/dist/client/hmr.js.map +0 -1
@@ -0,0 +1,278 @@
1
+ import { a as __exportAll } from "./logger-BVZwdqqT.js";
2
+ import { c as transformReactCode, f as resolveConfig, h as resolveMinifyOption, l as resolvePlugin, n as loadEnv, o as shouldTransform, s as transformCode, t as buildEnvDefine } from "./env-GY7K1zPK.js";
3
+ import { builtinModules, createRequire } from "node:module";
4
+ import path from "node:path";
5
+ import fs from "node:fs";
6
+ import pc from "picocolors";
7
+ import { rolldown } from "rolldown";
8
+ //#region src/plugins/electron.ts
9
+ const NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
10
+ const ELECTRON_MODULES = /* @__PURE__ */ new Set([
11
+ "electron",
12
+ "electron/main",
13
+ "electron/common",
14
+ "electron/renderer"
15
+ ]);
16
+ /**
17
+ * Create a Vite/Rollup plugin that externalizes Electron and Node built-in imports according to the resolved config.
18
+ *
19
+ * @param config - Resolved build config; any entries in `config.electron.external` are added to the externalized modules set.
20
+ * @returns A plugin that marks `electron` and `electron/*` imports and Node built-in modules (including `node:`-prefixed names) as external.
21
+ */
22
+ function electronPlugin(config) {
23
+ const external = /* @__PURE__ */ new Set([
24
+ ...ELECTRON_MODULES,
25
+ ...NODE_BUILTINS,
26
+ ...config.electron.external ?? []
27
+ ]);
28
+ return {
29
+ name: "nasti:electron",
30
+ enforce: "pre",
31
+ resolveId(source) {
32
+ if (external.has(source)) return {
33
+ id: source,
34
+ external: true
35
+ };
36
+ if (source.startsWith("electron/")) return {
37
+ id: source,
38
+ external: true
39
+ };
40
+ return null;
41
+ }
42
+ };
43
+ }
44
+ //#endregion
45
+ //#region src/build/electron.ts
46
+ var electron_exports = /* @__PURE__ */ __exportAll({
47
+ buildElectron: () => buildElectron,
48
+ createElectronRendererConfig: () => createElectronRendererConfig,
49
+ detectInstalledElectron: () => detectInstalledElectron,
50
+ normalizePreload: () => normalizePreload
51
+ });
52
+ /**
53
+ * Performs a full Electron build pipeline producing renderer, main, and preload artifacts.
54
+ *
55
+ * Resolves an Electron-targeted config, validates the installed Electron version, prepares the output directory, builds the renderer (via the web build), bundles the main process, bundles configured preload scripts, and logs a summary.
56
+ *
57
+ * @param inlineConfig - Optional config overrides merged into the resolved build configuration
58
+ * @returns An object with `rendererOutDir` (renderer output directory), `mainFile` (bundled main process file path), and `preloadFiles` (array of bundled preload file paths)
59
+ * @throws Error if the configured Electron main entry file does not exist
60
+ */
61
+ async function buildElectron(inlineConfig = {}) {
62
+ const config = await resolveConfig({
63
+ ...inlineConfig,
64
+ target: "electron"
65
+ }, "build");
66
+ const startTime = performance.now();
67
+ assertElectronVersion(config);
68
+ console.log(pc.cyan("\n⚡ nasti build (electron)") + pc.dim(` v2.5.2`));
69
+ console.log(pc.dim(` root: ${config.root}`));
70
+ console.log(pc.dim(` mode: ${config.mode}`));
71
+ console.log(pc.dim(` target: electron (≥ ${config.electron.minVersion})`));
72
+ const outDir = path.resolve(config.root, config.build.outDir);
73
+ if (config.build.emptyOutDir && fs.existsSync(outDir)) fs.rmSync(outDir, {
74
+ recursive: true,
75
+ force: true
76
+ });
77
+ fs.mkdirSync(outDir, { recursive: true });
78
+ const rendererOutDir = path.join(outDir, "renderer");
79
+ const { build } = await import("./build-CENae4VM.js").then((n) => n.n);
80
+ await build(createElectronRendererConfig(config, inlineConfig, { build: {
81
+ ...inlineConfig.build,
82
+ outDir: rendererOutDir,
83
+ emptyOutDir: false
84
+ } }));
85
+ const mainEntry = path.resolve(config.root, config.electron.main);
86
+ if (!fs.existsSync(mainEntry)) throw new Error(`Electron main entry not found: ${config.electron.main}\n在 nasti.config.ts 的 electron.main 指定主进程入口文件。`);
87
+ const mainFile = await bundleNode(config, mainEntry, {
88
+ outFile: outFileName(outDir, "main", config.electron.mainFormat),
89
+ format: config.electron.mainFormat,
90
+ label: "main"
91
+ });
92
+ const preloadEntries = normalizePreload(config.electron.preload, config.root);
93
+ const preloadFiles = [];
94
+ for (const entry of preloadEntries) {
95
+ if (!fs.existsSync(entry)) {
96
+ console.warn(pc.yellow(` ⚠ preload entry not found, skipped: ${entry}`));
97
+ continue;
98
+ }
99
+ const base = path.basename(entry).replace(/\.[^.]+$/, "");
100
+ const out = outFileName(outDir, base, config.electron.preloadFormat);
101
+ await bundleNode(config, entry, {
102
+ outFile: out,
103
+ format: config.electron.preloadFormat,
104
+ label: `preload (${base})`
105
+ });
106
+ preloadFiles.push(out);
107
+ }
108
+ const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
109
+ console.log(pc.green(`\n✓ Electron build complete in ${elapsed}s`));
110
+ console.log(pc.dim(` renderer: ${path.relative(config.root, rendererOutDir)}/`));
111
+ console.log(pc.dim(` main: ${path.relative(config.root, mainFile)}`));
112
+ for (const pf of preloadFiles) console.log(pc.dim(` preload: ${path.relative(config.root, pf)}`));
113
+ console.log();
114
+ return {
115
+ rendererOutDir,
116
+ mainFile,
117
+ preloadFiles
118
+ };
119
+ }
120
+ /**
121
+ * Bundles a Node-targeted entry for Electron into a single output file using Rolldown and the OXC transform.
122
+ *
123
+ * @param config - Fully resolved build configuration used to drive transforms, defines, plugins, and output options
124
+ * @param entry - Absolute path to the entry file to bundle
125
+ * @param opts - Bundle options; expects `outFile` (destination path), `format` (`'cjs'` or `'esm'`), and `label` (human-readable name for logging)
126
+ * @returns The path to the written bundle file (`opts.outFile`)
127
+ */
128
+ async function bundleNode(config, entry, opts) {
129
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
130
+ const envDefine = {
131
+ ...buildEnvDefine(env, config.mode),
132
+ __ELECTRON__: "true",
133
+ __NASTI_TARGET__: JSON.stringify("electron")
134
+ };
135
+ const oxcTransformPlugin = {
136
+ name: "nasti:oxc-transform",
137
+ async transform(code, id) {
138
+ const result = config.framework === "react" ? await transformReactCode(id, code, {
139
+ react: config.react,
140
+ consumer: "server",
141
+ development: config.mode === "development",
142
+ sourcemap: !!config.build.sourcemap,
143
+ target: config.electron.nodeTarget,
144
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
145
+ }) : shouldTransform(id) ? transformCode(id, code, {
146
+ sourcemap: !!config.build.sourcemap,
147
+ jsxRuntime: "automatic",
148
+ jsxImportSource: "vue",
149
+ target: config.electron.nodeTarget
150
+ }) : null;
151
+ if (!result) return null;
152
+ return {
153
+ code: result.code,
154
+ map: result.map ? JSON.parse(result.map) : void 0
155
+ };
156
+ }
157
+ };
158
+ const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
159
+ const mergedDefine = {
160
+ ...userTransform?.define ?? {},
161
+ ...envDefine
162
+ };
163
+ const bundle = await rolldown({
164
+ ...restInputOptions,
165
+ input: entry,
166
+ platform: "node",
167
+ transform: {
168
+ ...userTransform,
169
+ target: config.electron.nodeTarget,
170
+ define: mergedDefine
171
+ },
172
+ plugins: [
173
+ oxcTransformPlugin,
174
+ electronPlugin(config),
175
+ resolvePlugin(config)
176
+ ]
177
+ });
178
+ fs.mkdirSync(path.dirname(opts.outFile), { recursive: true });
179
+ await bundle.write({
180
+ sourcemap: !!config.build.sourcemap,
181
+ minify: resolveMinifyOption(config.build.minify),
182
+ ...userOutput,
183
+ file: opts.outFile,
184
+ format: opts.format === "cjs" ? "cjs" : "esm",
185
+ codeSplitting: false
186
+ });
187
+ await bundle.close();
188
+ console.log(pc.dim(` ✓ ${opts.label} → ${path.relative(config.root, opts.outFile)}`));
189
+ return opts.outFile;
190
+ }
191
+ /**
192
+ * 从 Electron 配置派生 renderer 的普通 Web 构建配置。
193
+ *
194
+ * renderer 使用指定 HTML 入口;本地文件加载场景默认把 `/` base 收敛为
195
+ * `./`,避免产物中的 `/assets/*` 被解析到文件系统根目录。
196
+ */
197
+ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
198
+ const inlineClient = inlineConfig.environments?.client ?? {};
199
+ return {
200
+ ...inlineConfig,
201
+ ...overrides,
202
+ root: config.root,
203
+ mode: config.mode,
204
+ target: "web",
205
+ framework: config.framework,
206
+ base: config.base === "/" ? "./" : config.base,
207
+ environments: {
208
+ ...inlineConfig.environments ?? {},
209
+ client: {
210
+ ...inlineClient,
211
+ html: config.electron.renderer
212
+ }
213
+ }
214
+ };
215
+ }
216
+ /**
217
+ * Compute an output file path for a given base name and module format.
218
+ *
219
+ * @param outDir - Directory where the output file will be placed
220
+ * @param base - Base filename without extension
221
+ * @param format - Module format; `cjs` yields a `.cjs` extension, `esm` yields a `.mjs` extension
222
+ * @returns The resolved file path combining `outDir` and `base` with the appropriate extension
223
+ */
224
+ function outFileName(outDir, base, format) {
225
+ const ext = format === "cjs" ? ".cjs" : ".mjs";
226
+ return path.join(outDir, base + ext);
227
+ }
228
+ /**
229
+ * Normalize Electron preload entries into absolute file paths.
230
+ *
231
+ * @param preload - A single preload path or an array of preload paths; a falsy value produces an empty list
232
+ * @param root - Root directory used to resolve relative preload entries
233
+ * @returns An array of absolute file paths for each preload entry
234
+ */
235
+ function normalizePreload(preload, root) {
236
+ return (Array.isArray(preload) ? preload : preload ? [preload] : []).map((p) => path.resolve(root, p));
237
+ }
238
+ /**
239
+ * Warns when the detected Electron major version is lower than the configured minimum.
240
+ *
241
+ * Checks the project for an installed Electron package and, if its major version
242
+ * is less than `config.electron.minVersion`, logs a yellow warning describing the mismatch.
243
+ *
244
+ * @param config - Resolved build configuration that contains `electron.minVersion` and project `root`
245
+ */
246
+ function assertElectronVersion(config) {
247
+ const min = config.electron.minVersion;
248
+ const installed = detectInstalledElectron(config.root);
249
+ if (installed && installed < min) console.warn(pc.yellow(` ⚠ 检测到 Electron ${installed},Nasti 要求 ≥ ${min}。旧版本可能缺少 ESM 主进程支持。`));
250
+ }
251
+ /**
252
+ * Detects the installed Electron major version in the given project root.
253
+ *
254
+ * @param root - Project root directory used to locate electron via Node resolution
255
+ * @returns The major Electron version as a number, or `null` if Electron is not installed or the version cannot be determined
256
+ */
257
+ function detectInstalledElectron(root) {
258
+ try {
259
+ const pkgPath = createRequire(path.resolve(root, "package.json")).resolve("electron/package.json");
260
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
261
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
262
+ return Number.isFinite(major) ? major : null;
263
+ } catch {
264
+ try {
265
+ const pkgPath = path.resolve(root, "node_modules/electron/package.json");
266
+ if (!fs.existsSync(pkgPath)) return null;
267
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
268
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
269
+ return Number.isFinite(major) ? major : null;
270
+ } catch {
271
+ return null;
272
+ }
273
+ }
274
+ }
275
+ //#endregion
276
+ export { normalizePreload as a, electron_exports as i, createElectronRendererConfig as n, electronPlugin as o, detectInstalledElectron as r, buildElectron as t };
277
+
278
+ //# sourceMappingURL=electron-Bj8H-BJ6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"electron-Bj8H-BJ6.js","names":[],"sources":["../src/plugins/electron.ts","../src/build/electron.ts"],"sourcesContent":["// Electron 内置插件\n//\n// 负责:将 Electron 模块(electron、electron/*)与 Node 内建模块(fs、path、...)\n// 标记为 external,避免被打包进主进程/Preload 产物。\n//\n// 仅在 config.target === 'electron' 时启用\nimport { builtinModules } from 'node:module'\nimport type { NastiPlugin, ResolvedConfig } from '../types.js'\n\nconst NODE_BUILTINS = new Set([\n ...builtinModules,\n ...builtinModules.map((m) => `node:${m}`),\n])\n\nconst ELECTRON_MODULES = new Set([\n 'electron',\n 'electron/main',\n 'electron/common',\n 'electron/renderer',\n])\n\n/**\n * Create a Vite/Rollup plugin that externalizes Electron and Node built-in imports according to the resolved config.\n *\n * @param config - Resolved build config; any entries in `config.electron.external` are added to the externalized modules set.\n * @returns A plugin that marks `electron` and `electron/*` imports and Node built-in modules (including `node:`-prefixed names) as external.\n */\nexport function electronPlugin(config: ResolvedConfig): NastiPlugin {\n const external = new Set([\n ...ELECTRON_MODULES,\n ...NODE_BUILTINS,\n ...(config.electron.external ?? []),\n ])\n\n return {\n name: 'nasti:electron',\n enforce: 'pre',\n\n resolveId(source) {\n // 显式外部化 electron 与 Node 内建模块\n if (external.has(source)) {\n return { id: source, external: true }\n }\n // 形如 `electron/xxx` 的子路径一律标记外部\n if (source.startsWith('electron/')) {\n return { id: source, external: true }\n }\n return null\n },\n }\n}\n","// Electron 构建入口\n//\n// 流水线:\n// 1. 渲染进程(Web)构建 —— 复用现有 build() 流水线,输出到 outDir/renderer\n// 2. 主进程构建 —— 独立 Rolldown,target=node22,external=electron+内建模块\n// 3. Preload 构建 —— 独立 Rolldown,默认 cjs,contextIsolation 友好\n//\n// 产物目录结构(默认):\n// dist/\n// ├── renderer/ Web 渲染层,与 nasti build 一致\n// ├── main.{cjs,mjs}\n// └── preload.{cjs,mjs}\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { rolldown } from 'rolldown'\nimport pc from 'picocolors'\nimport type { NastiConfig, ResolvedConfig } from '../types.js'\nimport { resolveConfig } from '../config/index.js'\nimport { resolvePlugin } from '../plugins/resolve.js'\nimport { electronPlugin } from '../plugins/electron.js'\nimport { transformCode, transformReactCode, shouldTransform } from '../core/transformer.js'\nimport { loadEnv, buildEnvDefine } from '../core/env.js'\nimport { resolveMinifyOption } from '../core/minify.js'\n\nexport interface ElectronBuildResult {\n rendererOutDir: string\n mainFile: string\n preloadFiles: string[]\n}\n\n/**\n * Performs a full Electron build pipeline producing renderer, main, and preload artifacts.\n *\n * Resolves an Electron-targeted config, validates the installed Electron version, prepares the output directory, builds the renderer (via the web build), bundles the main process, bundles configured preload scripts, and logs a summary.\n *\n * @param inlineConfig - Optional config overrides merged into the resolved build configuration\n * @returns An object with `rendererOutDir` (renderer output directory), `mainFile` (bundled main process file path), and `preloadFiles` (array of bundled preload file paths)\n * @throws Error if the configured Electron main entry file does not exist\n */\nexport async function buildElectron(inlineConfig: NastiConfig = {}): Promise<ElectronBuildResult> {\n const config = await resolveConfig({ ...inlineConfig, target: 'electron' }, 'build')\n const startTime = performance.now()\n\n assertElectronVersion(config)\n\n console.log(pc.cyan('\\n⚡ nasti build (electron)') + pc.dim(` v${__NASTI_VERSION__}`))\n console.log(pc.dim(` root: ${config.root}`))\n console.log(pc.dim(` mode: ${config.mode}`))\n console.log(pc.dim(` target: electron (≥ ${config.electron.minVersion})`))\n\n const outDir = path.resolve(config.root, config.build.outDir)\n if (config.build.emptyOutDir && fs.existsSync(outDir)) {\n fs.rmSync(outDir, { recursive: true, force: true })\n }\n fs.mkdirSync(outDir, { recursive: true })\n\n // ---- 1. 渲染进程(复用 Web 构建)----\n const rendererOutDir = path.join(outDir, 'renderer')\n const { build } = await import('./index.js')\n await build(createElectronRendererConfig(config, inlineConfig, {\n build: {\n ...inlineConfig.build,\n outDir: rendererOutDir,\n emptyOutDir: false,\n },\n }))\n\n // ---- 2. 主进程 ----\n const mainEntry = path.resolve(config.root, config.electron.main)\n if (!fs.existsSync(mainEntry)) {\n throw new Error(\n `Electron main entry not found: ${config.electron.main}\\n` +\n `在 nasti.config.ts 的 electron.main 指定主进程入口文件。`,\n )\n }\n const mainFile = await bundleNode(config, mainEntry, {\n outFile: outFileName(outDir, 'main', config.electron.mainFormat),\n format: config.electron.mainFormat,\n label: 'main',\n })\n\n // ---- 3. Preload ----\n const preloadEntries = normalizePreload(config.electron.preload, config.root)\n const preloadFiles: string[] = []\n for (const entry of preloadEntries) {\n if (!fs.existsSync(entry)) {\n console.warn(pc.yellow(` ⚠ preload entry not found, skipped: ${entry}`))\n continue\n }\n const base = path.basename(entry).replace(/\\.[^.]+$/, '')\n const out = outFileName(outDir, base, config.electron.preloadFormat)\n await bundleNode(config, entry, {\n outFile: out,\n format: config.electron.preloadFormat,\n label: `preload (${base})`,\n })\n preloadFiles.push(out)\n }\n\n const elapsed = ((performance.now() - startTime) / 1000).toFixed(2)\n console.log(pc.green(`\\n✓ Electron build complete in ${elapsed}s`))\n console.log(pc.dim(` renderer: ${path.relative(config.root, rendererOutDir)}/`))\n console.log(pc.dim(` main: ${path.relative(config.root, mainFile)}`))\n for (const pf of preloadFiles) {\n console.log(pc.dim(` preload: ${path.relative(config.root, pf)}`))\n }\n console.log()\n\n return { rendererOutDir, mainFile, preloadFiles }\n}\n\ninterface BundleNodeOptions {\n outFile: string\n format: 'cjs' | 'esm'\n label: string\n}\n\n/**\n * Bundles a Node-targeted entry for Electron into a single output file using Rolldown and the OXC transform.\n *\n * @param config - Fully resolved build configuration used to drive transforms, defines, plugins, and output options\n * @param entry - Absolute path to the entry file to bundle\n * @param opts - Bundle options; expects `outFile` (destination path), `format` (`'cjs'` or `'esm'`), and `label` (human-readable name for logging)\n * @returns The path to the written bundle file (`opts.outFile`)\n */\nasync function bundleNode(\n config: ResolvedConfig,\n entry: string,\n opts: BundleNodeOptions,\n): Promise<string> {\n const env = loadEnv(config.mode, config.root, config.envPrefix)\n const envDefine = {\n ...buildEnvDefine(env, config.mode),\n __ELECTRON__: 'true',\n __NASTI_TARGET__: JSON.stringify('electron'),\n }\n\n const oxcTransformPlugin = {\n name: 'nasti:oxc-transform',\n async transform(code: string, id: string) {\n const result = config.framework === 'react'\n ? await transformReactCode(id, code, {\n react: config.react,\n consumer: 'server',\n development: config.mode === 'development',\n sourcemap: !!config.build.sourcemap,\n target: config.electron.nodeTarget,\n onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`),\n })\n : shouldTransform(id)\n ? transformCode(id, code, {\n sourcemap: !!config.build.sourcemap,\n jsxRuntime: 'automatic',\n jsxImportSource: 'vue',\n target: config.electron.nodeTarget,\n })\n : null\n if (!result) return null\n return { code: result.code, map: result.map ? JSON.parse(result.map) : undefined }\n },\n }\n\n // 从 build.rolldownOptions 拆出 output(合并进 bundle.write())与 transform\n // (需与 envDefine 合并),其余 input 选项(treeshake 等)随 restInputOptions 透传。\n // Nasti 自管的 input / platform / transform / plugins 放在 spread 之后确保覆盖。\n const { output: userOutput, transform: userTransform, ...restInputOptions } =\n config.build.rolldownOptions\n // 合并用户的 transform.define 和 envDefine,确保 envDefine 优先级更高\n const mergedDefine = { ...(userTransform?.define ?? {}), ...envDefine }\n const bundle = await rolldown({\n ...restInputOptions,\n input: entry,\n platform: 'node',\n transform: {\n ...userTransform,\n target: config.electron.nodeTarget,\n define: mergedDefine,\n },\n plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)] as any,\n })\n\n fs.mkdirSync(path.dirname(opts.outFile), { recursive: true })\n\n await bundle.write({\n sourcemap: !!config.build.sourcemap,\n minify: resolveMinifyOption(config.build.minify),\n // 允许用户微调 output;但主进程 / preload 的单文件约束由下方键强制保证\n ...userOutput,\n file: opts.outFile,\n format: opts.format === 'cjs' ? 'cjs' : 'esm',\n codeSplitting: false,\n })\n\n await bundle.close()\n\n console.log(pc.dim(` ✓ ${opts.label} → ${path.relative(config.root, opts.outFile)}`))\n return opts.outFile\n}\n\n/**\n * 从 Electron 配置派生 renderer 的普通 Web 构建配置。\n *\n * renderer 使用指定 HTML 入口;本地文件加载场景默认把 `/` base 收敛为\n * `./`,避免产物中的 `/assets/*` 被解析到文件系统根目录。\n */\nexport function createElectronRendererConfig(\n config: ResolvedConfig,\n inlineConfig: NastiConfig = {},\n overrides: Pick<NastiConfig, 'build'> = {},\n): NastiConfig {\n const inlineClient = inlineConfig.environments?.client ?? {}\n return {\n ...inlineConfig,\n ...overrides,\n root: config.root,\n mode: config.mode,\n target: 'web',\n framework: config.framework,\n base: config.base === '/' ? './' : config.base,\n environments: {\n ...(inlineConfig.environments ?? {}),\n client: {\n ...inlineClient,\n html: config.electron.renderer,\n },\n },\n }\n}\n\n/**\n * Compute an output file path for a given base name and module format.\n *\n * @param outDir - Directory where the output file will be placed\n * @param base - Base filename without extension\n * @param format - Module format; `cjs` yields a `.cjs` extension, `esm` yields a `.mjs` extension\n * @returns The resolved file path combining `outDir` and `base` with the appropriate extension\n */\nfunction outFileName(outDir: string, base: string, format: 'cjs' | 'esm'): string {\n const ext = format === 'cjs' ? '.cjs' : '.mjs'\n return path.join(outDir, base + ext)\n}\n\n/**\n * Normalize Electron preload entries into absolute file paths.\n *\n * @param preload - A single preload path or an array of preload paths; a falsy value produces an empty list\n * @param root - Root directory used to resolve relative preload entries\n * @returns An array of absolute file paths for each preload entry\n */\nexport function normalizePreload(preload: string | string[] | undefined, root: string): string[] {\n const list = Array.isArray(preload) ? preload : preload ? [preload] : []\n return list.map((p) => path.resolve(root, p))\n}\n\n/**\n * Warns when the detected Electron major version is lower than the configured minimum.\n *\n * Checks the project for an installed Electron package and, if its major version\n * is less than `config.electron.minVersion`, logs a yellow warning describing the mismatch.\n *\n * @param config - Resolved build configuration that contains `electron.minVersion` and project `root`\n */\nfunction assertElectronVersion(config: ResolvedConfig): void {\n const min = config.electron.minVersion\n const installed = detectInstalledElectron(config.root)\n if (installed && installed < min) {\n console.warn(\n pc.yellow(\n ` ⚠ 检测到 Electron ${installed},Nasti 要求 ≥ ${min}。旧版本可能缺少 ESM 主进程支持。`,\n ),\n )\n }\n}\n\n/**\n * Detects the installed Electron major version in the given project root.\n *\n * @param root - Project root directory used to locate electron via Node resolution\n * @returns The major Electron version as a number, or `null` if Electron is not installed or the version cannot be determined\n */\nexport function detectInstalledElectron(root: string): number | null {\n try {\n // Node resolution handles pnpm/yarn symlink layouts; plain path join is a\n // fallback for installers that still flatten electron under node_modules.\n const require = createRequire(path.resolve(root, 'package.json'))\n const pkgPath = require.resolve('electron/package.json')\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n const major = parseInt(String(pkg.version).split('.')[0], 10)\n return Number.isFinite(major) ? major : null\n } catch {\n try {\n const pkgPath = path.resolve(root, 'node_modules/electron/package.json')\n if (!fs.existsSync(pkgPath)) return null\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n const major = parseInt(String(pkg.version).split('.')[0], 10)\n return Number.isFinite(major) ? major : null\n } catch {\n return null\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,316 @@
1
+ const require_logger = require("./logger-M7AuVVTV.cjs");
2
+ const require_env = require("./env-lOj3yw8v.cjs");
3
+ let node_path = require("node:path");
4
+ node_path = require_logger.__toESM(node_path, 1);
5
+ let node_fs = require("node:fs");
6
+ node_fs = require_logger.__toESM(node_fs, 1);
7
+ let picocolors = require("picocolors");
8
+ picocolors = require_logger.__toESM(picocolors, 1);
9
+ let node_module = require("node:module");
10
+ let rolldown = require("rolldown");
11
+ //#region src/plugins/electron.ts
12
+ const NODE_BUILTINS = /* @__PURE__ */ new Set([...node_module.builtinModules, ...node_module.builtinModules.map((m) => `node:${m}`)]);
13
+ const ELECTRON_MODULES = /* @__PURE__ */ new Set([
14
+ "electron",
15
+ "electron/main",
16
+ "electron/common",
17
+ "electron/renderer"
18
+ ]);
19
+ /**
20
+ * Create a Vite/Rollup plugin that externalizes Electron and Node built-in imports according to the resolved config.
21
+ *
22
+ * @param config - Resolved build config; any entries in `config.electron.external` are added to the externalized modules set.
23
+ * @returns A plugin that marks `electron` and `electron/*` imports and Node built-in modules (including `node:`-prefixed names) as external.
24
+ */
25
+ function electronPlugin(config) {
26
+ const external = /* @__PURE__ */ new Set([
27
+ ...ELECTRON_MODULES,
28
+ ...NODE_BUILTINS,
29
+ ...config.electron.external ?? []
30
+ ]);
31
+ return {
32
+ name: "nasti:electron",
33
+ enforce: "pre",
34
+ resolveId(source) {
35
+ if (external.has(source)) return {
36
+ id: source,
37
+ external: true
38
+ };
39
+ if (source.startsWith("electron/")) return {
40
+ id: source,
41
+ external: true
42
+ };
43
+ return null;
44
+ }
45
+ };
46
+ }
47
+ //#endregion
48
+ //#region src/build/electron.ts
49
+ var electron_exports = /* @__PURE__ */ require_logger.__exportAll({
50
+ buildElectron: () => buildElectron,
51
+ createElectronRendererConfig: () => createElectronRendererConfig,
52
+ detectInstalledElectron: () => detectInstalledElectron,
53
+ normalizePreload: () => normalizePreload
54
+ });
55
+ /**
56
+ * Performs a full Electron build pipeline producing renderer, main, and preload artifacts.
57
+ *
58
+ * Resolves an Electron-targeted config, validates the installed Electron version, prepares the output directory, builds the renderer (via the web build), bundles the main process, bundles configured preload scripts, and logs a summary.
59
+ *
60
+ * @param inlineConfig - Optional config overrides merged into the resolved build configuration
61
+ * @returns An object with `rendererOutDir` (renderer output directory), `mainFile` (bundled main process file path), and `preloadFiles` (array of bundled preload file paths)
62
+ * @throws Error if the configured Electron main entry file does not exist
63
+ */
64
+ async function buildElectron(inlineConfig = {}) {
65
+ const config = await require_env.resolveConfig({
66
+ ...inlineConfig,
67
+ target: "electron"
68
+ }, "build");
69
+ const startTime = performance.now();
70
+ assertElectronVersion(config);
71
+ console.log(picocolors.default.cyan("\n⚡ nasti build (electron)") + picocolors.default.dim(` v2.5.2`));
72
+ console.log(picocolors.default.dim(` root: ${config.root}`));
73
+ console.log(picocolors.default.dim(` mode: ${config.mode}`));
74
+ console.log(picocolors.default.dim(` target: electron (≥ ${config.electron.minVersion})`));
75
+ const outDir = node_path.default.resolve(config.root, config.build.outDir);
76
+ if (config.build.emptyOutDir && node_fs.default.existsSync(outDir)) node_fs.default.rmSync(outDir, {
77
+ recursive: true,
78
+ force: true
79
+ });
80
+ node_fs.default.mkdirSync(outDir, { recursive: true });
81
+ const rendererOutDir = node_path.default.join(outDir, "renderer");
82
+ const { build } = await Promise.resolve().then(() => require("./build-vjh6h7PB.cjs")).then((n) => n.build_exports);
83
+ await build(createElectronRendererConfig(config, inlineConfig, { build: {
84
+ ...inlineConfig.build,
85
+ outDir: rendererOutDir,
86
+ emptyOutDir: false
87
+ } }));
88
+ const mainEntry = node_path.default.resolve(config.root, config.electron.main);
89
+ if (!node_fs.default.existsSync(mainEntry)) throw new Error(`Electron main entry not found: ${config.electron.main}\n在 nasti.config.ts 的 electron.main 指定主进程入口文件。`);
90
+ const mainFile = await bundleNode(config, mainEntry, {
91
+ outFile: outFileName(outDir, "main", config.electron.mainFormat),
92
+ format: config.electron.mainFormat,
93
+ label: "main"
94
+ });
95
+ const preloadEntries = normalizePreload(config.electron.preload, config.root);
96
+ const preloadFiles = [];
97
+ for (const entry of preloadEntries) {
98
+ if (!node_fs.default.existsSync(entry)) {
99
+ console.warn(picocolors.default.yellow(` ⚠ preload entry not found, skipped: ${entry}`));
100
+ continue;
101
+ }
102
+ const base = node_path.default.basename(entry).replace(/\.[^.]+$/, "");
103
+ const out = outFileName(outDir, base, config.electron.preloadFormat);
104
+ await bundleNode(config, entry, {
105
+ outFile: out,
106
+ format: config.electron.preloadFormat,
107
+ label: `preload (${base})`
108
+ });
109
+ preloadFiles.push(out);
110
+ }
111
+ const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
112
+ console.log(picocolors.default.green(`\n✓ Electron build complete in ${elapsed}s`));
113
+ console.log(picocolors.default.dim(` renderer: ${node_path.default.relative(config.root, rendererOutDir)}/`));
114
+ console.log(picocolors.default.dim(` main: ${node_path.default.relative(config.root, mainFile)}`));
115
+ for (const pf of preloadFiles) console.log(picocolors.default.dim(` preload: ${node_path.default.relative(config.root, pf)}`));
116
+ console.log();
117
+ return {
118
+ rendererOutDir,
119
+ mainFile,
120
+ preloadFiles
121
+ };
122
+ }
123
+ /**
124
+ * Bundles a Node-targeted entry for Electron into a single output file using Rolldown and the OXC transform.
125
+ *
126
+ * @param config - Fully resolved build configuration used to drive transforms, defines, plugins, and output options
127
+ * @param entry - Absolute path to the entry file to bundle
128
+ * @param opts - Bundle options; expects `outFile` (destination path), `format` (`'cjs'` or `'esm'`), and `label` (human-readable name for logging)
129
+ * @returns The path to the written bundle file (`opts.outFile`)
130
+ */
131
+ async function bundleNode(config, entry, opts) {
132
+ const env = require_env.loadEnv(config.mode, config.root, config.envPrefix);
133
+ const envDefine = {
134
+ ...require_env.buildEnvDefine(env, config.mode),
135
+ __ELECTRON__: "true",
136
+ __NASTI_TARGET__: JSON.stringify("electron")
137
+ };
138
+ const oxcTransformPlugin = {
139
+ name: "nasti:oxc-transform",
140
+ async transform(code, id) {
141
+ const result = config.framework === "react" ? await require_env.transformReactCode(id, code, {
142
+ react: config.react,
143
+ consumer: "server",
144
+ development: config.mode === "development",
145
+ sourcemap: !!config.build.sourcemap,
146
+ target: config.electron.nodeTarget,
147
+ onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
148
+ }) : require_env.shouldTransform(id) ? require_env.transformCode(id, code, {
149
+ sourcemap: !!config.build.sourcemap,
150
+ jsxRuntime: "automatic",
151
+ jsxImportSource: "vue",
152
+ target: config.electron.nodeTarget
153
+ }) : null;
154
+ if (!result) return null;
155
+ return {
156
+ code: result.code,
157
+ map: result.map ? JSON.parse(result.map) : void 0
158
+ };
159
+ }
160
+ };
161
+ const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
162
+ const mergedDefine = {
163
+ ...userTransform?.define ?? {},
164
+ ...envDefine
165
+ };
166
+ const bundle = await (0, rolldown.rolldown)({
167
+ ...restInputOptions,
168
+ input: entry,
169
+ platform: "node",
170
+ transform: {
171
+ ...userTransform,
172
+ target: config.electron.nodeTarget,
173
+ define: mergedDefine
174
+ },
175
+ plugins: [
176
+ oxcTransformPlugin,
177
+ electronPlugin(config),
178
+ require_env.resolvePlugin(config)
179
+ ]
180
+ });
181
+ node_fs.default.mkdirSync(node_path.default.dirname(opts.outFile), { recursive: true });
182
+ await bundle.write({
183
+ sourcemap: !!config.build.sourcemap,
184
+ minify: require_env.resolveMinifyOption(config.build.minify),
185
+ ...userOutput,
186
+ file: opts.outFile,
187
+ format: opts.format === "cjs" ? "cjs" : "esm",
188
+ codeSplitting: false
189
+ });
190
+ await bundle.close();
191
+ console.log(picocolors.default.dim(` ✓ ${opts.label} → ${node_path.default.relative(config.root, opts.outFile)}`));
192
+ return opts.outFile;
193
+ }
194
+ /**
195
+ * 从 Electron 配置派生 renderer 的普通 Web 构建配置。
196
+ *
197
+ * renderer 使用指定 HTML 入口;本地文件加载场景默认把 `/` base 收敛为
198
+ * `./`,避免产物中的 `/assets/*` 被解析到文件系统根目录。
199
+ */
200
+ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
201
+ const inlineClient = inlineConfig.environments?.client ?? {};
202
+ return {
203
+ ...inlineConfig,
204
+ ...overrides,
205
+ root: config.root,
206
+ mode: config.mode,
207
+ target: "web",
208
+ framework: config.framework,
209
+ base: config.base === "/" ? "./" : config.base,
210
+ environments: {
211
+ ...inlineConfig.environments ?? {},
212
+ client: {
213
+ ...inlineClient,
214
+ html: config.electron.renderer
215
+ }
216
+ }
217
+ };
218
+ }
219
+ /**
220
+ * Compute an output file path for a given base name and module format.
221
+ *
222
+ * @param outDir - Directory where the output file will be placed
223
+ * @param base - Base filename without extension
224
+ * @param format - Module format; `cjs` yields a `.cjs` extension, `esm` yields a `.mjs` extension
225
+ * @returns The resolved file path combining `outDir` and `base` with the appropriate extension
226
+ */
227
+ function outFileName(outDir, base, format) {
228
+ const ext = format === "cjs" ? ".cjs" : ".mjs";
229
+ return node_path.default.join(outDir, base + ext);
230
+ }
231
+ /**
232
+ * Normalize Electron preload entries into absolute file paths.
233
+ *
234
+ * @param preload - A single preload path or an array of preload paths; a falsy value produces an empty list
235
+ * @param root - Root directory used to resolve relative preload entries
236
+ * @returns An array of absolute file paths for each preload entry
237
+ */
238
+ function normalizePreload(preload, root) {
239
+ return (Array.isArray(preload) ? preload : preload ? [preload] : []).map((p) => node_path.default.resolve(root, p));
240
+ }
241
+ /**
242
+ * Warns when the detected Electron major version is lower than the configured minimum.
243
+ *
244
+ * Checks the project for an installed Electron package and, if its major version
245
+ * is less than `config.electron.minVersion`, logs a yellow warning describing the mismatch.
246
+ *
247
+ * @param config - Resolved build configuration that contains `electron.minVersion` and project `root`
248
+ */
249
+ function assertElectronVersion(config) {
250
+ const min = config.electron.minVersion;
251
+ const installed = detectInstalledElectron(config.root);
252
+ if (installed && installed < min) console.warn(picocolors.default.yellow(` ⚠ 检测到 Electron ${installed},Nasti 要求 ≥ ${min}。旧版本可能缺少 ESM 主进程支持。`));
253
+ }
254
+ /**
255
+ * Detects the installed Electron major version in the given project root.
256
+ *
257
+ * @param root - Project root directory used to locate electron via Node resolution
258
+ * @returns The major Electron version as a number, or `null` if Electron is not installed or the version cannot be determined
259
+ */
260
+ function detectInstalledElectron(root) {
261
+ try {
262
+ const pkgPath = (0, node_module.createRequire)(node_path.default.resolve(root, "package.json")).resolve("electron/package.json");
263
+ const pkg = JSON.parse(node_fs.default.readFileSync(pkgPath, "utf-8"));
264
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
265
+ return Number.isFinite(major) ? major : null;
266
+ } catch {
267
+ try {
268
+ const pkgPath = node_path.default.resolve(root, "node_modules/electron/package.json");
269
+ if (!node_fs.default.existsSync(pkgPath)) return null;
270
+ const pkg = JSON.parse(node_fs.default.readFileSync(pkgPath, "utf-8"));
271
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
272
+ return Number.isFinite(major) ? major : null;
273
+ } catch {
274
+ return null;
275
+ }
276
+ }
277
+ }
278
+ //#endregion
279
+ Object.defineProperty(exports, "buildElectron", {
280
+ enumerable: true,
281
+ get: function() {
282
+ return buildElectron;
283
+ }
284
+ });
285
+ Object.defineProperty(exports, "createElectronRendererConfig", {
286
+ enumerable: true,
287
+ get: function() {
288
+ return createElectronRendererConfig;
289
+ }
290
+ });
291
+ Object.defineProperty(exports, "detectInstalledElectron", {
292
+ enumerable: true,
293
+ get: function() {
294
+ return detectInstalledElectron;
295
+ }
296
+ });
297
+ Object.defineProperty(exports, "electronPlugin", {
298
+ enumerable: true,
299
+ get: function() {
300
+ return electronPlugin;
301
+ }
302
+ });
303
+ Object.defineProperty(exports, "electron_exports", {
304
+ enumerable: true,
305
+ get: function() {
306
+ return electron_exports;
307
+ }
308
+ });
309
+ Object.defineProperty(exports, "normalizePreload", {
310
+ enumerable: true,
311
+ get: function() {
312
+ return normalizePreload;
313
+ }
314
+ });
315
+
316
+ //# sourceMappingURL=electron-D0PSXz-a.cjs.map