@soybeanjs/cli 1.7.4 → 1.8.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 CHANGED
@@ -1,51 +1,277 @@
1
1
  # @soybeanjs/cli
2
2
 
3
- SoybeanJS 的命令行工具
3
+ SoybeanJS 的命令行工具集,提供 Git 提交规范、依赖更新、Changelog 生成、版本发布等便捷功能。
4
4
 
5
- ## 用法
5
+ ## 特性
6
6
 
7
- ### 安装
7
+ - 📝 **符合 Conventional Commits 规范的 Git 提交** - 交互式选择提交类型和范围
8
+ - ✅ **提交信息校验** - 自动校验 commit message 是否符合规范
9
+ - 🧹 **清理功能** - 一键清理 node_modules、dist 等目录
10
+ - 📦 **依赖更新** - 基于 npm-check-updates 快速升级依赖
11
+ - 📋 **Changelog 生成** - 根据 Git tags 自动生成变更日志
12
+ - 🚀 **版本发布** - 一键完成版本更新、Changelog 生成、代码提交和推送
13
+ - 🌍 **多语言支持** - 支持中文和英文,可持久化设置默认语言
14
+ - ⚙️ **灵活配置** - 支持项目级和全局配置,可自定义提交类型和范围
15
+
16
+ ## 安装
8
17
 
9
18
  ```bash
10
- pnpm i -D @soybeanjs/cli
19
+ pnpm add -D @soybeanjs/cli
20
+ # 或者
21
+ npm i -D @soybeanjs/cli
22
+ # 或者
23
+ yarn add -D @soybeanjs/cli
11
24
  ```
12
25
 
13
- ### 使用
26
+ 安装后可通过 `pnpm soy` 或 `npx soy` 使用 CLI 命令。
14
27
 
15
- 示例:
28
+ ## 快速开始
16
29
 
