@hile/cli 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +59 -41
  2. package/dist/index.js +37 -1
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hile/cli
2
2
 
3
- Hile 命令行工具,用于启动基于 `@hile/core` 的服务应用。支持通过 `package.json` 配置和/或自动扫描 `*.boot.{ts,js}` 文件加载服务,并注册退出钩子实现优雅关闭。
3
+ Hile 命令行工具,用于启动基于 `@hile/core` 的服务应用。支持通过 `package.json` 配置和/或自动扫描 `*.boot.{ts,js}` 加载服务,并在进程退出时执行优雅关闭。
4
4
 
5
5
  ## 安装
6
6
 
@@ -8,7 +8,7 @@ Hile 命令行工具,用于启动基于 `@hile/core` 的服务应用。支持
8
8
  pnpm add @hile/cli
9
9
  ```
10
10
 
11
- 全局安装后可直接使用 `hile` 命令:
11
+ 全局使用:
12
12
 
13
13
  ```bash
14
14
  pnpm add -g @hile/cli
@@ -18,43 +18,59 @@ pnpm add -g @hile/cli
18
18
 
19
19
  ### `hile start`
20
20
 
21
- 在**当前工作目录**(通常为项目根,且含 `package.json`)下启动服务。按以下顺序加载服务并启动:
21
+ 在当前工作目录(通常为项目根,且包含 `package.json`)启动服务。加载顺序如下:
22
22
 
23
- 1. **package.json 中的 `hile.auto_load_packages`**(若存在):按数组顺序加载所列**模块名**的默认导出作为服务。
24
- 2. **运行时目录下的 `*.boot.ts` / `*.boot.js`**:扫描并加载每个文件的默认导出作为服务。
23
+ 1. `package.json` 中的 `hile.auto_load_packages`(如存在)
24
+ 2. 运行时目录下的 `*.boot.ts` / `*.boot.js`
25
25
 
26
- 若上述两者均未提供任何可加载项,CLI 会输出 `no services to load` 并退出。每个加载项(模块或 boot 文件)的默认导出须通过 `isService` 校验,否则会抛出 `invalid service file`。
26
+ 若两者都未提供可加载服务,CLI 输出 `no services to load` 并退出。每个加载项的默认导出都必须通过 `isService` 校验,否则抛出 `invalid service file`。
27
27
 
28
28
  ```bash
29
- hile start # 生产模式:NODE_ENV=production,扫描 dist/ 目录
30
- hile start --dev # 开发模式:NODE_ENV=development,扫描 src/ 目录(通过 tsx 支持 TypeScript)
29
+ hile start
30
+ hile start --dev
31
31
  ```
32
32
 
33
33
  | 选项 | 说明 | 默认值 |
34
34
  |------|------|--------|
35
- | `-d, --dev` | 开发模式:设置 `NODE_ENV=development`,使用 tsx 运行 TypeScript,扫描 `src/` | `false` |
36
- | `-e, --env-file <path>` | 加载指定 env 文件到 `process.env`(与 Node 原生 `--env-file` 语义一致:先加载的优先,已存在的 key 不覆盖)。可多次指定 | — |
35
+ | `-d, --dev` | 开发模式:`NODE_ENV=development`,使用 tsx,扫描 `src/` | `false` |
36
+ | `-e, --env-file <path>` | 加载 env 文件到 `process.env`,可多次指定 | — |
37
37
 
38
- 未使用 `--dev` 时,CLI 会将 `process.env.NODE_ENV` 设为 `production`;使用 `--dev` 时设为 `development`,便于业务代码区分环境。
38
+ - `--dev` 模式:`NODE_ENV=production`
39
+ - `--dev` 模式:`NODE_ENV=development`
39
40
 
40
- **示例:** `hile start --env-file .env --env-file .env.local` 会先加载 `.env`,再加载 `.env.local`(后者不会覆盖前者已设置的变量)。依赖 Node 20.12+ 原生 `process.loadEnvFile()`。
41
+ 示例:
41
42
 
42
- ### 其他
43
+ ```bash
44
+ hile start --env-file .env --env-file .env.local
45
+ ```
46
+
47
+ 依赖 Node 20.12+ 原生 `process.loadEnvFile()`。
48
+
49
+ ### 启动日志(基于 @hile/core 事件)
50
+
51
+ CLI 已接入容器事件日志,默认会输出:
52
+
53
+ - 服务启动:`service:init` / `service:ready`(含耗时)
54
+ - 服务失败:`service:error`
55
+ - 关闭阶段:`service:shutdown:start` / `service:shutdown:done`
56
+ - 容器关闭:`container:shutdown:start` / `container:shutdown:done`
57
+
58
+ 这使得线上启动问题与关闭过程更容易观测。
59
+
60
+ ### 其他命令
43
61
 
