@holix/cli 0.1.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.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # @holix/cli
2
+
3
+ Command-line interface for Holix applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @holix/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Commands
14
+
15
+ #### `dev`
16
+
17
+ Start development mode with hot reload.
18
+
19
+ ```bash
20
+ holix dev
21
+ ```
22
+
23
+ Options:
24
+ - `--open` - Auto open Electron window (default: true)
25
+ - `--clear` - Clear output directory before build (default: true)
26
+
27
+ #### `build`
28
+
29
+ Build application for production.
30
+
31
+ ```bash
32
+ holix build
33
+ ```
34
+
35
+ Options:
36
+ - `--clear` - Clear output directory before build (default: true)
37
+
38
+ #### `start`
39
+
40
+ Start the built application.
41
+
42
+ ```bash
43
+ holix start
44
+ ```
45
+
46
+ ### Configuration
47
+
48
+ Create `holix.config.ts` in your project root:
49
+
50
+ ```typescript
51
+ import { defineHolixConfig } from '@holix/cli/config'
52
+
53
+ export default defineHolixConfig({
54
+ // Application ID
55
+ appID: 'com.example.myapp',
56
+
57
+ // Client entry
58
+ app: {
59
+ entry: 'src/index.tsx'
60
+ },
61
+
62
+ // Preload scripts
63
+ preload: {
64
+ preload: 'src/preload.ts'
65
+ },
66
+
67
+ // Or multiple preload scripts
68
+ preload: {
69
+ main: 'src/preload-main.ts',
70
+ worker: 'src/preload-worker.ts'
71
+ },
72
+
73
+ // Directory configuration
74
+ directories: {
75
+ pages: 'src/pages'
76
+ },
77
+
78
+ // Output directory
79
+ outDir: 'dist',
80
+
81
+ // Vite configuration
82
+ vite: {
83
+ plugins: [],
84
+ server: {
85
+ port: 3000
86
+ }
87
+ },
88
+
89
+ // Or use external Vite config
90
+ viteConfigFile: './vite.config.ts',
91
+
92
+ // Plugins
93
+ plugins: []
94
+ })
95
+ ```
96
+
97
+ ### Package.json Scripts
98
+
99
+ Add these scripts to your `package.json`:
100
+
101
+ ```json
102
+ {
103
+ "scripts": {
104
+ "dev": "holix dev",
105
+ "build": "holix build",
106
+ "start": "holix start"
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Development Workflow
112
+
113
+ 1. **Start Development**
114
+ ```bash
115
+ pnpm dev
116
+ ```
117
+ This will:
118
+ - Build main and preload processes
119
+ - Start Vite dev server for renderer
120
+ - Launch Electron with hot reload
121
+ - Watch for file changes
122
+
123
+ 2. **Build for Production**
124
+ ```bash
125
+ pnpm build
126
+ ```
127
+ This will:
128
+ - Build all processes (main, preload, renderer)
129
+ - Optimize for production
130
+ - Output to `dist/` directory
131
+
132
+ 3. **Run Production Build**
133
+ ```bash
134
+ pnpm start
135
+ ```
136
+
137
+ ### Hot Reload
138
+
139
+ The development server automatically:
140
+ - Reloads renderer process on file changes
141
+ - Restarts main process on file changes
142
+ - Maintains application state where possible
143
+
144
+ ### File-based Routing
145
+
146
+ Place page components in `src/pages/`:
147
+
148
+ ```
149
+ src/pages/
150
+ ├── index.tsx # /
151
+ ├── about.tsx # /about
152
+ └── users/
153
+ └── [id].tsx # /users/:id
154
+ ```
155
+
156
+ The CLI will automatically generate routes based on the file structure.
157
+
158
+ ## API
159
+
160
+ ### `defineHolixConfig(config: HolixConfig): HolixConfig`
161
+
162
+ Define and validate Holix configuration with full TypeScript support.
163
+
164
+ ```typescript
165
+ import { defineHolixConfig } from '@holix/cli/config'
166
+
167
+ export default defineHolixConfig({
168
+ // Your configuration
169
+ })
170
+ ```
171
+
172
+ ## Environment Variables
173
+
174
+ - `NODE_ENV` - Set to `development` or `production`
175
+ - `HOLIX_DEBUG` - Enable debug logging
176
+
177
+ ## License
178
+
179
+ MIT
@@ -0,0 +1,4 @@
1
+ const require_config = require('../config-BrQgiHmo.cjs');
2
+
3
+ exports.defineHolixConfig = require_config.defineHolixConfig;
4
+ exports.loadHolixConfig = require_config.loadHolixConfig;
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import * as pkg_types0 from "pkg-types";
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
+ //#region src/config/loader.d.ts
24
+ interface LoadHolixOptions {
25
+ cwd?: string;
26
+ }
27
+ declare function loadHolixConfig({
28
+ cwd
29
+ }?: LoadHolixOptions): Promise<{
30
+ config: any;
31
+ configFile: string | undefined;
32
+ packageJson: pkg_types0.PackageJson;
33
+ }>;
34
+ //#endregion
35
+ //#region src/config/index.d.ts
36
+ /**
37
+ * 类型辅助:用于 holix.config.ts
38
+ * 提供类型提示和自动完成
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * // holix.config.ts
43
+ * import { defineHolixConfig } from '@holix/cli/config'
44
+ *
45
+ * export default defineHolixConfig({
46
+ * entry: 'src/index.tsx',
47
+ * outDir: 'dist'
48
+ * })
49
+ * ```
50
+ */
51
+ declare function defineHolixConfig(config: HolixConfig): HolixConfig;
52
+ //#endregion
53
+ export { LoadHolixOptions, defineHolixConfig, loadHolixConfig };
54
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +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"}
@@ -0,0 +1,54 @@
1
+ import * as pkg_types0 from "pkg-types";
2
+ import { z } from "zod";
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
+ //#region src/config/loader.d.ts
24
+ interface LoadHolixOptions {
25
+ cwd?: string;
26
+ }
27
+ declare function loadHolixConfig({
28
+ cwd
29
+ }?: LoadHolixOptions): Promise<{
30
+ config: any;
31
+ configFile: string | undefined;
32
+ packageJson: pkg_types0.PackageJson;
33
+ }>;
34
+ //#endregion
35
+ //#region src/config/index.d.ts
36
+ /**
37
+ * 类型辅助:用于 holix.config.ts
38
+ * 提供类型提示和自动完成
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * // holix.config.ts
43
+ * import { defineHolixConfig } from '@holix/cli/config'
44
+ *
45
+ * export default defineHolixConfig({
46
+ * entry: 'src/index.tsx',
47
+ * outDir: 'dist'
48
+ * })
49
+ * ```
50
+ */
51
+ declare function defineHolixConfig(config: HolixConfig): HolixConfig;
52
+ //#endregion
53
+ export { LoadHolixOptions, defineHolixConfig, loadHolixConfig };
54
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +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"}
@@ -0,0 +1,3 @@
1
+ import { n as loadHolixConfig, t as defineHolixConfig } from "../config-DF41qZ52.mjs";
2
+
3
+ export { defineHolixConfig, loadHolixConfig };
@@ -0,0 +1,117 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+ let node_process = require("node:process");
29
+ node_process = __toESM(node_process);
30
+ let __holix_config = require("@holix/config");
31
+ let c12 = require("c12");
32
+ let pkg_types = require("pkg-types");
33
+
34
+ //#region src/config/loader.ts
35
+ /**
36
+ * 规范化包名为 appID 格式
37
+ * 将 @scope/name 转换为 scope.name
38
+ *
39
+ * @example
40
+ * normalizePackageName('@holix/core') // 'holix.core'
41
+ * normalizePackageName('my-app') // 'my-app'
42
+ */
43
+ function normalizePackageName(name) {
44
+ if (name.startsWith("@")) return name.slice(1).replace("/", ".");
45
+ return name;
46
+ }
47
+ async function loadHolixConfig({ cwd = node_process.default.cwd() } = { cwd: node_process.default.cwd() }) {
48
+ const packageJson = await (0, pkg_types.readPackageJSON)(cwd);
49
+ const { config, configFile } = await (0, c12.loadConfig)({
50
+ name: "holix",
51
+ cwd,
52
+ defaultConfig: {
53
+ outDir: __holix_config.defaultHolixConfig.outDir,
54
+ preload: __holix_config.defaultHolixConfig.preload,
55
+ plugins: __holix_config.defaultHolixConfig.plugins
56
+ }
57
+ });
58
+ if (config.app && !config.app.id && packageJson.name) config.app.id = normalizePackageName(packageJson.name);
59
+ const validationResult = (0, __holix_config.validateConfig)({
60
+ app: config.app,
61
+ directories: config.directories,
62
+ outDir: config.outDir ?? __holix_config.defaultHolixConfig.outDir,
63
+ preload: config.preload ?? __holix_config.defaultHolixConfig.preload,
64
+ plugins: config.plugins ?? __holix_config.defaultHolixConfig.plugins,
65
+ vite: config.vite ?? __holix_config.defaultHolixConfig.vite
66
+ });
67
+ if (!validationResult.success) {
68
+ const errorMessages = validationResult.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
69
+ throw new Error(`Invalid Holix configuration:\n${errorMessages}`);
70
+ }
71
+ return {
72
+ config: validationResult.data,
73
+ configFile,
74
+ packageJson
75
+ };
76
+ }
77
+
78
+ //#endregion
79
+ //#region src/config/index.ts
80
+ /**
81
+ * 类型辅助:用于 holix.config.ts
82
+ * 提供类型提示和自动完成
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // holix.config.ts
87
+ * import { defineHolixConfig } from '@holix/cli/config'
88
+ *
89
+ * export default defineHolixConfig({
90
+ * entry: 'src/index.tsx',
91
+ * outDir: 'dist'
92
+ * })
93
+ * ```
94
+ */
95
+ function defineHolixConfig(config) {
96
+ return config;
97
+ }
98
+
99
+ //#endregion
100
+ Object.defineProperty(exports, '__toESM', {
101
+ enumerable: true,
102
+ get: function () {
103
+ return __toESM;
104
+ }
105
+ });
106
+ Object.defineProperty(exports, 'defineHolixConfig', {
107
+ enumerable: true,
108
+ get: function () {
109
+ return defineHolixConfig;
110
+ }
111
+ });
112
+ Object.defineProperty(exports, 'loadHolixConfig', {
113
+ enumerable: true,
114
+ get: function () {
115
+ return loadHolixConfig;
116
+ }
117
+ });
@@ -0,0 +1,73 @@
1
+ import process from "node:process";
2
+ import { defaultHolixConfig, validateConfig } from "@holix/config";
3
+ import { loadConfig } from "c12";
4
+ import { readPackageJSON } from "pkg-types";
5
+
6
+ //#region src/config/loader.ts
7
+ /**
8
+ * 规范化包名为 appID 格式
9
+ * 将 @scope/name 转换为 scope.name
10
+ *
11
+ * @example
12
+ * normalizePackageName('@holix/core') // 'holix.core'
13
+ * normalizePackageName('my-app') // 'my-app'
14
+ */
15
+ function normalizePackageName(name) {
16
+ if (name.startsWith("@")) return name.slice(1).replace("/", ".");
17
+ return name;
18
+ }
19
+ async function loadHolixConfig({ cwd = process.cwd() } = { cwd: process.cwd() }) {
20
+ const packageJson = await readPackageJSON(cwd);
21
+ const { config, configFile } = await loadConfig({
22
+ name: "holix",
23
+ cwd,
24
+ defaultConfig: {
25
+ outDir: defaultHolixConfig.outDir,
26
+ preload: defaultHolixConfig.preload,
27
+ plugins: defaultHolixConfig.plugins
28
+ }
29
+ });
30
+ if (config.app && !config.app.id && packageJson.name) config.app.id = normalizePackageName(packageJson.name);
31
+ const validationResult = validateConfig({
32
+ app: config.app,
33
+ directories: config.directories,
34
+ outDir: config.outDir ?? defaultHolixConfig.outDir,
35
+ preload: config.preload ?? defaultHolixConfig.preload,
36
+ plugins: config.plugins ?? defaultHolixConfig.plugins,
37
+ vite: config.vite ?? defaultHolixConfig.vite
38
+ });
39
+ if (!validationResult.success) {
40
+ const errorMessages = validationResult.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
41
+ throw new Error(`Invalid Holix configuration:\n${errorMessages}`);
42
+ }
43
+ return {
44
+ config: validationResult.data,
45
+ configFile,
46
+ packageJson
47
+ };
48
+ }
49
+
50
+ //#endregion
51
+ //#region src/config/index.ts
52
+ /**
53
+ * 类型辅助:用于 holix.config.ts
54
+ * 提供类型提示和自动完成
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * // holix.config.ts
59
+ * import { defineHolixConfig } from '@holix/cli/config'
60
+ *
61
+ * export default defineHolixConfig({
62
+ * entry: 'src/index.tsx',
63
+ * outDir: 'dist'
64
+ * })
65
+ * ```
66
+ */
67
+ function defineHolixConfig(config) {
68
+ return config;
69
+ }
70
+
71
+ //#endregion
72
+ export { loadHolixConfig as n, defineHolixConfig as t };
73
+ //# sourceMappingURL=config-DF41qZ52.mjs.map
@@ -0,0 +1 @@
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"}
package/dist/index.cjs ADDED
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ const require_config = require('./config-BrQgiHmo.cjs');
3
+ let citty = require("citty");
4
+ let node_process = require("node:process");
5
+ node_process = require_config.__toESM(node_process);
6
+ let __holix_builder = require("@holix/builder");
7
+ let consola = require("consola");
8
+ let node_path = require("node:path");
9
+ let __holix_electron = require("@holix/electron");
10
+ let perfect_debounce = require("perfect-debounce");
11
+ let vite = require("vite");
12
+ let node_module = require("node:module");
13
+
14
+ //#region src/utils/logger.ts
15
+ const logger = consola.consola.withTag("holix");
16
+ function banner(msg) {
17
+ logger.box(msg);
18
+ }
19
+
20
+ //#endregion
21
+ //#region src/commands/build.ts
22
+ const runBuild = (0, citty.defineCommand)({
23
+ meta: {
24
+ name: "build",
25
+ description: "Build Holix application for production"
26
+ },
27
+ args: { clear: {
28
+ type: "boolean",
29
+ description: "clear output directory before build",
30
+ default: true
31
+ } },
32
+ async run({ args }) {
33
+ const rootDir = node_process.default.cwd();
34
+ banner("🏗️ 构建 Holix 应用程序");
35
+ logger.info("Root directory:", rootDir);
36
+ logger.info("Auto open:", args.open);
37
+ if (args.clear) logger.info("Clear output:", "enabled");
38
+ try {
39
+ const { config, packageJson } = await require_config.loadHolixConfig({ cwd: rootDir });
40
+ logger.info("Building client and main processes...");
41
+ await (0, __holix_builder.build)(config, packageJson, { clean: args.clear });
42
+ logger.success("All builds completed successfully");
43
+ } catch (error) {
44
+ logger.error("Build failed:", error);
45
+ throw error;
46
+ }
47
+ }
48
+ });
49
+
50
+ //#endregion
51
+ //#region src/utils/vite.ts
52
+ const _require = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
53
+ /**
54
+ * 创建 Vite 开发服务器(不立即启动)
55
+ *
56
+ * @param options - Vite 开发服务器选项
57
+ * @returns ViteDevServer 实例
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const server = await createViteDevServer({
62
+ * cwd: '/path/to/project',
63
+ * config: { root: './src' }
64
+ * })
65
+ *
66
+ * // 手动启动
67
+ * await server.listen()
68
+ * server.printUrls()
69
+ * ```
70
+ */
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
+ });
88
+ }
89
+
90
+ //#endregion
91
+ //#region src/commands/dev.ts
92
+ const runDev = (0, citty.defineCommand)({
93
+ meta: {
94
+ name: "dev",
95
+ description: "Start Holix development mode (with SSR + Electron hot reload)"
96
+ },
97
+ args: {
98
+ open: {
99
+ type: "boolean",
100
+ description: "auto open Electron window",
101
+ default: true
102
+ },
103
+ clear: {
104
+ type: "boolean",
105
+ description: "clear output directory before build",
106
+ default: true
107
+ }
108
+ },
109
+ async run({ args }) {
110
+ const rootDir = node_process.default.cwd();
111
+ banner("🚀 启动 Holix 开发模式");
112
+ logger.info("Root directory:", rootDir);
113
+ logger.info("Auto open:", args.open);
114
+ if (args.clear) logger.info("Clear output:", "enabled");
115
+ try {
116
+ 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;
123
+ await viteServer.listen(port);
124
+ viteServer.printUrls();
125
+ logger.info("Building client and main processes...");
126
+ const watcher = await (0, __holix_builder.dev)(config, packageJson, { clean: args.clear });
127
+ logger.success("✓ Client built");
128
+ logger.success("All builds completed successfully");
129
+ if (!packageJson.main) {
130
+ logger.warn("No main entry found in package.json, skipping Electron start.");
131
+ return;
132
+ }
133
+ if (args.open && packageJson.main) {
134
+ const mainEntry = (0, node_path.resolve)(rootDir, packageJson.main);
135
+ logger.info("Starting Electron...");
136
+ const electronProcess = await (0, __holix_electron.startElectron)({
137
+ entry: mainEntry,
138
+ cwd: rootDir,
139
+ env: { NODE_ENV: "development" }
140
+ });
141
+ let isRestarting = false;
142
+ const onExit = (code) => {
143
+ logger.info("Electron process exited with code", code);
144
+ watcher.close();
145
+ node_process.default.exit(code ?? 0);
146
+ };
147
+ const restart = (0, perfect_debounce.debounce)(async () => {
148
+ logger.info("Changes detected. Restarting Electron...");
149
+ if (isRestarting) return;
150
+ isRestarting = true;
151
+ electronProcess.off("exit", onExit);
152
+ await electronProcess.restart();
153
+ electronProcess.on("exit", onExit);
154
+ isRestarting = false;
155
+ });
156
+ watcher.on("change", async (event, change) => {
157
+ logger.info(`File ${change.event} detected: ${event}`);
158
+ restart();
159
+ });
160
+ electronProcess.on("exit", onExit);
161
+ } else watcher.close();
162
+ } catch (error) {
163
+ logger.error("Build failed:", error);
164
+ throw error;
165
+ }
166
+ }
167
+ });
168
+
169
+ //#endregion
170
+ //#region src/index.ts
171
+ (0, citty.runMain)((0, citty.defineCommand)({
172
+ meta: {
173
+ name: "holix",
174
+ version: "0.1.0",
175
+ description: "Holix Application Framework CLI - Build desktop apps with Vue SSR + Electron"
176
+ },
177
+ args: { clear: {
178
+ type: "boolean",
179
+ description: "clear output directory before build",
180
+ default: true
181
+ } },
182
+ subCommands: {
183
+ dev: runDev,
184
+ build: runBuild
185
+ }
186
+ }));
187
+
188
+ //#endregion
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.mjs ADDED
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+ import { n as loadHolixConfig } from "./config-DF41qZ52.mjs";
3
+ import { createRequire } from "node:module";
4
+ import { defineCommand, runMain } from "citty";
5
+ import process from "node:process";
6
+ import { build, dev } from "@holix/builder";
7
+ import { consola } from "consola";
8
+ import { resolve } from "node:path";
9
+ import { startElectron } from "@holix/electron";
10
+ import { debounce } from "perfect-debounce";
11
+ import { mergeConfig } from "vite";
12
+
13
+ //#region src/utils/logger.ts
14
+ const logger = consola.withTag("holix");
15
+ function banner(msg) {
16
+ logger.box(msg);
17
+ }
18
+
19
+ //#endregion
20
+ //#region src/commands/build.ts
21
+ const runBuild = defineCommand({
22
+ meta: {
23
+ name: "build",
24
+ description: "Build Holix application for production"
25
+ },
26
+ args: { clear: {
27
+ type: "boolean",
28
+ description: "clear output directory before build",
29
+ default: true
30
+ } },
31
+ async run({ args }) {
32
+ const rootDir = process.cwd();
33
+ banner("🏗️ 构建 Holix 应用程序");
34
+ logger.info("Root directory:", rootDir);
35
+ logger.info("Auto open:", args.open);
36
+ if (args.clear) logger.info("Clear output:", "enabled");
37
+ try {
38
+ const { config, packageJson } = await loadHolixConfig({ cwd: rootDir });
39
+ logger.info("Building client and main processes...");
40
+ await build(config, packageJson, { clean: args.clear });
41
+ logger.success("All builds completed successfully");
42
+ } catch (error) {
43
+ logger.error("Build failed:", error);
44
+ throw error;
45
+ }
46
+ }
47
+ });
48
+
49
+ //#endregion
50
+ //#region src/utils/vite.ts
51
+ const _require = createRequire(import.meta.url);
52
+ /**
53
+ * 创建 Vite 开发服务器(不立即启动)
54
+ *
55
+ * @param options - Vite 开发服务器选项
56
+ * @returns ViteDevServer 实例
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const server = await createViteDevServer({
61
+ * cwd: '/path/to/project',
62
+ * config: { root: './src' }
63
+ * })
64
+ *
65
+ * // 手动启动
66
+ * await server.listen()
67
+ * server.printUrls()
68
+ * ```
69
+ */
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
+ });
87
+ }
88
+
89
+ //#endregion
90
+ //#region src/commands/dev.ts
91
+ const runDev = defineCommand({
92
+ meta: {
93
+ name: "dev",
94
+ description: "Start Holix development mode (with SSR + Electron hot reload)"
95
+ },
96
+ args: {
97
+ open: {
98
+ type: "boolean",
99
+ description: "auto open Electron window",
100
+ default: true
101
+ },
102
+ clear: {
103
+ type: "boolean",
104
+ description: "clear output directory before build",
105
+ default: true
106
+ }
107
+ },
108
+ async run({ args }) {
109
+ const rootDir = process.cwd();
110
+ banner("🚀 启动 Holix 开发模式");
111
+ logger.info("Root directory:", rootDir);
112
+ logger.info("Auto open:", args.open);
113
+ if (args.clear) logger.info("Clear output:", "enabled");
114
+ try {
115
+ 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;
122
+ await viteServer.listen(port);
123
+ viteServer.printUrls();
124
+ logger.info("Building client and main processes...");
125
+ const watcher = await dev(config, packageJson, { clean: args.clear });
126
+ logger.success("✓ Client built");
127
+ logger.success("All builds completed successfully");
128
+ if (!packageJson.main) {
129
+ logger.warn("No main entry found in package.json, skipping Electron start.");
130
+ return;
131
+ }
132
+ if (args.open && packageJson.main) {
133
+ const mainEntry = resolve(rootDir, packageJson.main);
134
+ logger.info("Starting Electron...");
135
+ const electronProcess = await startElectron({
136
+ entry: mainEntry,
137
+ cwd: rootDir,
138
+ env: { NODE_ENV: "development" }
139
+ });
140
+ let isRestarting = false;
141
+ const onExit = (code) => {
142
+ logger.info("Electron process exited with code", code);
143
+ watcher.close();
144
+ process.exit(code ?? 0);
145
+ };
146
+ const restart = debounce(async () => {
147
+ logger.info("Changes detected. Restarting Electron...");
148
+ if (isRestarting) return;
149
+ isRestarting = true;
150
+ electronProcess.off("exit", onExit);
151
+ await electronProcess.restart();
152
+ electronProcess.on("exit", onExit);
153
+ isRestarting = false;
154
+ });
155
+ watcher.on("change", async (event, change) => {
156
+ logger.info(`File ${change.event} detected: ${event}`);
157
+ restart();
158
+ });
159
+ electronProcess.on("exit", onExit);
160
+ } else watcher.close();
161
+ } catch (error) {
162
+ logger.error("Build failed:", error);
163
+ throw error;
164
+ }
165
+ }
166
+ });
167
+
168
+ //#endregion
169
+ //#region src/index.ts
170
+ runMain(defineCommand({
171
+ meta: {
172
+ name: "holix",
173
+ version: "0.1.0",
174
+ description: "Holix Application Framework CLI - Build desktop apps with Vue SSR + Electron"
175
+ },
176
+ args: { clear: {
177
+ type: "boolean",
178
+ description: "clear output directory before build",
179
+ default: true
180
+ } },
181
+ subCommands: {
182
+ dev: runDev,
183
+ build: runBuild
184
+ }
185
+ }));
186
+
187
+ //#endregion
188
+ export { };
189
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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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"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@holix/cli",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "private": false,
6
+ "description": "Holix Application Framework CLI",
7
+ "author": "zhaogongchengsi <zzhanya648@gmail.com>",
8
+ "license": "MIT",
9
+ "homepage": "https://github.com/zhaogongchengsi/holix#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/zhaogongchengsi/holix",
13
+ "directory": "packages/cli"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/zhaogongchengsi/holix/issues"
17
+ },
18
+ "keywords": [
19
+ "holix",
20
+ "cli",
21
+ "electron",
22
+ "ssr",
23
+ "vue"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.cjs"
30
+ },
31
+ "./config": {
32
+ "types": "./dist/config/index.d.ts",
33
+ "import": "./dist/config/index.js",
34
+ "require": "./dist/config/index.cjs"
35
+ }
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "main": "./dist/index.mjs",
41
+ "types": "./dist/index.d.ts",
42
+ "bin": {
43
+ "holix": "./dist/index.js"
44
+ },
45
+ "files": [
46
+ "dist"
47
+ ],
48
+ "dependencies": {
49
+ "c12": "^3.3.1",
50
+ "chokidar": "^4.0.3",
51
+ "citty": "^0.1.6",
52
+ "consola": "^3.4.2",
53
+ "pathe": "^2.0.3",
54
+ "perfect-debounce": "^2.0.0",
55
+ "pkg-types": "^1.3.1",
56
+ "@holix/builder": "0.1.0",
57
+ "@holix/config": "0.1.0",
58
+ "@holix/electron": "0.1.0"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^24.9.1",
62
+ "typescript": "^5.9.3"
63
+ },
64
+ "scripts": {
65
+ "build": "tsdown",
66
+ "dev": "tsdown --watch"
67
+ }
68
+ }