17
30
  ```bash
31
+ # 查看帮助
18
32
  pnpm soy -h
33
+
34
+ # 交互式 Git 提交
35
+ pnpm soy git-commit
36
+ ```
37
+
38
+ ## 命令说明
39
+
40
+ ### 全局选项
41
+
42
+ | 选项 | 说明 | 默认值 |
43
+ | ------------------------- | --------------------------------------------- | --------------------------------------- |
44
+ | `-v, --version` | 显示版本号 | - |
45
+ | `-e, --execute [command]` | 版本发布时在 bump 之后、commit 之前执行的命令 | `pnpm soy changelog` |
46
+ | `-p, --push` | 发布时是否推送 Git 提交和标签 | - |
47
+ | `-t, --total` | 生成 Changelog 时基于所有标签 | - |
48
+ | `-c, --cleanupDir <dir>` | 指定清理目录,多个目录用逗号分隔 | 见配置 |
49
+ | `-l, --lang <lang>` | CLI 显示语言 (`zh-cn` / `en-us`) | `en-us`(可通过 config 命令持久化修改) |
50
+ | `-h, --help` | 显示帮助信息 | - |
51
+
52
+ ### 命令列表
53
+
54
+ | 命令 | 说明 |
55
+ | ------------------- | ---------------------------------------------------------------- |
56
+ | `cleanup` | 清理目录(node_modules、dist、lock 文件等) |
57
+ | `ncu` | 升级 package.json 中的依赖到最新版本 |
58
+ | `update-pkg` | [已废弃] 请使用 `ncu` 代替 |
59
+ | `git-commit` | 交互式生成符合 Conventional Commits 规范的 Git 提交信息 |
60
+ | `git-commit-verify` | 校验 Git 提交信息是否符合规范(通常配合 Git hooks 使用) |
61
+ | `changelog` | 根据 Git tags 生成 Changelog |
62
+ | `release` | 一键发布:更新版本号 → 生成 Changelog → 提交代码 → 打标签 → 推送 |
63
+ | `config <cmd>` | 管理 CLI 配置 |
64
+
65
+ ### config 子命令
66
+
67
+ | 命令 | 说明 |
68
+ | ------------------------------ | -------------------------------------------------------------- |
69
+ | `config set --set-lang <lang>` | 设置默认语言(`zh-cn` 或 `en-us`),配置会持久化到全局配置文件 |
70
+ | `config get` | 查看当前配置信息 |
71
+ | `config path` | 显示全局配置文件路径 |
72
+
73
+ #### 使用示例
74
+
75
+ ```bash
76
+ # 设置默认语言为中文
77
+ pnpm soy config set --set-lang zh-cn
78
+
79
+ # 设置默认语言为英文
80
+ pnpm soy config set --set-lang en-us
81
+
82
+ # 查看当前配置
83
+ pnpm soy config get
84
+
85
+ # 查看全局配置文件位置
86
+ pnpm soy config path
87
+ ```
88
+
89
+ ### git-commit 命令详解
90
+
91
+ 使用 `pnpm soy git-commit` 进行交互式提交:
92
+
93
+ 1. **选择提交类型 (type)** - 如 feat、fix、docs、style 等
94
+ 2. **选择提交范围 (scope)** - 如 projects、components、utils 等
95
+ 3. **输入提交描述** - 在描述前加 `!` 表示破坏性变更(Breaking Change)
96
+
97
+ 生成的提交信息格式:
98
+
99
+ ```
100
+ <type>(<scope>)<!>: <description>
101
+ ```
102
+
103
+ 示例:
104
+
105
+ ```
106
+ feat(components): add new Button component
107
+ fix(utils)!: change API signature
108
+ ```
109
+
110
+ ## 配置
111
+
112
+ 支持两层配置:
113
+
114
+ 1. **全局配置** - `~/.soybeanrc`(JSON 格式),通过 `config set` 命令管理
115
+ 2. **项目配置** - 项目根目录下的配置文件(支持 TS/JS 等格式),优先级高于全局配置
116
+
117
+ ### 配置文件
118
+
119
+ 在项目根目录创建配置文件(支持以下名称):
120
+
121
+ - `soybean.config.ts`(推荐)
122
+ - `soybean.config.js`
123
+ - `soybean.config.mjs`
124
+ - `soybean.config.json`
125
+ - 在 `package.json` 的 `soybean` 字段中配置
126
+
127
+ 使用 TypeScript 配置时,使用 `defineConfig` 获得类型提示:
128
+
129
+ ```ts
130
+ // soybean.config.ts
131
+ import { defineConfig } from '@soybeanjs/cli';
132
+
133
+ export default defineConfig({
134
+ // 配置项
135
+ });
136
+ ```
137
+
138
+ ### 配置项
139
+
140
+ | 配置项 | 类型 | 说明 | 默认值 |
141
+ | ------------------------ | -------------------------- | -------------------------------------- | ---------------------------------------------------------- |
142
+ | `cwd` | `string` | 项目根目录 | `process.cwd()` |
143
+ | `lang` | `'zh-cn' \| 'en-us'` | 默认显示语言 | `'en-us'` |
144
+ | `cleanupDirs` | `string[]` | 需要清理的目录 glob 模式 | `['**/dist', '**/node_modules', '**/pnpm-lock.yaml', ...]` |
145
+ | `ncuCommandArgs` | `string[]` | ncu 命令参数 | 自动解析 workspace |
146
+ | `changelogOptions` | `Partial<ChangelogOption>` | Changelog 生成选项 | `{}` |
147
+ | `gitCommitVerifyIgnores` | `RegExp[]` | 提交信息校验忽略规则(追加到默认规则) | 见源码 |
148
+ | `gitCommit` | `GitCommitConfig` | Git 提交配置 | 见下方 |
149
+
150
+ ### Git 提交配置 (gitCommit)
151
+
152
+ 用于自定义 commit types 和 scopes:
153
+
154
+ | 配置项 | 类型 | 说明 | 默认值 |
155
+ | ------------------------ | -------------------- | --------------------------------------------------------- | ----------- |
156
+ | `gitCommit.types` | `[string, string][]` | 自定义提交类型 | 默认 types |
157
+ | `gitCommit.typesAppend` | `boolean` | 自定义 types 是否追加到默认 types(`false` 则完全覆盖) | `true` |
158
+ | `gitCommit.scopes` | `[string, string][]` | 自定义提交范围 | 默认 scopes |
159
+ | `gitCommit.scopesAppend` | `boolean` | 自定义 scopes 是否追加到默认 scopes(`false` 则完全覆盖) | `true` |
160
+
161
+ **默认提交类型 (types):**
162
+
163
+ | type | 说明 (中文) | 说明 (English) |
164
+ | ---------- | ------------------------------------- | ------------------------------------------------------------- |
165
+ | `feat` | 新功能 | A new feature |
166
+ | `fix` | 修复 Bug | A bug fix |
167
+ | `docs` | 文档更新 | Documentation only changes |
168
+ | `style` | 代码风格修改(不影响代码含义) | Changes that do not affect the meaning of the code |
169
+ | `refactor` | 代码重构(既不修复 bug 也不添加功能) | A code change that neither fixes a bug nor adds a feature |
170
+ | `perf` | 性能优化 | A code change that improves performance |
171
+ | `optimize` | 代码质量优化 | A code change that optimizes code quality |
172
+ | `test` | 测试相关 | Adding missing tests or correcting existing tests |
173
+ | `build` | 构建系统或外部依赖变更 | Changes that affect the build system or external dependencies |
174
+ | `ci` | CI 配置变更 | Changes to CI configuration files and scripts |
175
+ | `chore` | 其他不修改 src/测试文件的变更 | Other changes that don't modify src or test files |
176
+ | `revert` | 还原先前的提交 | Reverts a previous commit |
177
+
178
+ **默认提交范围 (scopes):**
179
+
180
+ | scope | 说明 (中文) | 说明 (English) |
181
+ | ------------ | -------------- | -------------------- |
182
+ | `projects` | 项目 | project |
183
+ | `packages` | 包 | packages |
184
+ | `components` | 组件 | components |
185
+ | `hooks` | 钩子函数 | hook functions |
186
+ | `utils` | 工具函数 | utils functions |
187
+ | `types` | TS 类型声明 | TS declaration |
188
+ | `styles` | 代码风格 | style |
189
+ | `deps` | 项目依赖 | project dependencies |
190
+ | `release` | 发布项目新版本 | release project |
191
+ | `other` | 其他变更 | other changes |
192
+
193
+ ### 配置示例
194
+
195
+ #### 1. 追加自定义提交类型和范围
196
+
197
+ ```ts
198
+ // soybean.config.ts
199
+ import { defineConfig } from '@soybeanjs/cli';
200
+
201
+ export default defineConfig({
202
+ lang: 'zh-cn', // 项目默认使用中文
203
+
204
+ gitCommit: {
205
+ // 追加自定义 types(在默认 types 基础上添加)
206
+ types: [
207
+ ['wip', '工作进行中'],
208
+ ['merge', '合并分支'],
209
+ ['i18n', '国际化相关']
210
+ ],
211
+
212
+ // 追加自定义 scopes
213
+ scopes: [
214
+ ['ui', 'UI 组件'],
215
+ ['store', '状态管理'],
216
+ ['api', 'API 接口']
217
+ ]
218
+ }
219
+ });
19
220
  ```