44
62
  ```bash
45
- hile -v # 查看版本号
46
- hile -h # 查看帮助
63
+ hile -v
64
+ hile -h
47
65
  ```
48
66
 
49
67
  ## 运行时目录
50
68
 
51
- CLI 按以下优先级确定扫描目录:
52
-
53
- 1. 环境变量 `HILE_RUNTIME_DIR`(如果设置)
54
- 2. 开发模式(`--dev`)→ `src/`
55
- 3. 生产模式 → `dist/`
69
+ 扫描目录优先级:
56
70
 
57
- 可通过环境变量自定义:
71
+ 1. `HILE_RUNTIME_DIR`(若设置)
72
+ 2. `--dev` 模式:`src/`
73
+ 3. 生产模式:`dist/`
58
74
 
59
75
  ```bash
60
76
  HILE_RUNTIME_DIR=./custom hile start
@@ -62,7 +78,7 @@ HILE_RUNTIME_DIR=./custom hile start
62
78
 
63
79
  ## package.json 配置(可选)
64
80
 
65
- 在项目根目录的 `package.json` 中可增加 `hile.auto_load_packages`,用于在扫描 boot 文件**之前**先加载指定模块的默认导出作为服务:
81
+ 可在项目根目录配置 `hile.auto_load_packages`,用于在扫描 boot 文件之前先加载指定模块:
66
82
 
67
83
  ```json
68
84
  {
@@ -73,14 +89,15 @@ HILE_RUNTIME_DIR=./custom hile start
73
89
  }
74
90
  ```
75
91
 
76
- - **含义**:数组中的每一项为**模块名**(与 `import('模块名')` 一致),不能写文件路径。
77
- - **顺序**:按数组顺序依次加载,再加载运行时目录下的 `*.boot.{ts,js}`。
78
- - **要求**:每个模块的默认导出必须是 `defineService` / `container.register` 的返回值(通过 `isService` 校验)。若无 `hile` 或 `auto_load_packages`,则仅通过 boot 文件加载服务。
79
- - **注意**:`hile` 配置为可选项。若当前工作目录存在 `package.json`,会读取其中可选的 `hile.auto_load_packages` 并优先加载;未配置该项时,仅通过 boot 文件加载服务。
92
+ 规则:
93
+
94
+ - 数组项必须是模块名(与 `import('module')` 语义一致)
95
+ - 按数组顺序加载,然后再扫描 `*.boot.{ts,js}`
96
+ - 每个模块默认导出必须是合法 Hile 服务(通过 `isService`)
80
97
 
81
98
  ## Boot 文件规范
82
99
 
83
- 每个 `*.boot.ts` 文件必须默认导出一个通过 `defineService` 定义的服务:
100
+ 每个 `*.boot.ts` / `*.boot.js` 文件必须默认导出一个服务:
84
101
 
85
102
  ```typescript
86
103
  // src/database.boot.ts
@@ -95,37 +112,38 @@ export default defineService(async (shutdown) => {
95
112
  })
96
113
  ```
97
114
 
98
- **要求:**
99
- - 文件名必须以 `.boot.ts` 或 `.boot.js` 结尾
100
- - 必须有 `default` 导出
101
- - 导出值必须是 `defineService` / `container.register` 的返回值(通过 `isService` 校验)
115
+ 要求:
116
+
117
+ - 文件名后缀必须为 `.boot.ts` 或 `.boot.js`
118
+ - 必须存在 `default` 导出
119
+ - 导出值必须为 `defineService` / `container.register` 返回值
102
120
 
103
121
  ## 优雅关闭
104
122
 
105
- 进程收到退出信号时(SIGTERMSIGINT 等),CLI 自动调用 `container.shutdown()` 按逆序销毁所有已启动的服务,确保资源正确释放。
123
+ 进程收到 `SIGTERM`、`SIGINT` 等信号时,CLI 会自动调用 `container.shutdown()`,按逆序销毁已启动服务。
106
124
 
107
125
  ## 项目结构示例
108
126
 
109
- ```
127
+ ```text
110
128
  my-app/
111
129
  ├── src/
112
- │ ├── database.boot.ts # 数据库服务(自启动)
113
- │ ├── http.boot.ts # HTTP 服务(自启动)
130
+ │ ├── database.boot.ts
131
+ │ ├── http.boot.ts
114
132
  │ └── services/
115
- │ ├── config.ts # 配置服务(被依赖,不自启动)
116
- │ └── cache.ts # 缓存服务(被依赖,不自启动)
117
- ├── package.json # 可含 hile.auto_load_packages
133
+ │ ├── config.ts
134
+ │ └── cache.ts
135
+ ├── package.json
118
136
  └── tsconfig.json
119
137
  ```
