@varlet/release 2.0.1 → 2.1.1

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
@@ -28,90 +28,156 @@ pnpm add @varlet/release -D
28
28
 
29
29
  ## Usage
30
30
 
31
- ### Core Workflow
31
+ ### Features Overview
32
32
 
33
- When executing `vr release`, the following sequence of lifecycles occurs automatically:
33
+ - [release](#release) - Automatically complete the standard workflow from version modification to publishing and creating git tags.
34
+ - [publish](#publish) - Execute the npm publish process independently, usually suitable for CI/CD environments.
35
+ - [changelog](#changelog) - Automatically generate formatted changelogs based on Git Commit conventions.
36
+ - [commit-lint](#commit-lint) - Validate whether the Git Commit Message adheres to specifications, helping teams unify commit formats.
37
+ - [lockfile-check](#lockfile-check) - Check the status of the project's lockfile and provide dependency update mechanisms when changes occur.
34
38
 
35
- 1. Select/Confirm the **version** to publish interactively
36
- 2. Execute the user-defined `task` function (optional, e.g., to rebuild projects based on the new version)
37
- 3. Update the `package.json` **version** programmatically
38
- 4. Generate the **Changelog**
39
- 5. **Git Commit** & **Git Tag**
40
- 6. **Publish** to npm
39
+ ---
41
40
 
42
- ### Using Command
41
+ ### release
42
+
43
+ **Description**: The core functional collection for package release, integrating all release preparation and subsequent operations.
44
+
45
+ **Use cases**: Used when a new version needs to be released and all workspace changes have been committed. It guides through the publication via an intuitive command-line interaction.
46
+
47
+ **Core Workflow**:
48
+
49
+ 1. Interactively prompt and confirm the new version number (automatically calculate patch, minor, major upgrades).
50
+ 2. Execute the user-customized `task` function (e.g., modifying files, bundling assets).
51
+ 3. Automatically update the version number in the project's `package.json`.
52
+ 4. Generate the `Changelog` for the corresponding version.
53
+ 5. Automatically complete the Git commit and create a new version Tag.
54
+ 6. Publish the updated packages to npm.
55
+
56
+ **CLI Commands**:
57
+
58
+ _Flags Reference_:
59
+
60
+ ```text
61
+ Usage: vr release [flags...]
62
+
63
+ Flags:
64
+ -r, --remote <string> Remote repository name
65
+ -s, --skip-npm-publish Skip npm publish
66
+ --skip-changelog Skip generating changelog
67
+ --skip-git-tag Skip git tag
68
+ -t, --npm-tag <string> npm tag
69
+ -c, --check-remote-version Check remote version
70
+ ```
71
+
72
+ _Example_:
43
73
 
44
74
  ```shell
45
- # Release all packages and run the full workflow
75
+ # Release all packages and execute the full workflow
46
76
  npx vr release
47
77
 
48
- # Specify remote name
78
+ # Specify remote repository name (default origin)
49
79
  npx vr release -r origin
50
- # or
51
- npx vr release --remote origin
52
80
 
53
- # Just generate changelogs
54
- npx vr changelog
81
+ # Skip npm publishing
82
+ npx vr release -s
83
+ # Skip generating changelog
84
+ npx vr release --skip-changelog
85
+ # Check remote version, interrupt execution if the identical version already exists
86
+ npx vr release -c
87
+ ```
55
88
 
56
- # Specify changelog filename
57
- npx vr changelog -f changelog.md
58
- # or
59
- npx vr changelog --file changelog.md
89
+ **Node API**:
90
+
91
+ ```typescript
92
+ import { release } from '@varlet/release'
93
+
94
+ release({
95
+ remote?: string // Remote repository name, defaults to 'origin'
96
+ npmTag?: string // NPM tag to publish, such as 'next', 'alpha'
97
+ cwd?: string // Working directory, defaults to process.cwd()
98
+ skipNpmPublish?: boolean // Whether to skip the npm publish process
99
+ skipChangelog?: boolean // Whether to skip changelog generation
100
+ skipGitTag?: boolean // Whether to skip git tag creation
101
+ checkRemoteVersion?: boolean // Whether to check remote version to avoid conflicts
102
+ task?(newVersion: string, oldVersion: string): Promise<void> // Custom task executed during the release
103
+ })
104
+ ```
60
105
 
61
- # Lint commit message
62
- npx vr commit-lint -p .git/COMMIT_EDITMSG
106
+ _Example: Add custom handling logic_
63
107
 
64
- # Publish to npm, which can be called in the ci environment
65
- npx vr publish
108
+ ```javascript
109
+ import { release } from '@varlet/release'
66
110
 
67
- # Check if lockfile has been updated
68
- npx vr lockfile-sync-check
111
+ async function task(newVersion, oldVersion) {
112
+ // Execute building or file writing operations here
113
+ await doBuild()
114
+ }
69
115
 
70
- # Auto install dependencies if lockfile changed
71
- npx vr lockfile-sync-check -i
116
+ release({ task })
72
117
  ```
73
118
 
74
- ### Git Hooks Integration (Best Practice)
119
+ ---
75
120
 
76
- It is highly recommended to use `commit-lint` with `simple-git-hooks` or `husky` in `package.json` to automatically check developers' commit messages before committing:
121
+ ### publish
77
122
 
78
- ```json
79
- {
80
- "simple-git-hooks": {
81
- "commit-msg": "npx vr commit-lint -p $1"
82
- }
83
- }
84
- ```
123
+ **Description**: Publish the package independently to the npm registry.
85
124
 
86
- ### Configuration
125
+ **Use cases**: Applicable in scenarios where manual version selection, changelog generation, or git tags are not needed, often used in CI/CD pipelines to trigger automated publication based on specific processes.
87
126
 
88
- #### release
127
+ **Core Workflow**: Read the version number from the current package.json and run the corresponding publish process.
89
128
 
90
- ```
91
- Usage: vr release [flags...]
129
+ **CLI Commands**:
130
+
131
+ _Flags Reference_:
132
+
133
+ ```text
134
+ Usage: vr publish [flags...]
92
135
 
93
136
  Flags:
94
- -r, --remote <string> Remote name
95
- -s, --skip-npm-publish Skip npm publish
96
- --skip-changelog Skip generate changelog
97
- --skip-git-tag Skip git tag
98
- -t, --npm-tag <string> Npm tag
99
137
  -c, --check-remote-version Check remote version
138
+ -t, --npm-tag <string> npm tag
100
139
  ```
101
140
 
102
- #### publish
141
+ _Example_:
103
142
 
104
- ```
105
- Usage: vr publish [flags...]
143
+ ```shell
144
+ # Publish directly to npm
145
+ npx vr publish
106
146
 
107
- Flags:
108
- -c, --check-remote-version Check remote version
109
- -t, --npm-tag <string> Npm tag
147
+ # Check if the same version already exists due to network or other reasons, and abort if so
148
+ npx vr publish -c
149
+ # Specify the npm dist-tag
150
+ npx vr publish -t alpha
110
151
  ```
111
152
 
112
- #### changelog
153
+ **Node API**:
113
154
 
155
+ ```typescript
156
+ import { publish } from '@varlet/release'
157
+
158
+ publish({
159
+ preRelease?: boolean // Pre-release indicator, will add the '--tag alpha' option
160
+ checkRemoteVersion?: boolean // Check if the same version exists on the remote npm before publishing
161
+ npmTag?: string // NPM tag to publish
162
+ cwd?: string // Working directory, defaults to process.cwd()
163
+ })
114
164
  ```
165
+
166
+ ---
167
+
168
+ ### changelog
169
+
170
+ **Description**: Automatically generate Markdown-formatted changelogs based on standard Commit history.
171
+
172
+ **Use cases**: Useful for updating the `CHANGELOG.md` file independently without triggering the full release process.
173
+
174
+ **Core Workflow**: Traverse the Git commit history and format the output classified by predefined conventional commit rules (e.g., feat, fix).
175
+
176
+ **CLI Commands**:
177
+
178
+ _Flags Reference_:
179
+
180
+ ```text
115
181
  Usage: vr changelog [flags...]
116
182
 
117
183
  Flags:
@@ -119,52 +185,144 @@ Flags:
119
185
  -f, --file <string> Changelog filename
120
186
  ```
121
187
 
122
- #### commit-lint
188
+ _Example_:
123
189
 
190
+ ```shell
191
+ # Generate changelogs for all history and output as CHANGELOG.md in the current directory
192
+ npx vr changelog
193
+
194
+ # Specify the generated changelog filename
195
+ npx vr changelog -f my-changelog.md
196
+ # Limit the range of release versions to generate changelogs for (0 means all)
197
+ npx vr changelog -c 0
198
+ ```
199
+
200
+ **Node API**:
201
+
202
+ ```typescript
203
+ import { changelog } from '@varlet/release'
204
+
205
+ changelog({
206
+ cwd?: string // Working directory, defaults to process.cwd()
207
+ releaseCount?: number // Number of recent releases to include in the log, defaults to 0 (all)
208
+ file?: string // Output changelog filename, defaults to 'CHANGELOG.md'
209
+ showTypes?: string[] // Commit types to display, defaults to ['feat', 'fix', 'perf', 'revert', 'refactor']
210
+ outputUnreleased?: boolean // Whether to output unreleased changes
211
+ writerOpt?: object // Specific configuration for conventional-changelog-writer
212
+ })
124
213
  ```
214
+
215
+ ---
216
+
217
+ ### commit-lint
218
+
219
+ **Description**: Validate Git commit message formats.
220
+
221
+ **Use cases**: Used in combination with `git hooks` to enforce high-quality commit descriptions, ensuring the quality of the changelog.
222
+
223
+ **Core Workflow**: Read the commit file. If it matches the configured regex, the process continues; otherwise, it prints specific failure messages and aborts the commit.
224
+
225
+ **CLI Commands**:
226
+
227
+ _Flags Reference_:
228
+
229
+ ```text
125
230
  Usage: vr commit-lint [flags...]
126
231
 
127
232
  Flags:
128
233
  -p, --commit-message-path <string> Git commit message path
129
- -r, --commit-message-re <string> Validate the regular of whether the commit message passes
130
- -e, --error-message <string> Validation failed to display error messages
131
- -w, --warning-message <string> Validation failed to display warning messages
234
+ -r, --commit-message-re <string> Validate the regex for commit message
235
+ -e, --error-message <string> Error message displayed on validation failure
236
+ -w, --warning-message <string> Warning message displayed on validation failure
132
237
  ```
133
238
 
134
- #### lockfile-sync-check
239
+ _Example_:
135
240
 
241
+ ```shell
242
+ # Check if the commit message at the given path is standard
243
+ npx vr commit-lint -p .git/COMMIT_EDITMSG
244
+
245
+ # Customize regex validation and prompt message
246
+ npx vr commit-lint -p .git/COMMIT_EDITMSG -r "^feat: .*" -e "Commit validation failed"
136
247
  ```
137
- Usage: vr lockfile-sync-check [flags...]
248
+
249
+ _It is recommended to integrate with `simple-git-hooks` or `husky` in `package.json`:_
250
+
251
+ ```json
252
+ {
253
+ "simple-git-hooks": {
254
+ "commit-msg": "npx vr commit-lint -p $1"
255
+ }
256
+ }
257
+ ```
258
+
259
+ **Node API**:
260
+
261
+ ```typescript
262
+ import { commitLint } from '@varlet/release'
263
+
264
+ commitLint({
265
+ commitMessagePath: string // Required: Path to Git commit message file
266
+ commitMessageRe?: string | RegExp // Regex to validate the commit message format
267
+ errorMessage?: string // Error message printed upon failure
268
+ warningMessage?: string // Supplemental warning information printed upon failure
269
+ })
270
+ ```
271
+
272
+ ---
273
+
274
+ ### lockfile-check
275
+
276
+ **Description**: Detect and visually output in the console whether the lockfile of frontend dependencies has been modified.
277
+
278
+ **Use cases**: Recommended to use after Git operations such as pulling updates (`git pull`), switching branches (`git checkout`), or merging code. It helps detect if upstream dependency lockfiles (like `pnpm-lock.yaml`) have changed. If a change is detected, you can invoke a package manager's installation command through specific options to synchronize the local environment with upstream instantly, preventing obscure bugs caused by outdated dependencies.
279
+
280
+ **Core Workflow**: Execute a Git diff comparing the project's lockfile (e.g. `pnpm-lock.yaml` or corresponding environment lockfile) from the original HEAD. Print its modification status in the console. Furthermore, trigger the package manager to reinstall dependencies to sync with upstream if directed by the command options.
281
+
282
+ **CLI Commands**:
283
+
284
+ _Flags Reference_:
285
+
286
+ ```text
287
+ Usage: vr lockfile-check [flags...]
138
288
 
139
289
  Flags:
140
290
  -m, --package-manager <string> Package manager (npm, yarn, pnpm), default pnpm
141
291
  -i, --install Auto install dependencies if lockfile changed
142
292
  ```
143
293
 
144
- ### Node API Custom Handle
294
+ _Example_:
145
295
 
146
- You can write your own release scripts with Internal Node.js API instead of CLI.
147
-
148
- #### Example
296
+ ```shell
297
+ # Check the synchronization status of the current lockfile
298
+ npx vr lockfile-check
149
299
 
150
- ```js
151
- import { changelog, release } from '@varlet/release'
300
+ # Check current status, forcefully run installation to sync dependencies if updates exist
301
+ npx vr lockfile-check -i
152
302
 
153
- // Run the core release workflow directly
154
- release()
303
+ # Specify other package managers for checking (defaults to pnpm)
304
+ npx vr lockfile-check -m npm
155
305
  ```
156
306
 
157
- You can pass in a custom `task` function that will be called after the package version is updated but before the remaining publish steps.
158
-
159
- ```js
160
- import { changelog, release } from '@varlet/release'
307
+ _It is also recommended to integrate with `simple-git-hooks` or `husky` in `package.json` (e.g. trigger checks and installations automatically during the `post-merge` or `post-checkout` hooks):_
161
308
 
162
- async function task(newVersion, oldVersion) {
163
- await doSomething1()
164
- await doSomething2()
309
+ ```json
310
+ {
311
+ "simple-git-hooks": {
312
+ "post-merge": "npx vr lockfile-check -i"
313
+ }
165
314
  }
315
+ ```
166
316
 
167
- release({ task })
317
+ **Node API**:
318
+
319
+ ```typescript
320
+ import { lockfileCheck } from '@varlet/release'
321
+
322
+ lockfileCheck({
323
+ packageManager?: 'npm' | 'yarn' | 'pnpm' // Choose package manager, defaults to 'pnpm'
324
+ install?: boolean // Whether to automatically run install if lockfile is out of sync
325
+ })
168
326
  ```
169
327
 
170
328
  ## License
package/README.zh-CN.md CHANGED
@@ -28,80 +28,109 @@ pnpm add @varlet/release -D
28
28
 
29
29
  ## 使用
30
30
 
31
- ### 核心工作流
31
+ ### 功能概览
32
32
 
33
- 执行 `vr release` 时,背后会自动完成以下流程(保障每一步的严谨性):
33
+ - [release](#release) - 自动完成从版本号变更到发布、打标签的标准工作流。
34
+ - [publish](#publish) - 单独执行 npm 发布流程,通常适用于 CI/CD 环境。
35
+ - [changelog](#changelog) - 根据 Git Commit 规范自动生成格式化的变更日志。
36
+ - [commit-lint](#commit-lint) - 校验 Git Commit Message 是否符合规范,帮助团队统一提交格式。
37
+ - [lockfile-check](#lockfile-check) - 检查项目 lockfile 状态并在变化时提供更新依赖机制。
34
38
 
35
- 1. 交互式选择/确认要发布的版本号
36
- 2. 执行用户自定义的额外 `task` 操作(可选,如重新构建以注入新版本号)
37
- 3. 自动修改工程中的版本号信息
38
- 4. 自动生成符合规范的 Changelog
39
- 5. Git 提交 (Commit) 与打标签 (Tag)
40
- 6. 发布至 npm
39
+ ---
41
40
 
42
- ### 命令行使用
41
+ ### release
42
+
43
+ **作用**:包版本发布的核心功能集合,集成和串联了所有的发布准备及后续操作。
44
+
45
+ **使用场景**:在项目需要发布新版本且工作区变更已全部提交时使用。通过直观的命令行交互完成发布。
46
+
47
+ **核心流程**:
48
+
49
+ 1. 交互式提示并确认发布版本号(自动计算 patch、minor 等升级维度)。
50
+ 2. 执行用户自定义的 `task` 函数(例如修改文件,打包构建)。
51
+ 3. 自动更新项目中 `package.json` 的版本号。
52
+ 4. 生成对应该版本的 `Changelog`。
53
+ 5. 自动完成 Git 提交动作并且打上新版本标签 (Tag)。
54
+ 6. 自动将更新后的包发布至 npm。
55
+
56
+ **CMD 命令**:
57
+
58
+ _标志参考_:
59
+
60
+ ```text
61
+ 用法: vr release [标志...]
62
+
63
+ 标志:
64
+ -r, --remote <string> 远程仓库名称
65
+ -s, --skip-npm-publish 跳过 npm 发布
66
+ --skip-changelog 跳过生成变更日志
67
+ --skip-git-tag 跳过 git tag
68
+ -t, --npm-tag <string> npm tag
69
+ -c, --check-remote-version 检查远程版本
70
+ ```
71
+
72
+ _使用示例_:
43
73
 
44
74
  ```shell
45
75
  # 发布所有包并执行完整工作流程
46
76
  npx vr release
47
77
 
48
- # 指定远程仓库名称
78
+ # 指定远程仓库名称 (默认 origin)
49
79
  npx vr release -r origin
50
- # 或
51
- npx vr release --remote origin
52
80
 
53
- # 仅生成变更日志
54
- npx vr changelog
81
+ # 跳过 npm 发布
82
+ npx vr release -s
83
+ # 跳过生成变更日志
84
+ npx vr release --skip-changelog
85
+ # 检查远程版本,若已存在相同版本则中断执行
86
+ npx vr release -c
87
+ ```
55
88
 
56
- # 指定变更日志文件名
57
- npx vr changelog -f changelog.md
58
- # 或
59
- npx vr changelog --file changelog.md
89
+ **Node 调用**:
90
+
91
+ ```typescript
92
+ import { release } from '@varlet/release'
93
+
94
+ release({
95
+ remote?: string // 远程仓库名称,默认为 'origin'
96
+ npmTag?: string // 发布的 npm tag,如 'next'、'alpha'
97
+ cwd?: string // 工作目录,默认为 process.cwd()
98
+ skipNpmPublish?: boolean // 是否跳过 npm publish 过程
99
+ skipChangelog?: boolean // 是否跳过生成变更日志
100
+ skipGitTag?: boolean // 是否跳过构建 git tag 过程
101
+ checkRemoteVersion?: boolean // 是否检查远程版本,保证不发生版本冲突
102
+ task?(newVersion: string, oldVersion: string): Promise<void> // 发布过程中执行的自定义任务
103
+ })
104
+ ```
60
105
 
61
- # 检测 commit message 是否符合规范
62
- npx vr commit-lint -p .git/COMMIT_EDITMSG
106
+ _例:增加自定义处理逻辑_
63
107
 
64
- # 发布到 npm(通常在 CI/CD 中执行)
65
- npx vr publish
108
+ ```javascript
109
+ import { release } from '@varlet/release'
66
110
 
67
- # 检查 lockfile 是否已更新
68
- npx vr lockfile-sync-check
111
+ async function task(newVersion, oldVersion) {
112
+ // 在此处执行构建或写入文件的操作
113
+ await doBuild()
114
+ }
69
115
 
70
- # 如果 lockfile 发生变化则自动安装依赖
71
- npx vr lockfile-sync-check -i
116
+ release({ task })
72
117
  ```
73
118
 
74
- ### Git Hooks 集成 (推荐最佳实践)
75
-
76
- 建议在 `package.json` 中配合 `simple-git-hooks` 或 `husky` 使用 `commit-lint`,在开发者提交代码时自动触发校验:
119
+ ---
77
120
 
78
- ```json
79
- {
80
- "simple-git-hooks": {
81
- "commit-msg": "npx vr commit-lint -p $1"
82
- }
83
- }
84
- ```
121
+ ### publish
85
122
 
86
- ### 配置参考
123
+ **作用**:单独将包发布至 npm 仓库。
87
124
 
88
- #### release
125
+ **使用场景**:适用于无需手动选择版本、生成 Changelog 或打 Git Tag 的场景,常用于在 CI/CD 流水线中针对特定过程触发自动化发布。
89
126
 
90
- ```
91
- 用法: vr release [标志...]
127
+ **核心流程**:读取当前 package.json 中的版本号,运行对应的 publish 流程。
92
128
 
93
- 标志:
94
- -r, --remote <string> 远程仓库名称
95
- -s, --skip-npm-publish 跳过 npm 发布
96
- --skip-changelog 跳过生成变更日志
97
- --skip-git-tag 跳过 git tag
98
- -t, --npm-tag <string> npm tag
99
- -c, --check-remote-version 检查远程版本
100
- ```
129
+ **CMD 命令**:
101
130
 
102
- #### publish
131
+ _标志参考_:
103
132
 
104
- ```
133
+ ```text
105
134
  用法: vr publish [标志...]
106
135
 
107
136
  标志:
@@ -109,9 +138,46 @@ npx vr lockfile-sync-check -i
109
138
  -t, --npm-tag <string> npm tag
110
139
  ```
111
140
 
112
- #### changelog
141
+ _使用示例_:
142
+
143
+ ```shell
144
+ # 直接发布到 npm
145
+ npx vr publish
146
+
147
+ # 检查由于网络等原因是否已存在相同版本,存在则放弃发布
148
+ npx vr publish -c
149
+ # 指定 npm 的 dist-tag
150
+ npx vr publish -t alpha
151
+ ```
152
+
153
+ **Node 调用**:
113
154
 
155
+ ```typescript
156
+ import { publish } from '@varlet/release'
157
+
158
+ publish({
159
+ preRelease?: boolean // 预发布标示,将添加 '--tag alpha' 选项
160
+ checkRemoteVersion?: boolean // 发布前检查远程 npm 上是否已存在相同版本
161
+ npmTag?: string // 发布的 npm tag
162
+ cwd?: string // 工作目录,默认为 process.cwd()
163
+ })
114
164
  ```
165
+
166
+ ---
167
+
168
+ ### changelog
169
+
170
+ **作用**:基于规范的 Commit 历史自动生成 Markdown 格式的变更日志。
171
+
172
+ **使用场景**:单独更新 `CHANGELOG.md` 记录,单点生成所需日志。
173
+
174
+ **核心流程**:遍历 Git 提交历史,依据预设的 conventional commit 规则分类(如 feat、fix 等),格式化输出。
175
+
176
+ **CMD 命令**:
177
+
178
+ _标志参考_:
179
+
180
+ ```text
115
181
  用法: vr changelog [标志...]
116
182
 
117
183
  标志:
@@ -119,9 +185,48 @@ npx vr lockfile-sync-check -i
119
185
  -f, --file <string> 变更日志文件名
120
186
  ```
121
187
 
122
- #### commit-lint
188
+ _使用示例_:
189
+
190
+ ```shell
191
+ # 生成所有历史的变更日志并在当前目录输出为 CHANGELOG.md
192
+ npx vr changelog
193
+
194
+ # 指定生成的变更日志文件名
195
+ npx vr changelog -f my-changelog.md
196
+ # 限定发布版本的范围数量以生成变更日志 (0 为全量)
197
+ npx vr changelog -c 0
198
+ ```
199
+
200
+ **Node 调用**:
201
+
202
+ ```typescript
203
+ import { changelog } from '@varlet/release'
123
204
 
205
+ changelog({
206
+ cwd?: string // 工作目录,默认为 process.cwd()
207
+ releaseCount?: number // 输出日志涉及的最近发布的版本数量,默认为 0(全部)
208
+ file?: string // 输出的日志文件名,默认为 'CHANGELOG.md'
209
+ showTypes?: string[] // 显示的 commit 类型,默认 ['feat', 'fix', 'perf', 'revert', 'refactor']
210
+ outputUnreleased?: boolean // 是否输出 unreleased 版本变更
211
+ writerOpt?: object // conventional-changelog-writer 具体配置参数
212
+ })
124
213
  ```
214
+
215
+ ---
216
+
217
+ ### commit-lint
218
+
219
+ **作用**:校验 Git 提交信息格式。
220
+
221
+ **使用场景**:结合 `git hooks` 一同工作,强制保障书写高质量的提交说明以保证 Changelog 质量。
222
+
223
+ **核心流程**:读取提交文件,若是符合配置的正则格式则通过处理,否则打印具体的失败信息报错,并终止提交。
224
+
225
+ **CMD 命令**:
226
+
227
+ _标志参考_:
228
+
229
+ ```text
125
230
  用法: vr commit-lint [标志...]
126
231
 
127
232
  标志:
@@ -131,40 +236,93 @@ npx vr lockfile-sync-check -i
131
236
  -w, --warning-message <string> 验证失败时显示的警告信息
132
237
  ```
133
238
 
134
- #### lockfile-sync-check
239
+ _使用示例_:
240
+
241
+ ```shell
242
+ # 检测指路径的 commit message 是否符合规范
243
+ npx vr commit-lint -p .git/COMMIT_EDITMSG
135
244
 
245
+ # 定制指定的校验正则表达式和提示信息
246
+ npx vr commit-lint -p .git/COMMIT_EDITMSG -r "^feat: .*" -e "提交校验失败"
136
247
  ```
137
- 用法: vr lockfile-sync-check [标志...]
248
+
249
+ _建议配合并在 `package.json` 中的 `simple-git-hooks` 或 `husky` 一同集成运作:_
250
+
251
+ ```json
252
+ {
253
+ "simple-git-hooks": {
254
+ "commit-msg": "npx vr commit-lint -p $1"
255
+ }
256
+ }
257
+ ```
258
+
259
+ **Node 调用**:
260
+
261
+ ```typescript
262
+ import { commitLint } from '@varlet/release'
263
+
264
+ commitLint({
265
+ commitMessagePath: string // 必选:Git commit message 文件路径
266
+ commitMessageRe?: string | RegExp // 验证 msg 格式的正则表达式
267
+ errorMessage?: string // 验证失败时打印的提示文本
268
+ warningMessage?: string // 验证失败时打印的补充警告文档链接
269
+ })
270
+ ```
271
+
272
+ ---
273
+
274
+ ### lockfile-check
275
+
276
+ **作用**:检测并在控制台直观地输出前端依赖包的 lockfile 文件是否发生变更。
277
+
278
+ **使用场景**:通常在进行 `git 操作` (如 `git pull`拉取最新代码、`git checkout`切换分支、或合并代码) 之后使用。它能帮助你检测上游的依赖锁文件(如 `pnpm-lock.yaml`)是否发生了变动。如果检测到有变更,可以通过可选操作直接执行 install 安装命令,从而确保本地环境快速与上游依赖保持一致,避免因依赖版本陈旧导致的疑难 bug。
279
+
280
+ **核心流程**:比对项目原始游标的锁文件(如 pnpm-lock.yaml 或对应环境的 lockfile)的 Git diff,在控制台输出其是否存在变动;并根据指令决定是否随后触发包管理器的依赖重装程序以同步上游。
281
+
282
+ **CMD 命令**:
283
+
284
+ _标志参考_:
285
+
286
+ ```text
287
+ 用法: vr lockfile-check [标志...]
138
288
 
139
289
  标志:
140
290
  -m, --package-manager <string> 包管理器 (npm, yarn, pnpm),默认 pnpm
141
291
  -i, --install 如果 lockfile 发生变化则自动安装依赖
142
292
  ```
143
293
 
144
- ### Node API 自定义处理
145
-
146
- 除了命令行,你也可以使用 Node.js API 结合内部逻辑编写发布脚本。
294
+ _使用示例_:
147
295
 
148
- #### 示例代码
296
+ ```shell
297
+ # 检查当前 lockfile 的同步状态
298
+ npx vr lockfile-check
149
299
 
150
- ```js
151
- import { changelog, release } from '@varlet/release'
300
+ # 检查当前状态,若存在更新则强制运行安装命令同步依赖
301
+ npx vr lockfile-check -i
152
302
 
153
- // 执行默认发布流程
154
- release()
303
+ # 指定其他包管理器进行检查(默认使用 pnpm)
304
+ npx vr lockfile-check -m npm
155
305
  ```
156
306
 
157
- 你可以传入一个 `task` 函数,在版本号变更之后、发布到 npm 等后续操作之前被调用。
158
-
159
- ```js
160
- import { changelog, release } from '@varlet/release'
307
+ _建议配合并在 `package.json` 中的 `simple-git-hooks` 或 `husky` 一同集成运作(例如在拉取代码的 `post-merge` 或 `post-checkout` 阶段自动触发检查与安装):_
161
308
 
162
- async function task(newVersion, oldVersion) {
163
- await doSomething1()
164
- await doSomething2()
309
+ ```json
310
+ {
311
+ "simple-git-hooks": {
312
+ "post-merge": "npx vr lockfile-check -i"
313
+ }
165
314
  }
315
+ ```
166
316
 
167
- release({ task })
317
+ **Node 调用**:
318
+
319
+ ```typescript
320
+ import { lockfileCheck } from '@varlet/release'
321
+
322
+ lockfileCheck({
323
+ packageManager?: 'npm' | 'yarn' | 'pnpm' // 选择包管理器,默认为 'pnpm'
324
+ install?: boolean // 检测到 lock 不同步时是否自动运行对应的 install 重新安装
325
+ })
168
326
  ```
169
327
 
170
328
  ## 许可证
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { c as release, i as lockfileSyncCheck, p as commitLint, s as publish, u as changelog } from "./src-CVV7ij5v.js";
2
+ import { c as release, i as lockfileCheck, p as commitLint, s as publish, u as changelog } from "./src-DJEBh4nv.js";
3
3
  import { cli, command } from "cleye";
4
4
  //#endregion
5
5
  //#region src/cli.ts
6
6
  cli({
7
7
  name: "vr",
8
- version: "2.0.1",
8
+ version: "2.1.1",
9
9
  commands: [
10
10
  command({
11
11
  name: "release",
@@ -102,7 +102,7 @@ cli({
102
102
  help: { description: "Lint commit message" }
103
103
  }, (argv) => commitLint(argv.flags)),
104
104
  command({
105
- name: "lockfile-sync-check",
105
+ name: "lockfile-check",
106
106
  flags: {
107
107
  packageManager: {
108
108
  type: String,
@@ -117,7 +117,7 @@ cli({
117
117
  }
118
118
  },
119
119
  help: { description: "Check if lockfile has been updated and optionally install dependencies" }
120
- }, (argv) => lockfileSyncCheck(argv.flags))
120
+ }, (argv) => lockfileCheck(argv.flags))
121
121
  ]
122
122
  });
123
123
  //#endregion
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Commit, Params } from "conventional-changelog";
1
+ import { ConventionalChangelog } from "standard-changelog";
2
2
 
3
3
  //#region src/release.d.ts
4
4
  interface PackageJsonConfig {
@@ -38,20 +38,34 @@ interface ReleaseCommandOptions {
38
38
  declare function release(options: ReleaseCommandOptions): Promise<void>;
39
39
  //#endregion
40
40
  //#region src/changelog.d.ts
41
- interface ChangelogCommandOptions {
41
+ declare const COMMIT_TYPE_MAP: {
42
+ readonly feat: "Features";
43
+ readonly fix: "Bug Fixes";
44
+ readonly perf: "Performance Improvements";
45
+ readonly revert: "Reverts";
46
+ readonly refactor: "Refactoring";
47
+ readonly docs: "Documentation";
48
+ readonly style: "Styles";
49
+ readonly test: "Tests";
50
+ readonly build: "Build System";
51
+ readonly ci: "Continuous Integration";
52
+ };
53
+ interface ChangelogOptions {
42
54
  cwd?: string;
43
- file?: string;
44
55
  releaseCount?: number;
45
- mainTemplate?: string;
46
- transformCommit?: (commit: Commit, params: Params) => Partial<Commit> | Promise<Partial<Commit> | null> | null;
56
+ file?: string;
57
+ showTypes?: (keyof typeof COMMIT_TYPE_MAP)[];
58
+ outputUnreleased?: boolean;
59
+ writerOpt?: Parameters<ConventionalChangelog["writer"]>[0];
47
60
  }
48
61
  declare function changelog({
49
62
  cwd,
50
63
  releaseCount,
51
64
  file,
52
- mainTemplate,
53
- transformCommit
54
- }?: ChangelogCommandOptions): Promise<void>;
65
+ showTypes,
66
+ outputUnreleased,
67
+ writerOpt
68
+ }?: ChangelogOptions): Promise<void>;
55
69
  //#endregion
56
70
  //#region src/commitLint.d.ts
57
71
  declare const COMMIT_HEADER_RE: RegExp;
@@ -66,15 +80,15 @@ interface CommitLintCommandOptions {
66
80
  }
67
81
  declare function commitLint(options: CommitLintCommandOptions): void;
68
82
  //#endregion
69
- //#region src/lockfileSyncCheck.d.ts
83
+ //#region src/lockfileCheck.d.ts
70
84
  type PackageManager = "npm" | "yarn" | "pnpm";
71
- interface LockfileSyncCheckOptions {
85
+ interface LockfileCheckOptions {
72
86
  packageManager?: PackageManager;
73
87
  install?: boolean;
74
88
  }
75
89
  declare function getLockfilePath(packageManager: PackageManager): string;
76
90
  declare function checkLockfileSync(packageManager: PackageManager): Promise<boolean>;
77
91
  declare function installDependencies(packageManager: PackageManager): Promise<void>;
78
- declare function lockfileSyncCheck(options?: LockfileSyncCheckOptions): Promise<void>;
92
+ declare function lockfileCheck(options?: LockfileCheckOptions): Promise<void>;
79
93
  //#endregion
80
- export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, ChangelogCommandOptions, CommitLintCommandOptions, LockfileSyncCheckOptions, PackageManager, PublishCommandOptions, ReleaseCommandOptions, changelog, checkLockfileSync, commitLint, getCommitMessage, getLockfilePath, getPackageJsons, installDependencies, isSameVersion, isVersionCommitMessage, lockfileSyncCheck, publish, release, updateVersion };
94
+ export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, ChangelogOptions, CommitLintCommandOptions, LockfileCheckOptions, PackageManager, PublishCommandOptions, ReleaseCommandOptions, changelog, checkLockfileSync, commitLint, getCommitMessage, getLockfilePath, getPackageJsons, installDependencies, isSameVersion, isVersionCommitMessage, lockfileCheck, publish, release, updateVersion };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as getPackageJsons, c as release, d as COMMIT_HEADER_RE, f as COMMIT_MESSAGE_RE, h as isVersionCommitMessage, i as lockfileSyncCheck, l as updateVersion, m as getCommitMessage, n as getLockfilePath, o as isSameVersion, p as commitLint, r as installDependencies, s as publish, t as checkLockfileSync, u as changelog } from "./src-CVV7ij5v.js";
2
- export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, changelog, checkLockfileSync, commitLint, getCommitMessage, getLockfilePath, getPackageJsons, installDependencies, isSameVersion, isVersionCommitMessage, lockfileSyncCheck, publish, release, updateVersion };
1
+ import { a as getPackageJsons, c as release, d as COMMIT_HEADER_RE, f as COMMIT_MESSAGE_RE, h as isVersionCommitMessage, i as lockfileCheck, l as updateVersion, m as getCommitMessage, n as getLockfilePath, o as isSameVersion, p as commitLint, r as installDependencies, s as publish, t as checkLockfileSync, u as changelog } from "./src-DJEBh4nv.js";
2
+ export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, changelog, checkLockfileSync, commitLint, getCommitMessage, getLockfilePath, getPackageJsons, installDependencies, isSameVersion, isVersionCommitMessage, lockfileCheck, publish, release, updateVersion };
@@ -5,7 +5,7 @@ import { cancel, confirm, isCancel, select, spinner } from "@clack/prompts";
5
5
  import { logger } from "rslog";
6
6
  import semver from "semver";
7
7
  import { x } from "tinyexec";
8
- import { ConventionalChangelog } from "conventional-changelog";
8
+ import { StandardChangelog } from "standard-changelog";
9
9
  //#region src/commitLint.ts
10
10
  const COMMIT_HEADER_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(?:\(([^)]+)\))?(!)?:\s(.+)$/;
11
11
  const COMMIT_MESSAGE_RE = new RegExp(COMMIT_HEADER_RE.source.replace(/\$$/, "") + "(?:\\n[\\s\\S]+)?$");
@@ -39,9 +39,7 @@ Allowed types:
39
39
  - revert
40
40
  - merge
41
41
  - wip
42
-
43
- Commit message reference: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y
44
- 参考阮一峰Commit message编写指南: https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html`;
42
+ `;
45
43
  function isVersionCommitMessage(message) {
46
44
  return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
47
45
  }
@@ -76,13 +74,14 @@ const COMMIT_TYPE_MAP = {
76
74
  build: "Build System",
77
75
  ci: "Continuous Integration"
78
76
  };
79
- const ALWAYS_SHOW_TYPES = new Set([
77
+ const ALWAYS_SHOW_TYPES = [
80
78
  "feat",
81
79
  "fix",
82
80
  "perf",
83
81
  "revert",
84
82
  "refactor"
85
- ]);
83
+ ];
84
+ const BREAKING_CHANGE_RE = /BREAKING CHANGES?:\s*([\s\S]+)/;
86
85
  const MAIN_TEMPLATE = `{{> header}}
87
86
 
88
87
  {{> footer}}
@@ -111,6 +110,15 @@ function linkify(text, context, issues) {
111
110
  if (context.host) result = result.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => username.includes("/") ? `@${username}` : `[@${username}](${context.host}/${username})`);
112
111
  return result;
113
112
  }
113
+ function extractBreakingText(commit) {
114
+ const body = typeof commit.body === "string" ? commit.body : "";
115
+ const footer = typeof commit.footer === "string" ? commit.footer : "";
116
+ const match = BREAKING_CHANGE_RE.exec(`${footer}\n${body}`);
117
+ if (match?.[1]) return match[1].trim();
118
+ if (typeof commit.subject === "string" && commit.subject) return commit.subject;
119
+ if (typeof commit.header === "string" && commit.header) return commit.header;
120
+ return "";
121
+ }
114
122
  function tryParseHeader(commit) {
115
123
  if (typeof commit.header !== "string") return null;
116
124
  const match = COMMIT_HEADER_RE.exec(commit.header.trim());
@@ -124,24 +132,19 @@ function tryParseHeader(commit) {
124
132
  }
125
133
  function processBreakingChanges(commit, context, issues) {
126
134
  let discard = true;
127
- commit.notes = [];
128
- const getCommitHashLink = () => {
129
- if (!commit.hash) return "";
130
- const shortHash = commit.hash.substring(0, 7);
131
- const repoUrl = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
132
- return repoUrl ? ` ([${shortHash}](${repoUrl}/commit/${commit.hash}))` : ` (${shortHash})`;
133
- };
134
- const hashLink = getCommitHashLink();
135
+ commit.notes.forEach((note) => {
136
+ note.title = "BREAKING CHANGES";
137
+ discard = false;
138
+ });
139
+ const hadBreakingNotes = commit.notes.length > 0;
135
140
  const addBreakingNote = () => {
136
- let text = linkify(typeof commit.subject === "string" && commit.subject ? commit.subject : typeof commit.header === "string" && commit.header ? commit.header : "", context, issues) + hashLink;
137
- if (commit.body) {
138
- const indentedBody = linkify(commit.body, context, issues).split("\n").map((line) => line.trim() ? ` ${line}` : "").join("\n");
139
- text += `\n\n${indentedBody}`;
141
+ if (!hadBreakingNotes) {
142
+ const text = linkify(extractBreakingText(commit), context, issues);
143
+ commit.notes.push({
144
+ title: "BREAKING CHANGES",
145
+ text
146
+ });
140
147
  }
141
- commit.notes.push({
142
- title: "BREAKING CHANGES",
143
- text
144
- });
145
148
  discard = false;
146
149
  };
147
150
  const parsed = tryParseHeader(commit);
@@ -157,51 +160,42 @@ function processBreakingChanges(commit, context, issues) {
157
160
  }
158
161
  return discard;
159
162
  }
160
- function mapCommitType(commit, discard) {
161
- if (commit.revert) {
162
- commit.type = "Reverts";
163
- return true;
164
- }
163
+ function mapCommitType(commit, discard, showTypes) {
164
+ if (commit.revert) commit.type = "revert";
165
+ if (!commit.type) return false;
165
166
  const mapped = COMMIT_TYPE_MAP[commit.type];
166
167
  if (mapped) {
167
- if (ALWAYS_SHOW_TYPES.has(commit.type) || !discard) {
168
+ if (showTypes.includes(commit.type) || !discard) {
168
169
  commit.type = mapped;
169
170
  return true;
170
171
  }
171
172
  }
172
173
  return !discard;
173
174
  }
174
- function createDefaultTransformCommit() {
175
- return (commit, params) => {
176
- const context = {
177
- host: params.context?.host,
178
- owner: params.context?.owner,
179
- repository: typeof params.repository === "object" && params.repository !== null ? params.repository.project : void 0,
180
- repoUrl: params.context?.repoUrl
181
- };
182
- const issues = [];
183
- const mutableCommit = { ...commit };
184
- if (mutableCommit.notes) mutableCommit.notes = [...mutableCommit.notes];
185
- if (!mapCommitType(mutableCommit, processBreakingChanges(mutableCommit, context, issues))) return null;
186
- if (mutableCommit.scope === "*") mutableCommit.scope = "";
187
- if (typeof mutableCommit.hash === "string") mutableCommit.shortHash = mutableCommit.hash.substring(0, 7);
188
- if (typeof mutableCommit.subject === "string") mutableCommit.subject = linkify(mutableCommit.subject, context, issues);
189
- if (mutableCommit.references) mutableCommit.references = mutableCommit.references.filter((ref) => !issues.includes(ref.issue));
190
- return mutableCommit;
175
+ function createDefaultWriterOpts({ showTypes }) {
176
+ return {
177
+ mainTemplate: MAIN_TEMPLATE,
178
+ transform(_commit, context) {
179
+ const commit = JSON.parse(JSON.stringify(_commit));
180
+ const issues = [];
181
+ if (!mapCommitType(commit, processBreakingChanges(commit, context, issues), showTypes)) return null;
182
+ if (commit.scope === "*") commit.scope = "";
183
+ if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
184
+ if (typeof commit.subject === "string") commit.subject = linkify(commit.subject, context, issues);
185
+ commit.references = commit.references.filter((ref) => !issues.includes(ref.issue));
186
+ return commit;
187
+ }
191
188
  };
192
189
  }
193
- function changelog({ cwd = process.cwd(), releaseCount = 0, file = "CHANGELOG.md", mainTemplate = MAIN_TEMPLATE, transformCommit = createDefaultTransformCommit() } = {}) {
190
+ function changelog({ cwd = process.cwd(), releaseCount = 0, file = "CHANGELOG.md", showTypes = ALWAYS_SHOW_TYPES, outputUnreleased, writerOpt } = {}) {
194
191
  const s = spinner();
195
192
  s.start("Generating changelog");
193
+ const defaultWriterOpts = writerOpt || createDefaultWriterOpts({ showTypes });
196
194
  return new Promise((resolve$1) => {
197
- new ConventionalChangelog(cwd).readPackage().loadPreset("angular").options({
195
+ new StandardChangelog(cwd).readPackage().options({
198
196
  releaseCount,
199
- transformCommit,
200
- outputUnreleased: true
201
- }).writer({
202
- mainTemplate,
203
- transform: (commit) => commit
204
- }).writeStream().pipe(createWriteStream(resolve(cwd, file))).on("close", () => {
197
+ outputUnreleased
198
+ }).writer(defaultWriterOpts).writeStream().pipe(createWriteStream(resolve(cwd, file))).on("close", () => {
205
199
  s.stop("Changelog generated successfully!");
206
200
  resolve$1();
207
201
  });
@@ -357,10 +351,10 @@ function computeExpectVersion(currentVersion, type) {
357
351
  }
358
352
  async function getReleaseType(currentVersion) {
359
353
  return unwrapPromptResult(await select({
360
- message: "Please select release type",
354
+ message: `Please select release type, current version ${currentVersion}`,
361
355
  options: RELEASE_TYPES.map((type) => {
362
356
  return {
363
- label: `${type} (${currentVersion} → ${computeExpectVersion(currentVersion, type)})`,
357
+ label: `${type} (${computeExpectVersion(currentVersion, type)})`,
364
358
  value: type
365
359
  };
366
360
  })
@@ -420,7 +414,7 @@ async function release(options) {
420
414
  }
421
415
  }
422
416
  //#endregion
423
- //#region src/lockfileSyncCheck.ts
417
+ //#region src/lockfileCheck.ts
424
418
  function getLockfilePath(packageManager) {
425
419
  switch (packageManager) {
426
420
  case "pnpm": return "pnpm-lock.yaml";
@@ -461,10 +455,18 @@ async function installDependencies(packageManager) {
461
455
  throw error;
462
456
  }
463
457
  }
464
- async function lockfileSyncCheck(options = {}) {
458
+ async function lockfileCheck(options = {}) {
465
459
  try {
466
460
  const pkgManager = options.packageManager || "pnpm";
467
461
  const installFlag = options.install || false;
462
+ if (![
463
+ "npm",
464
+ "yarn",
465
+ "pnpm"
466
+ ].includes(pkgManager)) {
467
+ logger.error(`Unsupported package manager: ${pkgManager}`);
468
+ return;
469
+ }
468
470
  if (await checkLockfileSync(pkgManager)) {
469
471
  logger.warn("Lockfile has been updated!");
470
472
  if (installFlag) await installDependencies(pkgManager);
@@ -474,4 +476,4 @@ async function lockfileSyncCheck(options = {}) {
474
476
  }
475
477
  }
476
478
  //#endregion
477
- export { getPackageJsons as a, release as c, COMMIT_HEADER_RE as d, COMMIT_MESSAGE_RE as f, isVersionCommitMessage as h, lockfileSyncCheck as i, updateVersion as l, getCommitMessage as m, getLockfilePath as n, isSameVersion as o, commitLint as p, installDependencies as r, publish as s, checkLockfileSync as t, changelog as u };
479
+ export { getPackageJsons as a, release as c, COMMIT_HEADER_RE as d, COMMIT_MESSAGE_RE as f, isVersionCommitMessage as h, lockfileCheck as i, updateVersion as l, getCommitMessage as m, getLockfilePath as n, isSameVersion as o, commitLint as p, installDependencies as r, publish as s, checkLockfileSync as t, changelog as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@varlet/release",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "publish all packages, generate changelogs and check commit messages",
5
5
  "keywords": [
6
6
  "changelog",
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@clack/prompts": "^1.2.0",
34
34
  "cleye": "^2.3.0",
35
- "conventional-changelog": "^7.2.0",
36
35
  "rslog": "^2.1.1",
37
36
  "semver": "^7.7.4",
37
+ "standard-changelog": "^7.0.1",
38
38
  "tinyexec": "^1.1.1"
39
39
  },
40
40
  "devDependencies": {