20
221
 
21
- ## 命令介绍
222
+ #### 2. 完全覆盖默认提交类型和范围
22
223
 
23
- | 命令 | 作用 |
24
- | ----------------- | ------------------------------------------------------------------------------------ |
25
- | help(-h) | 查看全部命令用法 |
26
- | git-commit | 生成符合 Angular 规范的 git 提交信息 (在提交信息添加前缀`!`可以表示破坏性更新的提交) |
27
- | git-commit-verify | 校验 git 的提交信息是否符合 Angular 规范 |
28
- | cleanup | 清空依赖和构建产物 |
29
- | ncu | 命令 npm-check-updates, 升级依赖 |
30
- | changelog | 根据两次 tag 生成 changelog (--total: 根据所有 tag 生成 changelog) |
31
- | release | 发布:更新版本号、生成 changelog、提交代码 |
224
+ ```ts
225
+ // soybean.config.ts
226
+ import { defineConfig } from '@soybeanjs/cli';
32
227
 
33
- ## 更多自定义配置
228
+ export default defineConfig({
229
+ gitCommit: {
230
+ // 完全覆盖默认 types
231
+ types: [
232
+ ['feat', '新功能'],
233
+ ['fix', '修复'],
234
+ ['docs', '文档']
235
+ ],
236
+ typesAppend: false, // 不追加,完全覆盖
34
237
 
35
- - 在项目根目录新建 soybean-config.ts
238
+ // 完全覆盖默认 scopes
239
+ scopes: [
240
+ ['frontend', '前端'],
241
+ ['backend', '后端'],
242
+ ['shared', '共享代码']
243
+ ],
244
+ scopesAppend: false
245
+ }
246
+ });
247
+ ```
36
248
 