120
138
 
121
- 服务加载来源:先按 `package.json` 的 `hile.auto_load_packages`(若有)加载模块默认导出,再扫描运行时目录下的 `*.boot.{ts,js}`;其余服务通过 `loadService` 按需加载。
139
+ 服务加载来源:先加载 `hile.auto_load_packages`(如有),再加载运行时目录下的 `*.boot.{ts,js}`。其余服务通过 `loadService` 按需加载。
122
140
 
123
141
  ## 开发
124
142
 
125
143
  ```bash
126
144
  pnpm install
127
- pnpm build # 编译
128
- pnpm dev # 监听模式
145
+ pnpm build
146
+ pnpm dev
129
147
  ```
130
148
 
131
149
  ## License
package/dist/index.js CHANGED
@@ -11,6 +11,37 @@ const require = createRequire(import.meta.url);
11
11
  function loadEnvFile(filePath) {
12
12
  process.loadEnvFile(resolve(process.cwd(), filePath));
13
13
  }
14
+ function logContainerEvent(event) {
15
+ switch (event.type) {
16
+ case 'service:init':
17
+ console.info(`[hile] service#${event.id} init`);
18
+ break;
19
+ case 'service:ready':
20
+ console.info(`[hile] service#${event.id} ready (${event.durationMs}ms)`);
21
+ break;
22
+ case 'service:error':
23
+ console.error(`[hile] service#${event.id} failed (${event.durationMs}ms):`, event.error);
24
+ break;
25
+ case 'service:shutdown:start':
26
+ console.info(`[hile] service#${event.id} stopping`);
27
+ break;
28
+ case 'service:shutdown:done':
29
+ console.info(`[hile] service#${event.id} stopped (${event.durationMs}ms)`);
30
+ break;
31
+ case 'service:shutdown:error':
32
+ console.error(`[hile] service#${event.id} shutdown error:`, event.error);
33
+ break;
34
+ case 'container:shutdown:start':
35
+ console.info('[hile] container shutdown start');
36
+ break;
37
+ case 'container:shutdown:done':
38
+ console.info(`[hile] container shutdown done (${event.durationMs}ms)`);
39
+ break;
40
+ case 'container:error':
41
+ console.error('[hile] container error:', event.error);
42
+ break;
43
+ }
44
+ }
14
45
  program.version(pkg.version, '-v, --version', '当前版本号');
15
46
  /**
16
47
  * 启动服务
@@ -28,6 +59,7 @@ program
28
59
  .option('-e, --env-file <path>', '加载指定 env 文件(兼容 Node --env-file 语义;可多次指定,先加载的不被后加载覆盖)', (v, acc) => (acc.push(v), acc), [])
29
60
  .description('启动服务,加载所有后缀为 boot.ts 或 boot.js 的服务,并注册退出钩子,在进程退出时销毁所有服务')
30
61
  .action(async (options) => {
62
+ const offEvent = container.onEvent(logContainerEvent);
31
63
  // 先加载 --env-file(与 Node --env-file 行为一致:先加载的优先,已存在的 key 不被覆盖)
32
64
  const envFiles = options.envFile ?? [];
33
65
  for (const p of envFiles) {
@@ -68,13 +100,17 @@ program
68
100
  // 如果没有服务要加载,则提示
69
101
  if (!files.length) {
70
102
  console.warn('no services to load');
103
+ offEvent();
71
104
  return;
72
105
  }
73
106
  // 注册退出钩子,在进程退出时销毁所有服务
74
107
  exitHook(exit => {
75
108
  container.shutdown()
76
109
  .catch(e => console.error(e))
77
- .finally(exit);
110
+ .finally(() => {
111
+ offEvent();
112
+ exit();
113
+ });
78
114
  });
79
115
  });
80
116
  program.parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hile/cli",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -23,11 +23,11 @@
23
23
  "vitest": "^4.0.18"
24
24
  },
25
25
  "dependencies": {
26
- "@hile/core": "^1.0.16",
26
+ "@hile/core": "^1.0.18",
27
27
  "async-exit-hook": "^2.0.1",
28
28
  "commander": "^14.0.3",
29
29
  "glob": "^13.0.6",
30
30
  "tsx": "^4.21.0"
31
31
  },
32
- "gitHead": "7e174bc0b7bac23bef7aebb0883e4ce86ec7795a"
32
+ "gitHead": "81347b9de460b693ed82af46c0f4a287d4527323"
33
33
  }