@holix/cli 0.1.0 → 0.2.0

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.
@@ -1,4 +1,4 @@
1
- const require_config = require('../config-BrQgiHmo.cjs');
1
+ const require_config = require('../config-DiolnOet.cjs');
2
2
 
3
3
  exports.defineHolixConfig = require_config.defineHolixConfig;
4
4
  exports.loadHolixConfig = require_config.loadHolixConfig;
@@ -1,25 +1,6 @@
1
- import { z } from "zod";
1
+ import { HolixConfig } from "@holix/config";
2
2
  import * as pkg_types0 from "pkg-types";
3
3
 
4
- //#region ../config/dist/index.d.mts
5
-
6
- /**
7
- * Holix 配置 Schema
8
- * 使用 Zod 定义的类型安全配置结构
9
- */
10
- declare const holixConfigSchema: any;
11
- /**
12
- * 导出配置 Schema
13
- */
14
-
15
- /**
16
- * Holix 配置类型(从 Schema 推断)
17
- */
18
- type HolixConfig = z.infer<typeof holixConfigSchema>;
19
- /**
20
- * 应用配置类型
21
- */
22
- //#endregion
23
4
  //#region src/config/loader.d.ts
24
5
  interface LoadHolixOptions {
25
6
  cwd?: string;
@@ -27,7 +8,7 @@ interface LoadHolixOptions {
27
8
  declare function loadHolixConfig({
28
9
  cwd
29
10
  }?: LoadHolixOptions): Promise<{
30
- config: any;
11
+ config: HolixConfig;
31
12
  configFile: string | undefined;
32
13
  packageJson: pkg_types0.PackageJson;
33
14
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":["z","appConfigSchema","directoriesConfigSchema","preloadConfigSchema","holixConfigSchema","holixConfig","HolixConfig","infer","AppConfig","DirectoriesConfig","PreloadConfig","defaultHolixConfig","Required","validateConfig","SafeParseReturnType","parseConfig","mergeConfig","Partial"],"sources":["../../../config/dist/index.d.mts","../../src/config/loader.ts","../../src/config/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n//#region src/schema.d.ts\n\n/**\n * 应用配置 Schema\n * 单入口模式配置\n */\ndeclare const appConfigSchema: any;\n/**\n * 目录配置 Schema\n * 多页面/目录模式配置\n */\ndeclare const directoriesConfigSchema: any;\n/**\n * 预加载脚本配置 Schema\n * 支持多种格式:\n * - string: 单个预加载脚本路径\n * - string[]: 多个预加载脚本路径\n * - Record<string, string>: 命名的预加载脚本映射\n */\ndeclare const preloadConfigSchema: any;\n/**\n * Holix 配置 Schema\n * 使用 Zod 定义的类型安全配置结构\n */\ndeclare const holixConfigSchema: any;\n/**\n * 导出配置 Schema\n */\ndeclare const holixConfig: any;\n/**\n * Holix 配置类型(从 Schema 推断)\n */\ntype HolixConfig = z.infer<typeof holixConfigSchema>;\n/**\n * 应用配置类型\n */\ntype AppConfig = z.infer<typeof appConfigSchema>;\n/**\n * 目录配置类型\n */\ntype DirectoriesConfig = z.infer<typeof directoriesConfigSchema>;\n/**\n * 预加载配置类型\n */\ntype PreloadConfig = z.infer<typeof preloadConfigSchema>;\n/**\n * 默认配置\n */\ndeclare const defaultHolixConfig: Required<HolixConfig>;\n/**\n * 验证配置对象\n *\n * @param config - 待验证的配置对象\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const result = validateConfig({\n * app: { id: 'my-app', entry: 'src/index.ts' },\n * outDir: 'dist'\n * })\n *\n * if (result.success) {\n * console.log('Valid config:', result.data)\n * } else {\n * console.error('Invalid config:', result.error.issues)\n * }\n * ```\n */\ndeclare function validateConfig(config: unknown): z.SafeParseReturnType<unknown, HolixConfig>;\n/**\n * 解析配置对象(抛出异常)\n *\n * @param config - 待解析的配置对象\n * @returns 解析后的类型安全配置\n * @throws {ZodError} 如果配置无效\n *\n * @example\n * ```ts\n * try {\n * const config = parseConfig({\n * app: { id: 'my-app', entry: 'src/index.ts' }\n * })\n * console.log('Parsed config:', config)\n * } catch (error) {\n * console.error('Config validation failed:', error)\n * }\n * ```\n */\ndeclare function parseConfig(config: unknown): HolixConfig;\n/**\n * 合并用户配置和默认配置\n *\n * @param userConfig - 用户提供的配置\n * @returns 合并后的完整配置\n *\n * @example\n * ```ts\n * const config = mergeConfig({\n * app: { id: 'my-app', entry: 'src/main.ts' }\n * })\n * // 返回: { app: { id: 'my-app', entry: 'src/main.ts' }, outDir: 'dist', ... }\n * ```\n */\ndeclare function mergeConfig(userConfig: Partial<HolixConfig>): HolixConfig;\n//#endregion\nexport { type AppConfig, type DirectoriesConfig, type HolixConfig, type PreloadConfig, appConfigSchema, defaultHolixConfig, directoriesConfigSchema, holixConfig, holixConfigSchema, mergeConfig, parseConfig, preloadConfigSchema, validateConfig };"],"mappings":";;;;;;;;;cA0BcI;;;;;;;;KAQTE,WAAAA,GAAcN,CAAAA,CAAEO,aAAaH;;;;;;UCXjB,gBAAA;;;iBAIK,eAAA;;IAEnB,mBAEF;EDLaA,MAAAA,EAAAA,GAAAA;EAQTE,UAAAA,EAAAA,MAAW,GAAA,SAAkBF;eCHjC,UAAA,CAAA;;;;;;ADVqC;AASR;;;;ACP9B;AAIA;;;;;;;iBCRgB,iBAAA,SAA0B,cAAc"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/config/loader.ts","../../src/config/index.ts"],"sourcesContent":[],"mappings":";;;;UAsBiB,gBAAA;;;AAAA,iBAIK,eAAA,CAJW;EAAA;AAAA,CAAA,CAAA,EAM9B,gBAN8B,CAAA,EAQhC,OARgC,CAAA;EAIX,MAAA,EA0Ce,WA1CA;EACnC,UAAA,EAAA,MAAA,GAAA,SAAA;EACC,WAAA,EAwC6C,UAAA,CAAA,WAxC7C;CAwCkC,CAAA;;;;;AA9CrC;AAIA;;;;;;;;;;ACPA;;iBAAgB,iBAAA,SAA0B,cAAc"}
@@ -1,25 +1,6 @@
1
+ import { HolixConfig } from "@holix/config";
1
2
  import * as pkg_types0 from "pkg-types";
2
- import { z } from "zod";
3
3
 
4
- //#region ../config/dist/index.d.mts
5
-
6
- /**
7
- * Holix 配置 Schema
8
- * 使用 Zod 定义的类型安全配置结构
9
- */
10
- declare const holixConfigSchema: any;
11
- /**
12
- * 导出配置 Schema
13
- */
14
-
15
- /**
16
- * Holix 配置类型(从 Schema 推断)
17
- */
18
- type HolixConfig = z.infer<typeof holixConfigSchema>;
19
- /**
20
- * 应用配置类型
21
- */
22
- //#endregion
23
4
  //#region src/config/loader.d.ts
24
5
  interface LoadHolixOptions {
25
6
  cwd?: string;
@@ -27,7 +8,7 @@ interface LoadHolixOptions {
27
8
  declare function loadHolixConfig({
28
9
  cwd
29
10
  }?: LoadHolixOptions): Promise<{
30
- config: any;
11
+ config: HolixConfig;
31
12
  configFile: string | undefined;
32
13
  packageJson: pkg_types0.PackageJson;
33
14
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":["z","appConfigSchema","directoriesConfigSchema","preloadConfigSchema","holixConfigSchema","holixConfig","HolixConfig","infer","AppConfig","DirectoriesConfig","PreloadConfig","defaultHolixConfig","Required","validateConfig","SafeParseReturnType","parseConfig","mergeConfig","Partial"],"sources":["../../../config/dist/index.d.mts","../../src/config/loader.ts","../../src/config/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n//#region src/schema.d.ts\n\n/**\n * 应用配置 Schema\n * 单入口模式配置\n */\ndeclare const appConfigSchema: any;\n/**\n * 目录配置 Schema\n * 多页面/目录模式配置\n */\ndeclare const directoriesConfigSchema: any;\n/**\n * 预加载脚本配置 Schema\n * 支持多种格式:\n * - string: 单个预加载脚本路径\n * - string[]: 多个预加载脚本路径\n * - Record<string, string>: 命名的预加载脚本映射\n */\ndeclare const preloadConfigSchema: any;\n/**\n * Holix 配置 Schema\n * 使用 Zod 定义的类型安全配置结构\n */\ndeclare const holixConfigSchema: any;\n/**\n * 导出配置 Schema\n */\ndeclare const holixConfig: any;\n/**\n * Holix 配置类型(从 Schema 推断)\n */\ntype HolixConfig = z.infer<typeof holixConfigSchema>;\n/**\n * 应用配置类型\n */\ntype AppConfig = z.infer<typeof appConfigSchema>;\n/**\n * 目录配置类型\n */\ntype DirectoriesConfig = z.infer<typeof directoriesConfigSchema>;\n/**\n * 预加载配置类型\n */\ntype PreloadConfig = z.infer<typeof preloadConfigSchema>;\n/**\n * 默认配置\n */\ndeclare const defaultHolixConfig: Required<HolixConfig>;\n/**\n * 验证配置对象\n *\n * @param config - 待验证的配置对象\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const result = validateConfig({\n * app: { id: 'my-app', entry: 'src/index.ts' },\n * outDir: 'dist'\n * })\n *\n * if (result.success) {\n * console.log('Valid config:', result.data)\n * } else {\n * console.error('Invalid config:', result.error.issues)\n * }\n * ```\n */\ndeclare function validateConfig(config: unknown): z.SafeParseReturnType<unknown, HolixConfig>;\n/**\n * 解析配置对象(抛出异常)\n *\n * @param config - 待解析的配置对象\n * @returns 解析后的类型安全配置\n * @throws {ZodError} 如果配置无效\n *\n * @example\n * ```ts\n * try {\n * const config = parseConfig({\n * app: { id: 'my-app', entry: 'src/index.ts' }\n * })\n * console.log('Parsed config:', config)\n * } catch (error) {\n * console.error('Config validation failed:', error)\n * }\n * ```\n */\ndeclare function parseConfig(config: unknown): HolixConfig;\n/**\n * 合并用户配置和默认配置\n *\n * @param userConfig - 用户提供的配置\n * @returns 合并后的完整配置\n *\n * @example\n * ```ts\n * const config = mergeConfig({\n * app: { id: 'my-app', entry: 'src/main.ts' }\n * })\n * // 返回: { app: { id: 'my-app', entry: 'src/main.ts' }, outDir: 'dist', ... }\n * ```\n */\ndeclare function mergeConfig(userConfig: Partial<HolixConfig>): HolixConfig;\n//#endregion\nexport { type AppConfig, type DirectoriesConfig, type HolixConfig, type PreloadConfig, appConfigSchema, defaultHolixConfig, directoriesConfigSchema, holixConfig, holixConfigSchema, mergeConfig, parseConfig, preloadConfigSchema, validateConfig };"],"mappings":";;;;;;;;;cA0BcI;;;;;;;;KAQTE,WAAAA,GAAcN,CAAAA,CAAEO,aAAaH;;;;;;UCXjB,gBAAA;;;iBAIK,eAAA;;IAEnB,mBAEF;EDLaA,MAAAA,EAAAA,GAAAA;EAQTE,UAAAA,EAAAA,MAAW,GAAA,SAAkBF;eCHjC,UAAA,CAAA;;;;;;ADVqC;AASR;;;;ACP9B;AAIA;;;;;;;iBCRgB,iBAAA,SAA0B,cAAc"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/config/loader.ts","../../src/config/index.ts"],"sourcesContent":[],"mappings":";;;;UAsBiB,gBAAA;;;AAAA,iBAIK,eAAA,CAJW;EAAA;AAAA,CAAA,CAAA,EAM9B,gBAN8B,CAAA,EAQhC,OARgC,CAAA;EAIX,MAAA,EA0Ce,WA1CA;EACnC,UAAA,EAAA,MAAA,GAAA,SAAA;EACC,WAAA,EAwC6C,UAAA,CAAA,WAxC7C;CAwCkC,CAAA;;;;;AA9CrC;AAIA;;;;;;;;;;ACPA;;iBAAgB,iBAAA,SAA0B,cAAc"}
@@ -1,3 +1,3 @@
1
- import { n as loadHolixConfig, t as defineHolixConfig } from "../config-DF41qZ52.mjs";
1
+ import { n as loadHolixConfig, t as defineHolixConfig } from "../config-BMXlLU4W.mjs";
2
2
 
3
3
  export { defineHolixConfig, loadHolixConfig };
@@ -21,11 +21,7 @@ async function loadHolixConfig({ cwd = process.cwd() } = { cwd: process.cwd() })
21
21
  const { config, configFile } = await loadConfig({
22
22
  name: "holix",
23
23
  cwd,
24
- defaultConfig: {
25
- outDir: defaultHolixConfig.outDir,
26
- preload: defaultHolixConfig.preload,
27
- plugins: defaultHolixConfig.plugins
28
- }
24
+ defaultConfig: defaultHolixConfig
29
25
  });
30
26
  if (config.app && !config.app.id && packageJson.name) config.app.id = normalizePackageName(packageJson.name);
31
27
  const validationResult = validateConfig({
@@ -33,8 +29,11 @@ async function loadHolixConfig({ cwd = process.cwd() } = { cwd: process.cwd() })
33
29
  directories: config.directories,
34
30
  outDir: config.outDir ?? defaultHolixConfig.outDir,
35
31
  preload: config.preload ?? defaultHolixConfig.preload,
36
- plugins: config.plugins ?? defaultHolixConfig.plugins,
37
- vite: config.vite ?? defaultHolixConfig.vite
32
+ publicDir: config.publicDir ?? defaultHolixConfig.publicDir,
33
+ alias: config.alias ?? defaultHolixConfig.alias,
34
+ port: config.port ?? defaultHolixConfig.port,
35
+ rolldownPlugins: config.rolldownPlugins ?? defaultHolixConfig.rolldownPlugins,
36
+ vitePlugins: config.vitePlugins ?? defaultHolixConfig.vitePlugins
38
37
  });
39
38
  if (!validationResult.success) {
40
39
  const errorMessages = validationResult.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
@@ -70,4 +69,4 @@ function defineHolixConfig(config) {
70
69
 
71
70
  //#endregion
72
71
  export { loadHolixConfig as n, defineHolixConfig as t };
73
- //# sourceMappingURL=config-DF41qZ52.mjs.map
72
+ //# sourceMappingURL=config-BMXlLU4W.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-BMXlLU4W.mjs","names":[],"sources":["../src/config/loader.ts","../src/config/index.ts"],"sourcesContent":["import type { HolixConfig } from '@holix/config'\r\nimport process from 'node:process'\r\nimport { defaultHolixConfig, validateConfig } from '@holix/config'\r\nimport { loadConfig } from 'c12'\r\nimport { readPackageJSON } from 'pkg-types'\r\n\r\n/**\r\n * 规范化包名为 appID 格式\r\n * 将 @scope/name 转换为 scope.name\r\n *\r\n * @example\r\n * normalizePackageName('@holix/core') // 'holix.core'\r\n * normalizePackageName('my-app') // 'my-app'\r\n */\r\nfunction normalizePackageName(name: string): string {\r\n if (name.startsWith('@')) {\r\n // 移除 @ 符号并将 / 替换为 .\r\n return name.slice(1).replace('/', '.')\r\n }\r\n return name\r\n}\r\n\r\nexport interface LoadHolixOptions {\r\n cwd?: string\r\n}\r\n\r\nexport async function loadHolixConfig({\r\n cwd = process.cwd(),\r\n}: LoadHolixOptions = {\r\n cwd: process.cwd(),\r\n}) {\r\n const packageJson = await readPackageJSON(cwd)\r\n\r\n const { config, configFile } = await loadConfig<HolixConfig>({\r\n name: 'holix',\r\n cwd,\r\n defaultConfig: defaultHolixConfig,\r\n })\r\n\r\n // 如果用户配置了 app,但没有设置 id,使用 package.json 的 name\r\n if (config.app && !config.app.id && packageJson.name) {\r\n config.app.id = normalizePackageName(packageJson.name)\r\n }\r\n\r\n // 使用 mergeConfig 合并默认值和用户配置\r\n // 只合并用户未设置的字段\r\n const mergedConfig: HolixConfig = {\r\n app: config.app,\r\n directories: config.directories,\r\n outDir: config.outDir ?? defaultHolixConfig.outDir,\r\n preload: config.preload ?? defaultHolixConfig.preload,\r\n publicDir: config.publicDir ?? defaultHolixConfig.publicDir,\r\n alias: config.alias ?? defaultHolixConfig.alias,\r\n port: config.port ?? defaultHolixConfig.port,\r\n rolldownPlugins: config.rolldownPlugins ?? defaultHolixConfig.rolldownPlugins,\r\n vitePlugins: config.vitePlugins ?? defaultHolixConfig.vitePlugins,\r\n }\r\n\r\n // 验证配置\r\n const validationResult = validateConfig(mergedConfig)\r\n if (!validationResult.success) {\r\n const errorMessages = validationResult.error.issues.map((issue: any) =>\r\n ` - ${issue.path.join('.')}: ${issue.message}`,\r\n ).join('\\n')\r\n throw new Error(`Invalid Holix configuration:\\n${errorMessages}`)\r\n }\r\n\r\n return {\r\n config: validationResult.data as HolixConfig,\r\n configFile,\r\n packageJson, // 返回 packageJson 供 builder 使用\r\n }\r\n}\r\n","import type { HolixConfig } from '@holix/config'\r\n\r\nexport * from './loader'\r\n\r\n/**\r\n * 类型辅助:用于 holix.config.ts\r\n * 提供类型提示和自动完成\r\n *\r\n * @example\r\n * ```ts\r\n * // holix.config.ts\r\n * import { defineHolixConfig } from '@holix/cli/config'\r\n *\r\n * export default defineHolixConfig({\r\n * entry: 'src/index.tsx',\r\n * outDir: 'dist'\r\n * })\r\n * ```\r\n */\r\nexport function defineHolixConfig(config: HolixConfig): HolixConfig {\r\n return config\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAS,qBAAqB,MAAsB;AAClD,KAAI,KAAK,WAAW,IAAI,CAEtB,QAAO,KAAK,MAAM,EAAE,CAAC,QAAQ,KAAK,IAAI;AAExC,QAAO;;AAOT,eAAsB,gBAAgB,EACpC,MAAM,QAAQ,KAAK,KACC,EACpB,KAAK,QAAQ,KAAK,EACnB,EAAE;CACD,MAAM,cAAc,MAAM,gBAAgB,IAAI;CAE9C,MAAM,EAAE,QAAQ,eAAe,MAAM,WAAwB;EAC3D,MAAM;EACN;EACA,eAAe;EAChB,CAAC;AAGF,KAAI,OAAO,OAAO,CAAC,OAAO,IAAI,MAAM,YAAY,KAC9C,QAAO,IAAI,KAAK,qBAAqB,YAAY,KAAK;CAkBxD,MAAM,mBAAmB,eAbS;EAChC,KAAK,OAAO;EACZ,aAAa,OAAO;EACpB,QAAQ,OAAO,UAAU,mBAAmB;EAC5C,SAAS,OAAO,WAAW,mBAAmB;EAC9C,WAAW,OAAO,aAAa,mBAAmB;EAClD,OAAO,OAAO,SAAS,mBAAmB;EAC1C,MAAM,OAAO,QAAQ,mBAAmB;EACxC,iBAAiB,OAAO,mBAAmB,mBAAmB;EAC9D,aAAa,OAAO,eAAe,mBAAmB;EACvD,CAGoD;AACrD,KAAI,CAAC,iBAAiB,SAAS;EAC7B,MAAM,gBAAgB,iBAAiB,MAAM,OAAO,KAAK,UACvD,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,MAAM,UACvC,CAAC,KAAK,KAAK;AACZ,QAAM,IAAI,MAAM,iCAAiC,gBAAgB;;AAGnE,QAAO;EACL,QAAQ,iBAAiB;EACzB;EACA;EACD;;;;;;;;;;;;;;;;;;;;ACpDH,SAAgB,kBAAkB,QAAkC;AAClE,QAAO"}
@@ -49,11 +49,7 @@ async function loadHolixConfig({ cwd = node_process.default.cwd() } = { cwd: nod
49
49
  const { config, configFile } = await (0, c12.loadConfig)({
50
50
  name: "holix",
51
51
  cwd,
52
- defaultConfig: {
53
- outDir: __holix_config.defaultHolixConfig.outDir,
54
- preload: __holix_config.defaultHolixConfig.preload,
55
- plugins: __holix_config.defaultHolixConfig.plugins
56
- }
52
+ defaultConfig: __holix_config.defaultHolixConfig
57
53
  });
58
54
  if (config.app && !config.app.id && packageJson.name) config.app.id = normalizePackageName(packageJson.name);
59
55
  const validationResult = (0, __holix_config.validateConfig)({
@@ -61,8 +57,11 @@ async function loadHolixConfig({ cwd = node_process.default.cwd() } = { cwd: nod
61
57
  directories: config.directories,
62
58
  outDir: config.outDir ?? __holix_config.defaultHolixConfig.outDir,
63
59
  preload: config.preload ?? __holix_config.defaultHolixConfig.preload,
64
- plugins: config.plugins ?? __holix_config.defaultHolixConfig.plugins,
65
- vite: config.vite ?? __holix_config.defaultHolixConfig.vite
60
+ publicDir: config.publicDir ?? __holix_config.defaultHolixConfig.publicDir,
61
+ alias: config.alias ?? __holix_config.defaultHolixConfig.alias,
62
+ port: config.port ?? __holix_config.defaultHolixConfig.port,
63
+ rolldownPlugins: config.rolldownPlugins ?? __holix_config.defaultHolixConfig.rolldownPlugins,
64
+ vitePlugins: config.vitePlugins ?? __holix_config.defaultHolixConfig.vitePlugins
66
65
  });
67
66
  if (!validationResult.success) {
68
67
  const errorMessages = validationResult.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
package/dist/index.cjs CHANGED
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env node
2
- const require_config = require('./config-BrQgiHmo.cjs');
2
+ const require_config = require('./config-DiolnOet.cjs');
3
3
  let citty = require("citty");
4
4
  let node_process = require("node:process");
5
5
  node_process = require_config.__toESM(node_process);
6
6
  let __holix_builder = require("@holix/builder");
7
7
  let consola = require("consola");
8
+ let node_module = require("node:module");
8
9
  let node_path = require("node:path");
10
+ let node_url = require("node:url");
11
+ require("vite");
9
12
  let __holix_electron = require("@holix/electron");
10
13
  let perfect_debounce = require("perfect-debounce");
11
- let vite = require("vite");
12
- let node_module = require("node:module");
13
14
 
14
15
  //#region src/utils/logger.ts
15
16
  const logger = consola.consola.withTag("holix");
@@ -17,6 +18,52 @@ function banner(msg) {
17
18
  logger.box(msg);
18
19
  }
19
20
 
21
+ //#endregion
22
+ //#region src/vite/resolve.ts
23
+ async function resolveViteFromCwd(cwd) {
24
+ const _require = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
25
+ let viteEntry;
26
+ try {
27
+ viteEntry = _require.resolve("vite", { paths: [cwd] });
28
+ } catch {
29
+ throw new Error(`[holix] Cannot find "vite" in project: ${cwd}\nPlease install it first: pnpm add -D vite`);
30
+ }
31
+ try {
32
+ return await import((0, node_url.pathToFileURL)(viteEntry).href);
33
+ } catch (err) {
34
+ if (err?.code === "ERR_REQUIRE_ESM" || err?.message?.includes("Cannot use import statement")) return _require(viteEntry);
35
+ throw err;
36
+ }
37
+ }
38
+ async function resolveViteConfigFromHolixConfig(cwd, holixConfig) {
39
+ const outdir = (0, node_path.join)(holixConfig.outDir || ".holix", "client");
40
+ return {
41
+ root: cwd,
42
+ base: "./",
43
+ plugins: [...holixConfig.vitePlugins || []],
44
+ resolve: { alias: holixConfig.alias || {} },
45
+ build: {
46
+ outDir: outdir,
47
+ rollupOptions: {
48
+ external: ["electron"],
49
+ output: {
50
+ entryFileNames: "[name].js",
51
+ chunkFileNames: "chunks/[name]-[hash].js",
52
+ assetFileNames: "assets/[name]-[hash][extname]"
53
+ }
54
+ }
55
+ }
56
+ };
57
+ }
58
+
59
+ //#endregion
60
+ //#region src/vite/build.ts
61
+ async function buildVite(cwd, holixConfig) {
62
+ const vite$1 = await resolveViteFromCwd(cwd);
63
+ const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig);
64
+ return vite$1.build(serverConfig);
65
+ }
66
+
20
67
  //#endregion
21
68
  //#region src/commands/build.ts
22
69
  const runBuild = (0, citty.defineCommand)({
@@ -38,6 +85,7 @@ const runBuild = (0, citty.defineCommand)({
38
85
  try {
39
86
  const { config, packageJson } = await require_config.loadHolixConfig({ cwd: rootDir });
40
87
  logger.info("Building client and main processes...");
88
+ await buildVite(rootDir, config);
41
89
  await (0, __holix_builder.build)(config, packageJson, { clean: args.clear });
42
90
  logger.success("All builds completed successfully");
43
91
  } catch (error) {
@@ -48,8 +96,7 @@ const runBuild = (0, citty.defineCommand)({
48
96
  });
49
97
 
50
98
  //#endregion
51
- //#region src/utils/vite.ts
52
- const _require = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
99
+ //#region src/vite/server.ts
53
100
  /**
54
101
  * 创建 Vite 开发服务器(不立即启动)
55
102
  *
@@ -68,23 +115,10 @@ const _require = (0, node_module.createRequire)(require("url").pathToFileURL(__f
68
115
  * server.printUrls()
69
116
  * ```
70
117
  */
71
- async function createViteDevServer(options = {}) {
72
- const { cwd = node_process.default.cwd(), config = {} } = options;
73
- let vite$1;
74
- try {
75
- vite$1 = await import(_require.resolve("vite", { paths: [cwd, (0, node_path.resolve)(cwd, "node_modules")] }));
76
- } catch {
77
- console.warn("Vite not found in project dependencies, using built-in version");
78
- vite$1 = await import("vite");
79
- }
80
- const serverConfig = {
81
- ...config,
82
- root: config.root || cwd
83
- };
84
- return vite$1.createServer({
85
- ...serverConfig,
86
- configFile: false
87
- });
118
+ async function createViteDevServer(cwd, holixConfig) {
119
+ const vite$1 = await resolveViteFromCwd(cwd);
120
+ const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig);
121
+ return vite$1.createServer(serverConfig);
88
122
  }
89
123
 
90
124
  //#endregion
@@ -114,12 +148,8 @@ const runDev = (0, citty.defineCommand)({
114
148
  if (args.clear) logger.info("Clear output:", "enabled");
115
149
  try {
116
150
  const { config, packageJson } = await require_config.loadHolixConfig({ cwd: rootDir });
117
- const viteServer = await createViteDevServer((0, vite.mergeConfig)(config.vite, {
118
- root: rootDir,
119
- base: "./",
120
- resolve: { alias: config?.alias || {} }
121
- }));
122
- const port = config.vite?.server?.port ?? config.port ?? 5183;
151
+ const viteServer = await createViteDevServer(rootDir, config);
152
+ const port = config.port ?? 5183;
123
153
  await viteServer.listen(port);
124
154
  viteServer.printUrls();
125
155
  logger.info("Building client and main processes...");
@@ -138,12 +168,13 @@ const runDev = (0, citty.defineCommand)({
138
168
  cwd: rootDir,
139
169
  env: { NODE_ENV: "development" }
140
170
  });
171
+ logger.success("Electron started");
141
172
  let isRestarting = false;
142
- const onExit = (code) => {
173
+ const onExit = (0, perfect_debounce.debounce)((code) => {
143
174
  logger.info("Electron process exited with code", code);
144
175
  watcher.close();
145
176
  node_process.default.exit(code ?? 0);
146
- };
177
+ }, 100);
147
178
  const restart = (0, perfect_debounce.debounce)(async () => {
148
179
  logger.info("Changes detected. Restarting Electron...");
149
180
  if (isRestarting) return;
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { n as loadHolixConfig } from "./config-DF41qZ52.mjs";
2
+ import { n as loadHolixConfig } from "./config-BMXlLU4W.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { defineCommand, runMain } from "citty";
5
5
  import process from "node:process";
6
6
  import { build, dev } from "@holix/builder";
7
7
  import { consola } from "consola";
8
- import { resolve } from "node:path";
8
+ import { join, resolve } from "node:path";
9
+ import { pathToFileURL } from "node:url";
10
+ import "vite";
9
11
  import { startElectron } from "@holix/electron";
10
12
  import { debounce } from "perfect-debounce";
11
- import { mergeConfig } from "vite";
12
13
 
13
14
  //#region src/utils/logger.ts
14
15
  const logger = consola.withTag("holix");
@@ -16,6 +17,52 @@ function banner(msg) {
16
17
  logger.box(msg);
17
18
  }
18
19
 
20
+ //#endregion
21
+ //#region src/vite/resolve.ts
22
+ async function resolveViteFromCwd(cwd) {
23
+ const _require = createRequire(import.meta.url);
24
+ let viteEntry;
25
+ try {
26
+ viteEntry = _require.resolve("vite", { paths: [cwd] });
27
+ } catch {
28
+ throw new Error(`[holix] Cannot find "vite" in project: ${cwd}\nPlease install it first: pnpm add -D vite`);
29
+ }
30
+ try {
31
+ return await import(pathToFileURL(viteEntry).href);
32
+ } catch (err) {
33
+ if (err?.code === "ERR_REQUIRE_ESM" || err?.message?.includes("Cannot use import statement")) return _require(viteEntry);
34
+ throw err;
35
+ }
36
+ }
37
+ async function resolveViteConfigFromHolixConfig(cwd, holixConfig) {
38
+ const outdir = join(holixConfig.outDir || ".holix", "client");
39
+ return {
40
+ root: cwd,
41
+ base: "./",
42
+ plugins: [...holixConfig.vitePlugins || []],
43
+ resolve: { alias: holixConfig.alias || {} },
44
+ build: {
45
+ outDir: outdir,
46
+ rollupOptions: {
47
+ external: ["electron"],
48
+ output: {
49
+ entryFileNames: "[name].js",
50
+ chunkFileNames: "chunks/[name]-[hash].js",
51
+ assetFileNames: "assets/[name]-[hash][extname]"
52
+ }
53
+ }
54
+ }
55
+ };
56
+ }
57
+
58
+ //#endregion
59
+ //#region src/vite/build.ts
60
+ async function buildVite(cwd, holixConfig) {
61
+ const vite = await resolveViteFromCwd(cwd);
62
+ const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig);
63
+ return vite.build(serverConfig);
64
+ }
65
+
19
66
  //#endregion
20
67
  //#region src/commands/build.ts
21
68
  const runBuild = defineCommand({
@@ -37,6 +84,7 @@ const runBuild = defineCommand({
37
84
  try {
38
85
  const { config, packageJson } = await loadHolixConfig({ cwd: rootDir });
39
86
  logger.info("Building client and main processes...");
87
+ await buildVite(rootDir, config);
40
88
  await build(config, packageJson, { clean: args.clear });
41
89
  logger.success("All builds completed successfully");
42
90
  } catch (error) {
@@ -47,8 +95,7 @@ const runBuild = defineCommand({
47
95
  });
48
96
 
49
97
  //#endregion
50
- //#region src/utils/vite.ts
51
- const _require = createRequire(import.meta.url);
98
+ //#region src/vite/server.ts
52
99
  /**
53
100
  * 创建 Vite 开发服务器(不立即启动)
54
101
  *
@@ -67,23 +114,10 @@ const _require = createRequire(import.meta.url);
67
114
  * server.printUrls()
68
115
  * ```
69
116
  */
70
- async function createViteDevServer(options = {}) {
71
- const { cwd = process.cwd(), config = {} } = options;
72
- let vite;
73
- try {
74
- vite = await import(_require.resolve("vite", { paths: [cwd, resolve(cwd, "node_modules")] }));
75
- } catch {
76
- console.warn("Vite not found in project dependencies, using built-in version");
77
- vite = await import("vite");
78
- }
79
- const serverConfig = {
80
- ...config,
81
- root: config.root || cwd
82
- };
83
- return vite.createServer({
84
- ...serverConfig,
85
- configFile: false
86
- });
117
+ async function createViteDevServer(cwd, holixConfig) {
118
+ const vite = await resolveViteFromCwd(cwd);
119
+ const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig);
120
+ return vite.createServer(serverConfig);
87
121
  }
88
122
 
89
123
  //#endregion
@@ -113,12 +147,8 @@ const runDev = defineCommand({
113
147
  if (args.clear) logger.info("Clear output:", "enabled");
114
148
  try {
115
149
  const { config, packageJson } = await loadHolixConfig({ cwd: rootDir });
116
- const viteServer = await createViteDevServer(mergeConfig(config.vite, {
117
- root: rootDir,
118
- base: "./",
119
- resolve: { alias: config?.alias || {} }
120
- }));
121
- const port = config.vite?.server?.port ?? config.port ?? 5183;
150
+ const viteServer = await createViteDevServer(rootDir, config);
151
+ const port = config.port ?? 5183;
122
152
  await viteServer.listen(port);
123
153
  viteServer.printUrls();
124
154
  logger.info("Building client and main processes...");
@@ -137,12 +167,13 @@ const runDev = defineCommand({
137
167
  cwd: rootDir,
138
168
  env: { NODE_ENV: "development" }
139
169
  });
170
+ logger.success("Electron started");
140
171
  let isRestarting = false;
141
- const onExit = (code) => {
172
+ const onExit = debounce((code) => {
142
173
  logger.info("Electron process exited with code", code);
143
174
  watcher.close();
144
175
  process.exit(code ?? 0);
145
- };
176
+ }, 100);
146
177
  const restart = debounce(async () => {
147
178
  logger.info("Changes detected. Restarting Electron...");
148
179
  if (isRestarting) return;
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["vite: typeof import('vite')","serverConfig: ViteConfig"],"sources":["../src/utils/logger.ts","../src/commands/build.ts","../src/utils/vite.ts","../src/commands/dev.ts","../src/index.ts"],"sourcesContent":["import { consola } from 'consola'\r\n\r\nexport const logger = consola.withTag('holix')\r\n\r\nexport function banner(msg: string) {\r\n logger.box(msg)\r\n}\r\n","import process from 'node:process'\r\nimport { build } from '@holix/builder'\r\nimport { defineCommand } from 'citty'\r\nimport { loadHolixConfig } from '../config'\r\nimport { banner, logger } from '../utils/logger'\r\n\r\nexport const runBuild = defineCommand({\r\n meta: {\r\n name: 'build',\r\n description: 'Build Holix application for production',\r\n },\r\n args: {\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n async run({ args }) {\r\n const rootDir = process.cwd()\r\n banner('🏗️ 构建 Holix 应用程序')\r\n\r\n logger.info('Root directory:', rootDir)\r\n logger.info('Auto open:', args.open)\r\n if (args.clear) {\r\n logger.info('Clear output:', 'enabled')\r\n }\r\n\r\n try {\r\n const { config, packageJson } = await loadHolixConfig({\r\n cwd: rootDir,\r\n })\r\n\r\n logger.info('Building client and main processes...')\r\n\r\n await build(config, packageJson, { clean: args.clear })\r\n\r\n logger.success('All builds completed successfully')\r\n }\r\n catch (error) {\r\n logger.error('Build failed:', error)\r\n throw error\r\n }\r\n },\r\n})\r\n","import type { UserConfig as ViteConfig, ViteDevServer } from 'vite'\r\nimport { createRequire } from 'node:module'\r\nimport { resolve } from 'node:path'\r\nimport process from 'node:process'\r\n\r\nconst _require = createRequire(import.meta.url)\r\n\r\n/**\r\n * Vite 开发服务器选项\r\n */\r\nexport interface ViteDevServerOptions {\r\n /**\r\n * 工作目录\r\n * @default process.cwd()\r\n */\r\n cwd?: string\r\n\r\n /**\r\n * Vite 配置\r\n */\r\n config?: ViteConfig\r\n\r\n /**\r\n * 服务器端口\r\n * @default 5173\r\n */\r\n port?: number\r\n}\r\n\r\n/**\r\n * 创建 Vite 开发服务器(不立即启动)\r\n *\r\n * @param options - Vite 开发服务器选项\r\n * @returns ViteDevServer 实例\r\n *\r\n * @example\r\n * ```ts\r\n * const server = await createViteDevServer({\r\n * cwd: '/path/to/project',\r\n * config: { root: './src' }\r\n * })\r\n *\r\n * // 手动启动\r\n * await server.listen()\r\n * server.printUrls()\r\n * ```\r\n */\r\nexport async function createViteDevServer(\r\n options: ViteDevServerOptions = {},\r\n): Promise<ViteDevServer> {\r\n const {\r\n cwd = process.cwd(),\r\n config = {},\r\n } = options\r\n\r\n // 从用户项目的 node_modules 中解析 Vite\r\n let vite: typeof import('vite')\r\n\r\n try {\r\n const vitePath = _require.resolve('vite', {\r\n paths: [cwd, resolve(cwd, 'node_modules')],\r\n })\r\n vite = await import(vitePath)\r\n }\r\n catch {\r\n console.warn('Vite not found in project dependencies, using built-in version')\r\n vite = await import('vite')\r\n }\r\n\r\n // 创建 Vite 服务器配置\r\n const serverConfig: ViteConfig = {\r\n ...config,\r\n root: config.root || cwd,\r\n }\r\n\r\n // 创建开发服务器(不启动)\r\n return vite.createServer({\r\n ...serverConfig,\r\n configFile: false,\r\n })\r\n}\r\n","import { resolve } from 'node:path'\r\nimport process from 'node:process'\r\nimport { dev } from '@holix/builder'\r\nimport { startElectron } from '@holix/electron'\r\nimport { defineCommand } from 'citty'\r\nimport { debounce } from 'perfect-debounce'\r\nimport { mergeConfig } from 'vite'\r\nimport { loadHolixConfig } from '../config'\r\nimport { banner, logger } from '../utils/logger'\r\nimport { createViteDevServer } from '../utils/vite'\r\n\r\nexport const runDev = defineCommand({\r\n meta: {\r\n name: 'dev',\r\n description: 'Start Holix development mode (with SSR + Electron hot reload)',\r\n },\r\n args: {\r\n open: {\r\n type: 'boolean',\r\n description: 'auto open Electron window',\r\n default: true,\r\n },\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n async run({ args }) {\r\n const rootDir = process.cwd()\r\n banner('🚀 启动 Holix 开发模式')\r\n\r\n logger.info('Root directory:', rootDir)\r\n logger.info('Auto open:', args.open)\r\n\r\n if (args.clear) {\r\n logger.info('Clear output:', 'enabled')\r\n }\r\n\r\n try {\r\n const { config, packageJson } = await loadHolixConfig({\r\n cwd: rootDir,\r\n })\r\n\r\n const viteServer = await createViteDevServer(mergeConfig(config.vite, {\r\n root: rootDir,\r\n base: './',\r\n resolve: {\r\n alias: config?.alias || { },\r\n },\r\n }))\r\n\r\n const port = config.vite?.server?.port ?? config.port ?? 5183\r\n\r\n await viteServer.listen(port)\r\n\r\n viteServer.printUrls()\r\n\r\n logger.info('Building client and main processes...')\r\n\r\n const watcher = await dev(config, packageJson, { clean: args.clear })\r\n\r\n logger.success('✓ Client built')\r\n\r\n logger.success('All builds completed successfully')\r\n\r\n if (!packageJson.main) {\r\n logger.warn('No main entry found in package.json, skipping Electron start.')\r\n return\r\n }\r\n\r\n // 如果启用 open,启动 Electron 进程\r\n if (args.open && packageJson.main) {\r\n const mainEntry = resolve(rootDir, packageJson.main!)\r\n logger.info('Starting Electron...')\r\n\r\n const electronProcess = await startElectron({\r\n entry: mainEntry,\r\n cwd: rootDir,\r\n env: {\r\n NODE_ENV: 'development',\r\n },\r\n })\r\n\r\n let isRestarting = false\r\n\r\n const onExit = (code: number | null) => {\r\n logger.info('Electron process exited with code', code)\r\n watcher.close()\r\n process.exit(code ?? 0)\r\n }\r\n\r\n const restart = debounce(async () => {\r\n logger.info('Changes detected. Restarting Electron...')\r\n if (isRestarting) {\r\n return\r\n }\r\n isRestarting = true\r\n electronProcess.off('exit', onExit)\r\n await electronProcess.restart()\r\n electronProcess.on('exit', onExit)\r\n isRestarting = false\r\n })\r\n\r\n watcher.on('change', async (event, change) => {\r\n logger.info(`File ${change.event} detected: ${event}`)\r\n restart()\r\n })\r\n\r\n electronProcess.on('exit', onExit)\r\n }\r\n else {\r\n watcher.close()\r\n }\r\n }\r\n catch (error) {\r\n logger.error('Build failed:', error)\r\n throw error\r\n }\r\n },\r\n})\r\n","#!/usr/bin/env node\r\nimport { defineCommand, runMain } from 'citty'\r\nimport { runBuild } from './commands/build'\r\nimport { runDev } from './commands/dev'\r\n\r\nconst main = defineCommand({\r\n meta: {\r\n name: 'holix',\r\n version: '0.1.0',\r\n description: 'Holix Application Framework CLI - Build desktop apps with Vue SSR + Electron',\r\n },\r\n args: {\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n subCommands: {\r\n dev: runDev,\r\n build: runBuild,\r\n },\r\n})\r\n\r\nrunMain(main)\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["viteEntry: string","err: any"],"sources":["../src/utils/logger.ts","../src/vite/resolve.ts","../src/vite/build.ts","../src/commands/build.ts","../src/vite/server.ts","../src/commands/dev.ts","../src/index.ts"],"sourcesContent":["import { consola } from 'consola'\r\n\r\nexport const logger = consola.withTag('holix')\r\n\r\nexport function banner(msg: string) {\r\n logger.box(msg)\r\n}\r\n","import type { HolixConfig } from '@holix/config'\r\nimport type { UserConfig as ViteConfig } from 'vite'\r\nimport { createRequire } from 'node:module'\r\nimport { join } from 'node:path'\r\nimport { pathToFileURL } from 'node:url'\r\n\r\nexport { mergeConfig } from 'vite'\r\n\r\nexport async function resolveViteFromCwd(\r\n cwd: string,\r\n): Promise<typeof import('vite')> {\r\n const _require = createRequire(import.meta.url)\r\n let viteEntry: string\r\n\r\n try {\r\n viteEntry = _require.resolve('vite', {\r\n paths: [cwd],\r\n })\r\n }\r\n catch {\r\n throw new Error(\r\n `[holix] Cannot find \"vite\" in project: ${cwd}\\n`\r\n + `Please install it first: pnpm add -D vite`,\r\n )\r\n }\r\n\r\n try {\r\n // 优先走 ESM\r\n return await import(pathToFileURL(viteEntry).href)\r\n }\r\n catch (err: any) {\r\n // 仅在明确是 CJS 不兼容时 fallback\r\n if (\r\n err?.code === 'ERR_REQUIRE_ESM'\r\n || err?.message?.includes('Cannot use import statement')\r\n ) {\r\n return _require(viteEntry)\r\n }\r\n\r\n throw err\r\n }\r\n}\r\n\r\nexport async function resolveViteConfigFromHolixConfig(cwd: string, holixConfig: HolixConfig): Promise<ViteConfig> {\r\n const outdir = join(holixConfig.outDir || '.holix', 'client')\r\n\r\n const viteConfig: ViteConfig = {\r\n root: cwd,\r\n base: './',\r\n plugins: [\r\n ...(holixConfig.vitePlugins || []),\r\n ],\r\n resolve: {\r\n alias: holixConfig.alias || {},\r\n },\r\n build: {\r\n outDir: outdir,\r\n rollupOptions: {\r\n external: ['electron'],\r\n output: {\r\n // 可选:控制输出文件名\r\n entryFileNames: '[name].js',\r\n chunkFileNames: 'chunks/[name]-[hash].js',\r\n assetFileNames: 'assets/[name]-[hash][extname]',\r\n },\r\n },\r\n },\r\n }\r\n return viteConfig\r\n}\r\n","import type { HolixConfig } from '@holix/config'\r\nimport { resolveViteConfigFromHolixConfig, resolveViteFromCwd } from './resolve'\r\n\r\nexport async function buildVite(cwd: string, holixConfig: HolixConfig) {\r\n // 从用户项目的 node_modules 中解析 Vite\r\n const vite = await resolveViteFromCwd(cwd)\r\n\r\n // 创建 Vite 服务器配置\r\n const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig)\r\n\r\n return vite.build(serverConfig)\r\n}\r\n","import process from 'node:process'\r\nimport { build } from '@holix/builder'\r\nimport { defineCommand } from 'citty'\r\nimport { loadHolixConfig } from '../config'\r\nimport { banner, logger } from '../utils/logger'\r\nimport { buildVite } from '../vite/build'\r\n\r\nexport const runBuild = defineCommand({\r\n meta: {\r\n name: 'build',\r\n description: 'Build Holix application for production',\r\n },\r\n args: {\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n async run({ args }) {\r\n const rootDir = process.cwd()\r\n banner('🏗️ 构建 Holix 应用程序')\r\n\r\n logger.info('Root directory:', rootDir)\r\n logger.info('Auto open:', args.open)\r\n if (args.clear) {\r\n logger.info('Clear output:', 'enabled')\r\n }\r\n\r\n try {\r\n const { config, packageJson } = await loadHolixConfig({\r\n cwd: rootDir,\r\n })\r\n\r\n logger.info('Building client and main processes...')\r\n\r\n await buildVite(rootDir, config)\r\n\r\n await build(config, packageJson, { clean: args.clear })\r\n\r\n logger.success('All builds completed successfully')\r\n }\r\n catch (error) {\r\n logger.error('Build failed:', error)\r\n throw error\r\n }\r\n },\r\n})\r\n","import type { HolixConfig } from '@holix/config/dist/index.mjs'\r\nimport { resolveViteConfigFromHolixConfig, resolveViteFromCwd } from './resolve'\r\n\r\n/**\r\n * 创建 Vite 开发服务器(不立即启动)\r\n *\r\n * @param options - Vite 开发服务器选项\r\n * @returns ViteDevServer 实例\r\n *\r\n * @example\r\n * ```ts\r\n * const server = await createViteDevServer({\r\n * cwd: '/path/to/project',\r\n * config: { root: './src' }\r\n * })\r\n *\r\n * // 手动启动\r\n * await server.listen()\r\n * server.printUrls()\r\n * ```\r\n */\r\nexport async function createViteDevServer(cwd: string, holixConfig: HolixConfig) {\r\n // 从用户项目的 node_modules 中解析 Vite\r\n const vite = await resolveViteFromCwd(cwd)\r\n\r\n // 创建 Vite 服务器配置\r\n const serverConfig = await resolveViteConfigFromHolixConfig(cwd, holixConfig)\r\n\r\n // 创建开发服务器(不启动)\r\n return vite.createServer(serverConfig)\r\n}\r\n","import { resolve } from 'node:path'\r\nimport process from 'node:process'\r\nimport { dev } from '@holix/builder'\r\nimport { startElectron } from '@holix/electron'\r\nimport { defineCommand } from 'citty'\r\nimport { debounce } from 'perfect-debounce'\r\nimport { loadHolixConfig } from '../config'\r\nimport { banner, logger } from '../utils/logger'\r\nimport { createViteDevServer } from '../vite/server'\r\n\r\nexport const runDev = defineCommand({\r\n meta: {\r\n name: 'dev',\r\n description: 'Start Holix development mode (with SSR + Electron hot reload)',\r\n },\r\n args: {\r\n open: {\r\n type: 'boolean',\r\n description: 'auto open Electron window',\r\n default: true,\r\n },\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n async run({ args }) {\r\n const rootDir = process.cwd()\r\n banner('🚀 启动 Holix 开发模式')\r\n\r\n logger.info('Root directory:', rootDir)\r\n logger.info('Auto open:', args.open)\r\n\r\n if (args.clear) {\r\n logger.info('Clear output:', 'enabled')\r\n }\r\n\r\n try {\r\n const { config, packageJson } = await loadHolixConfig({\r\n cwd: rootDir,\r\n })\r\n\r\n const viteServer = await createViteDevServer(rootDir, config)\r\n\r\n const port = config.port ?? 5183\r\n\r\n await viteServer.listen(port)\r\n\r\n viteServer.printUrls()\r\n\r\n logger.info('Building client and main processes...')\r\n\r\n const watcher = await dev(config, packageJson, { clean: args.clear })\r\n\r\n logger.success('✓ Client built')\r\n\r\n logger.success('All builds completed successfully')\r\n\r\n if (!packageJson.main) {\r\n logger.warn('No main entry found in package.json, skipping Electron start.')\r\n return\r\n }\r\n\r\n // 如果启用 open,启动 Electron 进程\r\n if (args.open && packageJson.main) {\r\n const mainEntry = resolve(rootDir, packageJson.main!)\r\n logger.info('Starting Electron...')\r\n\r\n const electronProcess = await startElectron({\r\n entry: mainEntry,\r\n cwd: rootDir,\r\n env: {\r\n NODE_ENV: 'development',\r\n },\r\n })\r\n\r\n logger.success('Electron started')\r\n\r\n let isRestarting = false\r\n\r\n const onExit = debounce((code: number | null) => {\r\n logger.info('Electron process exited with code', code)\r\n watcher.close()\r\n process.exit(code ?? 0)\r\n }, 100)\r\n\r\n const restart = debounce(async () => {\r\n logger.info('Changes detected. Restarting Electron...')\r\n if (isRestarting) {\r\n return\r\n }\r\n isRestarting = true\r\n electronProcess.off('exit', onExit)\r\n await electronProcess.restart()\r\n electronProcess.on('exit', onExit)\r\n isRestarting = false\r\n })\r\n\r\n watcher.on('change', async (event, change) => {\r\n logger.info(`File ${change.event} detected: ${event}`)\r\n restart()\r\n })\r\n\r\n electronProcess.on('exit', onExit)\r\n }\r\n else {\r\n watcher.close()\r\n }\r\n }\r\n catch (error) {\r\n logger.error('Build failed:', error)\r\n throw error\r\n }\r\n },\r\n})\r\n","#!/usr/bin/env node\r\nimport { defineCommand, runMain } from 'citty'\r\nimport { runBuild } from './commands/build'\r\nimport { runDev } from './commands/dev'\r\n\r\nconst main = defineCommand({\r\n meta: {\r\n name: 'holix',\r\n version: '0.1.0',\r\n description: 'Holix Application Framework CLI - Build desktop apps with Vue SSR + Electron',\r\n },\r\n args: {\r\n clear: {\r\n type: 'boolean',\r\n description: 'clear output directory before build',\r\n default: true,\r\n },\r\n },\r\n subCommands: {\r\n dev: runDev,\r\n build: runBuild,\r\n },\r\n})\r\n\r\nrunMain(main)\r\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@holix/cli",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "private": false,
6
6
  "description": "Holix Application Framework CLI",
7
7
  "author": "zhaogongchengsi <zzhanya648@gmail.com>",
@@ -25,12 +25,12 @@
25
25
  "exports": {
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js",
28
+ "import": "./dist/index.mjs",
29
29
  "require": "./dist/index.cjs"
30
30
  },
31
31
  "./config": {
32
32
  "types": "./dist/config/index.d.ts",
33
- "import": "./dist/config/index.js",
33
+ "import": "./dist/config/index.mjs",
34
34
  "require": "./dist/config/index.cjs"
35
35
  }
36
36
  },
@@ -40,7 +40,7 @@
40
40
  "main": "./dist/index.mjs",
41
41
  "types": "./dist/index.d.ts",
42
42
  "bin": {
43
- "holix": "./dist/index.js"
43
+ "holix": "./dist/index.mjs"
44
44
  },
45
45
  "files": [
46
46
  "dist"
@@ -53,9 +53,9 @@
53
53
  "pathe": "^2.0.3",
54
54
  "perfect-debounce": "^2.0.0",
55
55
  "pkg-types": "^1.3.1",
56
- "@holix/builder": "0.1.0",
57
- "@holix/config": "0.1.0",
58
- "@holix/electron": "0.1.0"
56
+ "@holix/config": "0.2.0",
57
+ "@holix/builder": "0.2.0",
58
+ "@holix/electron": "0.2.0"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/node": "^24.9.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DF41qZ52.mjs","names":[],"sources":["../src/config/loader.ts","../src/config/index.ts"],"sourcesContent":["import type { HolixConfig } from '@holix/config'\r\nimport type { UserConfig as ViteUserConfig } from 'vite'\r\nimport process from 'node:process'\r\nimport { defaultHolixConfig, validateConfig } from '@holix/config'\r\nimport { loadConfig } from 'c12'\r\nimport { readPackageJSON } from 'pkg-types'\r\n\r\n/**\r\n * 规范化包名为 appID 格式\r\n * 将 @scope/name 转换为 scope.name\r\n *\r\n * @example\r\n * normalizePackageName('@holix/core') // 'holix.core'\r\n * normalizePackageName('my-app') // 'my-app'\r\n */\r\nfunction normalizePackageName(name: string): string {\r\n if (name.startsWith('@')) {\r\n // 移除 @ 符号并将 / 替换为 .\r\n return name.slice(1).replace('/', '.')\r\n }\r\n return name\r\n}\r\n\r\nexport interface LoadHolixOptions {\r\n cwd?: string\r\n}\r\n\r\nexport async function loadHolixConfig({\r\n cwd = process.cwd(),\r\n}: LoadHolixOptions = {\r\n cwd: process.cwd(),\r\n}) {\r\n const packageJson = await readPackageJSON(cwd)\r\n\r\n const { config, configFile } = await loadConfig<HolixConfig>({\r\n name: 'holix',\r\n cwd,\r\n defaultConfig: {\r\n outDir: defaultHolixConfig.outDir,\r\n preload: defaultHolixConfig.preload,\r\n plugins: defaultHolixConfig.plugins,\r\n // 不设置 app 和 directories 的默认值,让用户配置决定\r\n },\r\n })\r\n\r\n // 如果用户配置了 app,但没有设置 id,使用 package.json 的 name\r\n if (config.app && !config.app.id && packageJson.name) {\r\n config.app.id = normalizePackageName(packageJson.name)\r\n }\r\n\r\n // 使用 mergeConfig 合并默认值和用户配置\r\n // 只合并用户未设置的字段\r\n const mergedConfig: HolixConfig = {\r\n app: config.app,\r\n directories: config.directories,\r\n outDir: config.outDir ?? defaultHolixConfig.outDir,\r\n preload: config.preload ?? defaultHolixConfig.preload,\r\n plugins: config.plugins ?? defaultHolixConfig.plugins,\r\n vite: config.vite ?? defaultHolixConfig.vite,\r\n }\r\n\r\n // 验证配置\r\n const validationResult = validateConfig(mergedConfig)\r\n if (!validationResult.success) {\r\n const errorMessages = validationResult.error.issues.map((issue: any) =>\r\n ` - ${issue.path.join('.')}: ${issue.message}`,\r\n ).join('\\n')\r\n throw new Error(`Invalid Holix configuration:\\n${errorMessages}`)\r\n }\r\n\r\n return {\r\n config: validationResult.data,\r\n configFile,\r\n packageJson, // 返回 packageJson 供 builder 使用\r\n }\r\n}\r\n","import type { HolixConfig } from '@holix/config'\r\n\r\nexport * from './loader'\r\n\r\n/**\r\n * 类型辅助:用于 holix.config.ts\r\n * 提供类型提示和自动完成\r\n *\r\n * @example\r\n * ```ts\r\n * // holix.config.ts\r\n * import { defineHolixConfig } from '@holix/cli/config'\r\n *\r\n * export default defineHolixConfig({\r\n * entry: 'src/index.tsx',\r\n * outDir: 'dist'\r\n * })\r\n * ```\r\n */\r\nexport function defineHolixConfig(config: HolixConfig): HolixConfig {\r\n return config\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAS,qBAAqB,MAAsB;AAClD,KAAI,KAAK,WAAW,IAAI,CAEtB,QAAO,KAAK,MAAM,EAAE,CAAC,QAAQ,KAAK,IAAI;AAExC,QAAO;;AAOT,eAAsB,gBAAgB,EACpC,MAAM,QAAQ,KAAK,KACC,EACpB,KAAK,QAAQ,KAAK,EACnB,EAAE;CACD,MAAM,cAAc,MAAM,gBAAgB,IAAI;CAE9C,MAAM,EAAE,QAAQ,eAAe,MAAM,WAAwB;EAC3D,MAAM;EACN;EACA,eAAe;GACb,QAAQ,mBAAmB;GAC3B,SAAS,mBAAmB;GAC5B,SAAS,mBAAmB;GAE7B;EACF,CAAC;AAGF,KAAI,OAAO,OAAO,CAAC,OAAO,IAAI,MAAM,YAAY,KAC9C,QAAO,IAAI,KAAK,qBAAqB,YAAY,KAAK;CAexD,MAAM,mBAAmB,eAVS;EAChC,KAAK,OAAO;EACZ,aAAa,OAAO;EACpB,QAAQ,OAAO,UAAU,mBAAmB;EAC5C,SAAS,OAAO,WAAW,mBAAmB;EAC9C,SAAS,OAAO,WAAW,mBAAmB;EAC9C,MAAM,OAAO,QAAQ,mBAAmB;EACzC,CAGoD;AACrD,KAAI,CAAC,iBAAiB,SAAS;EAC7B,MAAM,gBAAgB,iBAAiB,MAAM,OAAO,KAAK,UACvD,OAAO,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI,MAAM,UACvC,CAAC,KAAK,KAAK;AACZ,QAAM,IAAI,MAAM,iCAAiC,gBAAgB;;AAGnE,QAAO;EACL,QAAQ,iBAAiB;EACzB;EACA;EACD;;;;;;;;;;;;;;;;;;;;ACvDH,SAAgB,kBAAkB,QAAkC;AAClE,QAAO"}