37
- - 导入 defineConfig 函数
249
+ #### 3. 修改默认清理目录
38
250
 
39
- ```ts
40
- import { defineConfig } from '@soybeanjs/cli';
251
+ ```ts
252
+ // soybean.config.ts
253
+ import { defineConfig } from '@soybeanjs/cli';
41
254
 
42
- export default defineConfig({
43
- // options
44
- });
45
- ```
255
+ export default defineConfig({
256
+ cleanupDirs: ['**/dist', '**/.cache', '**/coverage', '**/node_modules', '!node_modules/**']
257
+ });
258
+ ```
259
+
260
+ ### package.json 脚本配置示例
261
+
262
+ ```json
263
+ {
264
+ "scripts": {
265
+ "commit": "soy git-commit",
266
+ "commit:zh": "soy git-commit -l=zh-cn",
267
+ "cleanup": "soy cleanup",
268
+ "ncu": "soy ncu",
269
+ "changelog": "soy changelog",
270
+ "release": "soy release"
271
+ }
272
+ }
273
+ ```
46
274
 
47
- - 配置参考
275
+ ## License
48
276
 
49
- ```ts
50
- import type { CliOption } from '@soybeanjs/cli';
51
- ```
277
+ [MIT](./LICENSE)
package/dist/index.d.ts CHANGED
@@ -1,5 +1,57 @@
1
1
  import { ChangelogOption } from "@soybeanjs/changelog";
2
+ //#region src/locales/index.d.ts
3
+ type Lang = 'zh-cn' | 'en-us';
4
+ //#endregion
2
5
  //#region src/types/index.d.ts
6
+ type CommitItem = [string, string];
7
+ interface GitCommitConfig {
8
+ /**
9
+ * Commit types
10
+ *
11
+ * If not set, it will use the default types
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * {
16
+ * types: [
17
+ * ['feat', '新功能'],
18
+ * ['wip', '工作进行中']
19
+ * ],
20
+ * typesAppend: true // append to defaults, set to false to overwrite
21
+ * }
22
+ * ```
23
+ */
24
+ types?: CommitItem[];
25
+ /**
26
+ * Whether to append custom types to defaults or overwrite
27
+ *
28
+ * @default true
29
+ */
30
+ typesAppend?: boolean;
31
+ /**
32
+ * Commit scopes
33
+ *
34
+ * If not set, it will use the default scopes
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * {
39
+ * scopes: [
40
+ * ['ui', 'UI 相关'],
41
+ * ['api', 'API 相关']
42
+ * ],
43
+ * scopesAppend: true // append to defaults, set to false to overwrite
44
+ * }
45
+ * ```
46
+ */
47
+ scopes?: CommitItem[];
48
+ /**
49
+ * Whether to append custom scopes to defaults or overwrite
50
+ *
51
+ * @default true
52
+ */
53
+ scopesAppend?: boolean;
54
+ }
3
55
  interface CliOption {
4
56
  /** The project root directory */
5
57
  cwd: string;
@@ -28,6 +80,18 @@ interface CliOption {
28
80
  changelogOptions: Partial<ChangelogOption>;
29
81
  /** The ignore pattern list of git commit verify */
30
82
  gitCommitVerifyIgnores: RegExp[];
83
+ /**
84
+ * Git commit config for types and scopes
85
+ */
86
+ gitCommit?: GitCommitConfig;
87
+ /**
88
+ * Default display language of cli
89
+ *
90
+ * Can be 'zh-cn' or 'en-us'
91
+ *
92
+ * @default 'en-us'
93
+ */
94
+ lang?: Lang;
31
95
  }
32
96
  //#endregion
33
97
  //#region src/index.d.ts
package/dist/index.js CHANGED
@@ -1,61 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { cac } from "cac";
3
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
4
  import process$1 from "node:process";
4
5
  import { loadConfig } from "c12";
5
- import { readFileSync } from "node:fs";
6
+ import { bgRed, green, red, yellow } from "kolorist";
6
7
  import path, { join, posix } from "node:path";
7
8
  import enquirer from "enquirer";
8
- import { bgRed, green, red, yellow } from "kolorist";
9
9
  import { rimraf } from "rimraf";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import { glob } from "tinyglobby";
12
- import { existsSync } from "fs";
12
+ import { existsSync as existsSync$1 } from "fs";
13
13
  import { join as join$1 } from "path";
14
14
  import { generateChangelog, generateTotalChangelog } from "@soybeanjs/changelog";
15
15
  import { versionBump } from "bumpp";
16
+ import { consola } from "consola";
16
17
  //#region package.json
17
- var version = "1.7.4";
18
- //#endregion
19
- //#region src/config/index.ts
20
- const defaultOptions = {
21
- cwd: process$1.cwd(),
22
- cleanupDirs: [
23
- "**/dist",
24
- "**/package-lock.json",
25
- "**/yarn.lock",
26
- "**/pnpm-lock.yaml",
27
- "**/node_modules",
28
- "!node_modules/**"
29
- ],
30
- ncuCommandArgs: [],
31
- changelogOptions: {},
32
- gitCommitVerifyIgnores: [
33
- /^((Merge pull request)|(Merge (.*?) into (.*?)|(Merge branch (.*?)))(?:\r?\n)*$)/m,
34
- /^(Merge tag (.*?))(?:\r?\n)*$/m,
35
- /^(R|r)evert (.*)/,
36
- /^(amend|fixup|squash)!/,
37
- /^(Merged (.*?)(in|into) (.*)|Merged PR (.*): (.*))/,
38
- /^Merge remote-tracking branch(\s*)(.*)/,
39
- /^Automatic merge(.*)/,
40
- /^Auto-merged (.*?) into (.*)/
41
- ]
42
- };
43
- async function loadCliOptions(overrides, cwd = process$1.cwd()) {
44
- const { config } = await loadConfig({
45
- name: "soybean",
46
- defaults: defaultOptions,
47
- overrides,
48
- cwd,
49
- packageJson: true
50
- });
51
- return config;
52
- }
53
- //#endregion
54
- //#region src/shared/index.ts
55
- async function execCommand(cmd, args, options) {
56
- const { execa } = await import("execa");
57
- return ((await execa(cmd, args, options))?.stdout)?.trim() || "";
58
- }
18
+ var version = "1.8.0";
59
19
  //#endregion
60
20
  //#region src/locales/index.ts
61
21
  const locales = {
@@ -129,21 +89,125 @@ const locales = {
129
89
  }
130
90
  };
131
91
  //#endregion
92
+ //#region src/config/index.ts
93
+ const defaultGitCommitVerifyIgnores = [
94
+ /^((Merge pull request)|(Merge (.*?) into (.*?)|(Merge branch (.*?)))(?:\r?\n)*$)/m,
95
+ /^(Merge tag (.*?))(?:\r?\n)*$/m,
96
+ /^(R|r)evert (.*)/,
97
+ /^(amend|fixup|squash)!/,
98
+ /^(Merged (.*?)(in|into) (.*)|Merged PR (.*): (.*))/,
99
+ /^Merge remote-tracking branch(\s*)(.*)/,
100
+ /^Automatic merge(.*)/,
101
+ /^Auto-merged (.*?) into (.*)/
102
+ ];
103
+ const defaultOptions = {
104
+ cwd: process$1.cwd(),
105
+ cleanupDirs: [
106
+ "**/dist",
107
+ "**/package-lock.json",
108
+ "**/yarn.lock",
109
+ "**/pnpm-lock.yaml",
110
+ "**/node_modules",
111
+ "!node_modules/**"
112
+ ],
113
+ ncuCommandArgs: [],
114
+ changelogOptions: {},
115
+ gitCommitVerifyIgnores: defaultGitCommitVerifyIgnores,
116
+ gitCommit: {
117
+ typesAppend: true,
118
+ scopesAppend: true
119
+ },
120
+ lang: "en-us"
121
+ };
122
+ function mergeCommitItems(defaults, custom, append = true) {
123
+ if (!custom || custom.length === 0) return defaults;
124
+ if (!append) return custom;
125
+ const existing = new Map(defaults);
126
+ for (const [key, value] of custom) existing.set(key, value);
127
+ return Array.from(existing.entries());
128
+ }
129
+ function resolveGitCommitConfig(config, lang) {
130
+ const gitCommitConfig = config.gitCommit || {};
131
+ const defaultLocale = locales[lang] || locales["en-us"];
132
+ const defaultTypes = defaultLocale.gitCommitTypes;
133
+ const defaultScopes = defaultLocale.gitCommitScopes;
134
+ return {
135
+ types: mergeCommitItems(defaultTypes, gitCommitConfig.types, gitCommitConfig.typesAppend !== false),
136
+ scopes: mergeCommitItems(defaultScopes, gitCommitConfig.scopes, gitCommitConfig.scopesAppend !== false),
137
+ typesAppend: gitCommitConfig.typesAppend !== false,
138
+ scopesAppend: gitCommitConfig.scopesAppend !== false
139
+ };
140
+ }
141
+ function readGlobalConfig$1() {
142
+ const globalConfigPath = getGlobalConfigPath();
143
+ if (!existsSync(globalConfigPath)) return {};
144
+ try {
145
+ const content = readFileSync(globalConfigPath, "utf8");
146
+ return JSON.parse(content);
147
+ } catch {
148
+ return {};
149
+ }
150
+ }
151
+ function isPlainObject(value) {
152
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof RegExp) && !(value instanceof Date);
153
+ }
154
+ function deepMerge(target, source) {
155
+ const result = { ...target };
156
+ for (const key of Object.keys(source)) {
157
+ const sourceVal = source[key];
158
+ const targetVal = result[key];
159
+ if (sourceVal !== void 0) if (isPlainObject(sourceVal) && isPlainObject(targetVal)) result[key] = deepMerge(targetVal, sourceVal);
160
+ else result[key] = sourceVal;
161
+ }
162
+ return result;
163
+ }
164
+ async function loadCliOptions(overrides, cwd = process$1.cwd()) {
165
+ const { config: projectConfig } = await loadConfig({
166
+ name: "soybean",
167
+ defaults: {},
168
+ overrides,
169
+ cwd,
170
+ packageJson: true,
171
+ rcFile: false
172
+ });
173
+ const globalConfig = readGlobalConfig$1();
174
+ let mergedConfig = deepMerge({ ...defaultOptions }, globalConfig);
175
+ mergedConfig = deepMerge(mergedConfig, projectConfig);
176
+ const resolvedConfig = mergedConfig;
177
+ if (resolvedConfig.gitCommitVerifyIgnores) resolvedConfig.gitCommitVerifyIgnores = [...defaultGitCommitVerifyIgnores, ...resolvedConfig.gitCommitVerifyIgnores.filter((item) => !defaultGitCommitVerifyIgnores.some((def) => def.toString() === item.toString()))];
178
+ const lang = resolvedConfig.lang || "en-us";
179
+ resolvedConfig.gitCommit = resolveGitCommitConfig(resolvedConfig, lang);
180
+ resolvedConfig.lang = lang;
181
+ return resolvedConfig;
182
+ }
183
+ function getGlobalConfigPath() {
184
+ return `${process$1.env.HOME || process$1.env.USERPROFILE || "."}/.soybeanrc`;
185
+ }
186
+ //#endregion
187
+ //#region src/shared/index.ts
188
+ async function execCommand(cmd, args, options) {
189
+ const { execa } = await import("execa");
190
+ return ((await execa(cmd, args, options))?.stdout)?.trim() || "";
191
+ }
192
+ //#endregion
132
193
  //#region src/command/git-commit.ts
133
194
  /**
134
195
  * Git commit with Conventional Commits standard
135
196
  *
136
- * @param lang
197
+ * @param options
137
198
  */
138
- async function gitCommit(lang = "en-us") {
139
- const { gitCommitMessages, gitCommitTypes, gitCommitScopes } = locales[lang];
140
- const typesChoices = gitCommitTypes.map(([value, msg]) => {
199
+ async function gitCommit(options = {}) {
200
+ const lang = options.lang || "en-us";
201
+ const { gitCommitMessages } = locales[lang];
202
+ const types = options.types || locales[lang].gitCommitTypes;
203
+ const scopes = options.scopes || locales[lang].gitCommitScopes;
204
+ const typesChoices = types.map(([value, msg]) => {
141
205
  return {
142
206
  name: value,
143
207
  message: `${`${value}:`.padEnd(12)}${msg}`
144
208
  };
145
209
  });
146
- const scopesChoices = gitCommitScopes.map(([value, msg]) => ({
210
+ const scopesChoices = scopes.map(([value, msg]) => ({
147
211
  name: value,
148
212
  message: `${value.padEnd(30)} (${msg})`
149
213
  }));
@@ -257,7 +321,7 @@ async function resolveDefaultNcuArgs(cwd = process$1.cwd()) {
257
321
  //#endregion
258
322
  //#region src/command/changelog.ts
259
323
  async function genChangelog(options, total = false) {
260
- const hasChangelog = existsSync(join$1(process.cwd(), "CHANGELOG.md"));
324
+ const hasChangelog = existsSync$1(join$1(process.cwd(), "CHANGELOG.md"));
261
325
  if (total) await generateTotalChangelog(options);
262
326
  else await generateChangelog(options);
263
327
  if (!hasChangelog) await execCommand("git", ["add", "CHANGELOG.md"]);
@@ -275,15 +339,54 @@ async function release(execute = "pnpm soy changelog", push = true) {
275
339
  });
276
340
  }
277
341
  //#endregion
342
+ //#region src/command/config.ts
343
+ function readGlobalConfig() {
344
+ const filePath = getGlobalConfigPath();
345
+ if (!existsSync(filePath)) return {};
346
+ try {
347
+ const content = readFileSync(filePath, "utf8");
348
+ return JSON.parse(content);
349
+ } catch {
350
+ consola.warn(`Failed to parse global config at ${filePath}, will create new one.`);
351
+ return {};
352
+ }
353
+ }
354
+ function writeGlobalConfig(config) {
355
+ writeFileSync(getGlobalConfigPath(), JSON.stringify(config, null, 2), "utf8");
356
+ }
357
+ async function configSet(options) {
358
+ const config = readGlobalConfig();
359
+ if (options.lang) {
360
+ if (options.lang !== "zh-cn" && options.lang !== "en-us") {
361
+ consola.error(`Invalid language: ${options.lang}. Supported values: 'zh-cn', 'en-us'`);
362
+ return;
363
+ }
364
+ config.lang = options.lang;
365
+ writeGlobalConfig(config);
366
+ consola.success(`Default language set to ${green(options.lang)}`);
367
+ consola.info(`Config file: ${yellow(getGlobalConfigPath())}`);
368
+ }
369
+ }
370
+ async function configGet() {
371
+ const config = await loadCliOptions();
372
+ consola.log("\nCurrent configuration:");
373
+ consola.log(` ${green("lang")}: ${config.lang}`);
374
+ consola.log(` ${green("cwd")}: ${config.cwd}`);
375
+ consola.log(` ${green("global config")}: ${getGlobalConfigPath()}\n`);
376
+ }
377
+ async function configPath() {
378
+ consola.log(getGlobalConfigPath());
379
+ }
380
+ //#endregion
278
381
  //#region src/index.ts
279
382
  async function setupCli() {
280
383
  const cliOptions = await loadCliOptions();
281
384
  const cli = cac("soybean");
282
- cli.version(version).option("-e, --execute [command]", "Execute additional command after bumping and before git commit. Defaults to 'pnpm soy changelog'").option("-p, --push", "Indicates whether to push the git commit and tag").option("-t, --total", "Generate changelog by total tags").option("-c, --cleanupDir <dir>", "The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use \",\" to separate them").option("-l, --lang <lang>", "display lang of cli", {
283
- default: "en-us",
385
+ cli.version(version).option("-e, --execute [command]", "Execute additional command after bumping and before git commit. Defaults to 'pnpm soy changelog'").option("-p, --push", "Indicates whether to push the git commit and tag").option("-t, --total", "Generate changelog by total tags").option("-c, --cleanupDir <dir>", "The glob pattern of dirs to cleanup, If not set, it will use the default value, Multiple values use \",\" to separate them").option("-l, --lang <lang>", `display lang of cli (default: ${cliOptions.lang})`, {
386
+ default: cliOptions.lang,
284
387
  type: [String]
285
388
  }).help();
286
- const commands = {
389
+ const simpleCommands = {
287
390
  cleanup: {
288
391
  desc: "delete dirs: node_modules, dist, etc.",
289
392
  action: async (args) => {
@@ -307,13 +410,17 @@ async function setupCli() {
307
410
  "git-commit": {
308
411
  desc: "git commit, generate commit message which match Conventional Commits standard",
309
412
  action: async (args) => {
310
- await gitCommit(args?.lang);
413
+ await gitCommit({
414
+ lang: args?.lang || cliOptions.lang,
415
+ types: cliOptions.gitCommit?.types,
416
+ scopes: cliOptions.gitCommit?.scopes
417
+ });
311
418
  }
312
419
  },
313
420
  "git-commit-verify": {
314
421
  desc: "verify git commit message, make sure it match Conventional Commits standard",
315
422
  action: async (args) => {
316
- await gitCommitVerify(args?.lang, cliOptions.gitCommitVerifyIgnores);
423
+ await gitCommitVerify(args?.lang || cliOptions.lang, cliOptions.gitCommitVerifyIgnores);
317
424
  }
318
425
  },
319
426
  changelog: {
@@ -329,7 +436,24 @@ async function setupCli() {
329
436
  }
330
437
  }
331
438
  };
332
- for await (const [command, { desc, action }] of Object.entries(commands)) cli.command(command, desc).action(action);
439
+ for (const [cmdName, { desc, action }] of Object.entries(simpleCommands)) cli.command(cmdName, desc).action(action);
440
+ cli.command("config <cmd>", "manage cli configuration (set|get|path)").option("--set-lang <lang>", "Set default language (zh-cn or en-us)").action(async (cmd, options) => {
441
+ switch (cmd) {
442
+ case "set":
443
+ await configSet({ lang: options.setLang });
444
+ break;
445
+ case "get":
446
+ await configGet();
447
+ break;
448
+ case "path":
449
+ await configPath();
450
+ break;
451
+ default:
452
+ console.error(`Unknown config subcommand: ${cmd}`);
453
+ console.log("Available subcommands: set, get, path");
454
+ process.exit(1);
455
+ }
456
+ });
333
457
  cli.parse();
334
458
  }
335
459
  setupCli();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soybeanjs/cli",
3
- "version": "1.7.4",
3
+ "version": "1.8.0",
4
4
  "description": "SoybeanJS's command line tools",
5
5
  "homepage": "https://github.com/soybeanjs/cli",
6
6
  "bugs": {
@@ -37,7 +37,7 @@
37
37
  "registry": "https://registry.npmjs.org/"
38
38
  },
39
39
  "dependencies": {
40
- "@soybeanjs/changelog": "^0.4.7",
40
+ "@soybeanjs/changelog": "^0.5.2",
41
41
  "bumpp": "^12.0.0",
42
42
  "c12": "^3.3.4",
43
43
  "cac": "^7.0.0",