@varlet/release 1.0.2 → 1.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 +52 -70
- package/README.zh-CN.md +62 -80
- package/dist/cli.js +3 -6
- package/dist/index.d.ts +9 -2
- package/dist/index.js +2 -431
- package/dist/src-BWrnR5U-.js +432 -0
- package/package.json +7 -11
package/README.md
CHANGED
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
`Varlet Release` is a tool used for publishing all packages, generating change logs, and checking `commit messages`, relying on `pnpm`.
|
|
15
15
|
|
|
16
|
+
- 📦 **Out of the box**: Zero-configuration release experience
|
|
17
|
+
- 🤖 **Interactive CLI**: Friendly interactive terminal prompts
|
|
18
|
+
- 🛠 **Standardization**: Validates Git Commit messages and generates standard changelogs
|
|
19
|
+
- 🔗 **Extensibility**: Supports both CLI commands and Node.js API for deep customization
|
|
20
|
+
|
|
16
21
|
> `Varlet Release` requires `Node.js` ^20.19.0 || >=22.12.0 and `esm` only.
|
|
17
22
|
|
|
18
23
|
## Installation
|
|
@@ -23,10 +28,21 @@ pnpm add @varlet/release -D
|
|
|
23
28
|
|
|
24
29
|
## Usage
|
|
25
30
|
|
|
31
|
+
### Core Workflow
|
|
32
|
+
|
|
33
|
+
When executing `vr release`, the following sequence of lifecycles occurs automatically:
|
|
34
|
+
|
|
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
|
|
41
|
+
|
|
26
42
|
### Using Command
|
|
27
43
|
|
|
28
44
|
```shell
|
|
29
|
-
# Release all packages and
|
|
45
|
+
# Release all packages and run the full workflow
|
|
30
46
|
npx vr release
|
|
31
47
|
|
|
32
48
|
# Specify remote name
|
|
@@ -49,26 +65,38 @@ npx vr lint-commit -p .git/COMMIT_EDITMSG
|
|
|
49
65
|
npx vr publish
|
|
50
66
|
```
|
|
51
67
|
|
|
68
|
+
### Git Hooks Integration (Best Practice)
|
|
69
|
+
|
|
70
|
+
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:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"simple-git-hooks": {
|
|
75
|
+
"commit-msg": "npx vr lint-commit -p $1"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
52
80
|
### Configuration
|
|
53
81
|
|
|
54
82
|
#### release
|
|
55
83
|
|
|
56
|
-
| Params | Instructions |
|
|
57
|
-
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
-
| -r --remote \<remote\> | Specify remote name |
|
|
59
|
-
| -s --skip-npm-publish | Skip npm publish |
|
|
60
|
-
| -c --check-remote-version | Check if the remote version of the npm package is the same as the one you want to publish locally, if so, stop execution. |
|
|
61
|
-
| -sc --skip-changelog | Skip generate changelog |
|
|
62
|
-
| -sgt --skip-git-tag | Skip git tag |
|
|
63
|
-
| -nt --npm-tag \<npmTag\> | npm tag |
|
|
84
|
+
| Params | Instructions | Default |
|
|
85
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------- |
|
|
86
|
+
| -r --remote \<remote\> | Specify remote name | `origin` |
|
|
87
|
+
| -s --skip-npm-publish | Skip npm publish | `false` |
|
|
88
|
+
| -c --check-remote-version | Check if the remote version of the npm package is the same as the one you want to publish locally, if so, stop execution. | `false` |
|
|
89
|
+
| -sc --skip-changelog | Skip generate changelog | `false` |
|
|
90
|
+
| -sgt --skip-git-tag | Skip git tag | `false` |
|
|
91
|
+
| -nt --npm-tag \<npmTag\> | npm tag | `-` |
|
|
64
92
|
|
|
65
93
|
#### changelog
|
|
66
94
|
|
|
67
|
-
| Params | Instructions |
|
|
68
|
-
| ----------------------------------- | -------------------------- |
|
|
69
|
-
| -f --file \<filename\> | Specify changelog filename |
|
|
70
|
-
| -rc --releaseCount \<releaseCount\> | Release count |
|
|
71
|
-
| -p --preset \<preset\> | Specify changelog preset |
|
|
95
|
+
| Params | Instructions | Default |
|
|
96
|
+
| ----------------------------------- | -------------------------- | -------------- |
|
|
97
|
+
| -f --file \<filename\> | Specify changelog filename | `CHANGELOG.md` |
|
|
98
|
+
| -rc --releaseCount \<releaseCount\> | Release count | `0` |
|
|
99
|
+
| -p --preset \<preset\> | Specify changelog preset | `angular` |
|
|
72
100
|
|
|
73
101
|
#### lint-commit
|
|
74
102
|
|
|
@@ -81,28 +109,30 @@ npx vr publish
|
|
|
81
109
|
|
|
82
110
|
#### publish
|
|
83
111
|
|
|
84
|
-
| Params | Instructions |
|
|
85
|
-
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
86
|
-
| -c --check-remote-version | Detects whether the remote version of the npm package is the same as the package version to be published locally, and if it is, skip the release |
|
|
87
|
-
| -nt --npm-tag \<npmTag\> | npm tag |
|
|
112
|
+
| Params | Instructions | Default |
|
|
113
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
|
114
|
+
| -c --check-remote-version | Detects whether the remote version of the npm package is the same as the package version to be published locally, and if it is, skip the release | `false` |
|
|
115
|
+
| -nt --npm-tag \<npmTag\> | npm tag | `-` |
|
|
88
116
|
|
|
89
|
-
### Custom Handle
|
|
117
|
+
### Node API Custom Handle
|
|
118
|
+
|
|
119
|
+
You can write your own release scripts with Internal Node.js API instead of CLI.
|
|
90
120
|
|
|
91
121
|
#### Example
|
|
92
122
|
|
|
93
123
|
```js
|
|
94
124
|
import { changelog, release } from '@varlet/release'
|
|
95
125
|
|
|
96
|
-
//
|
|
126
|
+
// Run the core release workflow directly
|
|
97
127
|
release()
|
|
98
128
|
```
|
|
99
129
|
|
|
100
|
-
You can pass in a task that will be called
|
|
130
|
+
You can pass in a custom `task` function that will be called after the package version is updated but before the remaining publish steps.
|
|
101
131
|
|
|
102
132
|
```js
|
|
103
133
|
import { changelog, release } from '@varlet/release'
|
|
104
134
|
|
|
105
|
-
async function task() {
|
|
135
|
+
async function task(newVersion, oldVersion) {
|
|
106
136
|
await doSomething1()
|
|
107
137
|
await doSomething2()
|
|
108
138
|
}
|
|
@@ -110,54 +140,6 @@ async function task() {
|
|
|
110
140
|
release({ task })
|
|
111
141
|
```
|
|
112
142
|
|
|
113
|
-
#### Types
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
interface PublishCommandOptions {
|
|
117
|
-
preRelease?: boolean
|
|
118
|
-
checkRemoteVersion?: boolean
|
|
119
|
-
npmTag?: string
|
|
120
|
-
}
|
|
121
|
-
function publish({ preRelease, checkRemoteVersion, npmTag }: PublishCommandOptions): Promise<void>
|
|
122
|
-
function updateVersion(version: string): void
|
|
123
|
-
interface ReleaseCommandOptions {
|
|
124
|
-
remote?: string
|
|
125
|
-
skipNpmPublish?: boolean
|
|
126
|
-
skipChangelog?: boolean
|
|
127
|
-
skipGitTag?: boolean
|
|
128
|
-
npmTag?: string
|
|
129
|
-
task?(newVersion: string, oldVersion: string): Promise<void>
|
|
130
|
-
}
|
|
131
|
-
function release(options: ReleaseCommandOptions): Promise<void>
|
|
132
|
-
|
|
133
|
-
interface ChangelogCommandOptions {
|
|
134
|
-
file?: string
|
|
135
|
-
releaseCount?: number
|
|
136
|
-
preset?:
|
|
137
|
-
| 'angular'
|
|
138
|
-
| 'atom'
|
|
139
|
-
| 'codemirror'
|
|
140
|
-
| 'conventionalcommits'
|
|
141
|
-
| 'ember'
|
|
142
|
-
| 'eslint'
|
|
143
|
-
| 'express'
|
|
144
|
-
| 'jquery'
|
|
145
|
-
| 'jshint'
|
|
146
|
-
}
|
|
147
|
-
function changelog({ releaseCount, file, preset }?: ChangelogCommandOptions): Promise<void>
|
|
148
|
-
|
|
149
|
-
const COMMIT_MESSAGE_RE: RegExp
|
|
150
|
-
function isVersionCommitMessage(message: string): string | false | null
|
|
151
|
-
function getCommitMessage(commitMessagePath: string): string
|
|
152
|
-
interface CommitLintCommandOptions {
|
|
153
|
-
commitMessagePath: string
|
|
154
|
-
commitMessageRe?: string | RegExp
|
|
155
|
-
errorMessage?: string
|
|
156
|
-
warningMessage?: string
|
|
157
|
-
}
|
|
158
|
-
function commitLint(options: CommitLintCommandOptions): void
|
|
159
|
-
```
|
|
160
|
-
|
|
161
143
|
## License
|
|
162
144
|
|
|
163
145
|
[MIT](https://github.com/varletjs/release/blob/main/LICENSE)
|
package/README.zh-CN.md
CHANGED
|
@@ -6,14 +6,19 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/@varlet/release" target="_blank" rel="noopener noreferrer"><img src="https://badgen.net/npm/v/@varlet/release" alt="NPM Version" /></a>
|
|
9
|
-
<a href="https://github.com/
|
|
9
|
+
<a href="https://github.com/varletjs/release/blob/main/LICENSE" target="_blank" rel="noopener noreferrer"><img src="https://badgen.net/github/license/varletjs/release" alt="License" /></a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
## 介绍
|
|
13
13
|
|
|
14
|
-
`Varlet Release` 是一个用于发布所有包、生成变更日志和检测 `commit message`
|
|
14
|
+
`Varlet Release` 是一个用于发布所有包、生成变更日志和检测 `commit message` 的辅助工具,依赖于 `pnpm`。
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
- 📦 **开箱即用**:零配置的极简发布体验
|
|
17
|
+
- 🤖 **直观交互**:提供非常友好的交互式终端提示
|
|
18
|
+
- 🛠 **规范驱动**:自动校验 Git Commit 并生成标准 Changelog
|
|
19
|
+
- 🔗 **深度扩展**:支持命令行调用与 Node.js API 无缝扩展
|
|
20
|
+
|
|
21
|
+
> `Varlet Release` 需要 `Node.js` ^20.19.0 || >=22.12.0,并且仅支持 `esm`。
|
|
17
22
|
|
|
18
23
|
## 安装
|
|
19
24
|
|
|
@@ -23,15 +28,26 @@ pnpm add @varlet/release -D
|
|
|
23
28
|
|
|
24
29
|
## 使用
|
|
25
30
|
|
|
26
|
-
###
|
|
31
|
+
### 核心工作流
|
|
32
|
+
|
|
33
|
+
执行 `vr release` 时,背后会自动完成以下流程(保障每一步的严谨性):
|
|
34
|
+
|
|
35
|
+
1. 交互式选择/确认要发布的版本号
|
|
36
|
+
2. 执行用户自定义的额外 `task` 操作(可选,如重新构建以注入新版本号)
|
|
37
|
+
3. 自动修改工程中的版本号信息
|
|
38
|
+
4. 自动生成符合规范的 Changelog
|
|
39
|
+
5. Git 提交 (Commit) 与打标签 (Tag)
|
|
40
|
+
6. 发布至 npm
|
|
41
|
+
|
|
42
|
+
### 命令行使用
|
|
27
43
|
|
|
28
44
|
```shell
|
|
29
|
-
#
|
|
45
|
+
# 发布所有包并执行完整工作流程
|
|
30
46
|
npx vr release
|
|
31
47
|
|
|
32
48
|
# 指定远程仓库名称
|
|
33
49
|
npx vr release -r https://github.com/varletjs/varlet-release
|
|
34
|
-
#
|
|
50
|
+
# 或
|
|
35
51
|
npx vr release --remote https://github.com/varletjs/varlet-release
|
|
36
52
|
|
|
37
53
|
# 仅生成变更日志
|
|
@@ -39,36 +55,48 @@ npx vr changelog
|
|
|
39
55
|
|
|
40
56
|
# 指定变更日志文件名
|
|
41
57
|
npx vr changelog -f changelog.md
|
|
42
|
-
#
|
|
58
|
+
# 或
|
|
43
59
|
npx vr changelog --file changelog.md
|
|
44
60
|
|
|
45
|
-
# 检测 commit message
|
|
61
|
+
# 检测 commit message 是否符合规范
|
|
46
62
|
npx vr lint-commit -p .git/COMMIT_EDITMSG
|
|
47
63
|
|
|
48
|
-
# 发布到 npm
|
|
64
|
+
# 发布到 npm(通常在 CI/CD 中执行)
|
|
49
65
|
npx vr publish
|
|
50
66
|
```
|
|
51
67
|
|
|
52
|
-
###
|
|
68
|
+
### Git Hooks 集成 (推荐最佳实践)
|
|
69
|
+
|
|
70
|
+
建议在 `package.json` 中配合 `simple-git-hooks` 或 `husky` 使用 `commit-lint`,在开发者提交代码时自动触发校验:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"simple-git-hooks": {
|
|
75
|
+
"commit-msg": "npx vr lint-commit -p $1"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 配置参考
|
|
53
81
|
|
|
54
82
|
#### release
|
|
55
83
|
|
|
56
|
-
| 参数 | 说明 |
|
|
57
|
-
| ------------------------- | ----------------------------------------------------------------------- |
|
|
58
|
-
| -r --remote \<remote\> | 指定远程仓库名称 |
|
|
59
|
-
| -s --skip-npm-publish | 跳过 npm 发布 |
|
|
60
|
-
| -c --check-remote-version | 检测 npm 包的远程版本是否与要在本地发布的包版本相同,如果是,则停止执行 |
|
|
61
|
-
| -sc --skip-changelog | 跳过生成变更日志 |
|
|
62
|
-
| -sgt --skip-git-tag | 跳过 git tag |
|
|
63
|
-
| -nt --npm-tag \<npmTag\> | npm tag |
|
|
84
|
+
| 参数 | 说明 | 默认值 |
|
|
85
|
+
| ------------------------- | ----------------------------------------------------------------------- | -------- |
|
|
86
|
+
| -r --remote \<remote\> | 指定远程仓库名称 | `origin` |
|
|
87
|
+
| -s --skip-npm-publish | 跳过 npm 发布 | `false` |
|
|
88
|
+
| -c --check-remote-version | 检测 npm 包的远程版本是否与要在本地发布的包版本相同,如果是,则停止执行 | `false` |
|
|
89
|
+
| -sc --skip-changelog | 跳过生成变更日志 | `false` |
|
|
90
|
+
| -sgt --skip-git-tag | 跳过 git tag | `false` |
|
|
91
|
+
| -nt --npm-tag \<npmTag\> | npm tag | `-` |
|
|
64
92
|
|
|
65
93
|
#### changelog
|
|
66
94
|
|
|
67
|
-
| 参数 | 说明 |
|
|
68
|
-
| ----------------------------------- | ------------------ |
|
|
69
|
-
| -f --file \<filename\> | 指定变更日志文件名 |
|
|
70
|
-
| -rc --releaseCount \<releaseCount\> | 发布数量 |
|
|
71
|
-
| -p --preset \<preset\> | 指定变更预设 |
|
|
95
|
+
| 参数 | 说明 | 默认值 |
|
|
96
|
+
| ----------------------------------- | ------------------ | -------------- |
|
|
97
|
+
| -f --file \<filename\> | 指定变更日志文件名 | `CHANGELOG.md` |
|
|
98
|
+
| -rc --releaseCount \<releaseCount\> | 发布数量 | `0` |
|
|
99
|
+
| -p --preset \<preset\> | 指定变更预设 | `angular` |
|
|
72
100
|
|
|
73
101
|
#### lint-commit
|
|
74
102
|
|
|
@@ -81,28 +109,30 @@ npx vr publish
|
|
|
81
109
|
|
|
82
110
|
#### publish
|
|
83
111
|
|
|
84
|
-
| 参数 | 说明 |
|
|
85
|
-
| ------------------------- | --------------------------------------------------------------------- |
|
|
86
|
-
| -c --check-remote-version | 检测npm包的远程版本是否与要在本地发布的包版本相同,如果是,则跳过发布 |
|
|
87
|
-
| -nt --npm-tag \<npmTag\> | npm tag |
|
|
112
|
+
| 参数 | 说明 | 默认值 |
|
|
113
|
+
| ------------------------- | --------------------------------------------------------------------- | ------- |
|
|
114
|
+
| -c --check-remote-version | 检测npm包的远程版本是否与要在本地发布的包版本相同,如果是,则跳过发布 | `false` |
|
|
115
|
+
| -nt --npm-tag \<npmTag\> | npm tag | `-` |
|
|
88
116
|
|
|
89
|
-
### 自定义处理
|
|
117
|
+
### Node API 自定义处理
|
|
90
118
|
|
|
91
|
-
|
|
119
|
+
除了命令行,你也可以使用 Node.js API 结合内部逻辑编写发布脚本。
|
|
120
|
+
|
|
121
|
+
#### 示例代码
|
|
92
122
|
|
|
93
123
|
```js
|
|
94
124
|
import { changelog, release } from '@varlet/release'
|
|
95
125
|
|
|
96
|
-
//
|
|
126
|
+
// 执行默认发布流程
|
|
97
127
|
release()
|
|
98
128
|
```
|
|
99
129
|
|
|
100
|
-
你可以传入一个 `task
|
|
130
|
+
你可以传入一个 `task` 函数,在版本号变更之后、发布到 npm 等后续操作之前被调用。
|
|
101
131
|
|
|
102
132
|
```js
|
|
103
133
|
import { changelog, release } from '@varlet/release'
|
|
104
134
|
|
|
105
|
-
async function task() {
|
|
135
|
+
async function task(newVersion, oldVersion) {
|
|
106
136
|
await doSomething1()
|
|
107
137
|
await doSomething2()
|
|
108
138
|
}
|
|
@@ -110,54 +140,6 @@ async function task() {
|
|
|
110
140
|
release({ task })
|
|
111
141
|
```
|
|
112
142
|
|
|
113
|
-
#### 类型
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
interface PublishCommandOptions {
|
|
117
|
-
preRelease?: boolean
|
|
118
|
-
checkRemoteVersion?: boolean
|
|
119
|
-
npmTag?: string
|
|
120
|
-
}
|
|
121
|
-
function publish({ preRelease, checkRemoteVersion, npmTag }: PublishCommandOptions): Promise<void>
|
|
122
|
-
function updateVersion(version: string): void
|
|
123
|
-
interface ReleaseCommandOptions {
|
|
124
|
-
remote?: string
|
|
125
|
-
skipNpmPublish?: boolean
|
|
126
|
-
skipChangelog?: boolean
|
|
127
|
-
skipGitTag?: boolean
|
|
128
|
-
npmTag?: string
|
|
129
|
-
task?(newVersion: string, oldVersion: string): Promise<void>
|
|
130
|
-
}
|
|
131
|
-
function release(options: ReleaseCommandOptions): Promise<void>
|
|
132
|
-
|
|
133
|
-
interface ChangelogCommandOptions {
|
|
134
|
-
file?: string
|
|
135
|
-
releaseCount?: number
|
|
136
|
-
preset?:
|
|
137
|
-
| 'angular'
|
|
138
|
-
| 'atom'
|
|
139
|
-
| 'codemirror'
|
|
140
|
-
| 'conventionalcommits'
|
|
141
|
-
| 'ember'
|
|
142
|
-
| 'eslint'
|
|
143
|
-
| 'express'
|
|
144
|
-
| 'jquery'
|
|
145
|
-
| 'jshint'
|
|
146
|
-
}
|
|
147
|
-
function changelog({ releaseCount, file, preset }?: ChangelogCommandOptions): Promise<void>
|
|
148
|
-
|
|
149
|
-
const COMMIT_MESSAGE_RE: RegExp
|
|
150
|
-
function isVersionCommitMessage(message: string): string | false | null
|
|
151
|
-
function getCommitMessage(commitMessagePath: string): string
|
|
152
|
-
interface CommitLintCommandOptions {
|
|
153
|
-
commitMessagePath: string
|
|
154
|
-
commitMessageRe?: string | RegExp
|
|
155
|
-
errorMessage?: string
|
|
156
|
-
warningMessage?: string
|
|
157
|
-
}
|
|
158
|
-
function commitLint(options: CommitLintCommandOptions): void
|
|
159
|
-
```
|
|
160
|
-
|
|
161
143
|
## 许可证
|
|
162
144
|
|
|
163
145
|
[MIT](https://github.com/varletjs/release/blob/main/LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { i as release, l as commitLint, o as changelog, r as publish } from "./src-BWrnR5U-.js";
|
|
3
3
|
import { Command } from "commander";
|
|
4
|
-
|
|
5
4
|
//#region package.json
|
|
6
|
-
var version = "1.0
|
|
7
|
-
|
|
5
|
+
var version = "1.1.0";
|
|
8
6
|
//#endregion
|
|
9
7
|
//#region src/cli.ts
|
|
10
8
|
const program = new Command();
|
|
@@ -14,6 +12,5 @@ program.command("publish").option("-c --check-remote-version", "Check remote ver
|
|
|
14
12
|
program.command("changelog").option("-rc --releaseCount <releaseCount>", "Release count").option("-f --file <file>", "Changelog filename").option("-p --preset <preset>", "Changelog preset").description("Generate changelog").action((options) => changelog(options));
|
|
15
13
|
program.command("commit-lint").option("-p --commitMessagePath <path>", "Git commit message path").option("-r --commitMessageRe <reg>", "Validate the regular of whether the commit message passes").option("-e --errorMessage <message>", "Validation failed to display error messages").option("-w --warningMessage <message>", "Validation failed to display warning messages").description("Lint commit message").action((option) => commitLint(option));
|
|
16
14
|
program.parse();
|
|
17
|
-
|
|
18
15
|
//#endregion
|
|
19
|
-
export {
|
|
16
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,14 @@ declare function publish({
|
|
|
12
12
|
checkRemoteVersion,
|
|
13
13
|
npmTag
|
|
14
14
|
}: PublishCommandOptions): Promise<void>;
|
|
15
|
-
declare function
|
|
15
|
+
declare function getPackageJsons(): {
|
|
16
|
+
filePath: string;
|
|
17
|
+
config: {
|
|
18
|
+
name: string;
|
|
19
|
+
version: string;
|
|
20
|
+
private: boolean;
|
|
21
|
+
};
|
|
22
|
+
}[];
|
|
16
23
|
declare function updateVersion(version: string): void;
|
|
17
24
|
interface ReleaseCommandOptions {
|
|
18
25
|
remote?: string;
|
|
@@ -52,4 +59,4 @@ interface CommitLintCommandOptions {
|
|
|
52
59
|
}
|
|
53
60
|
declare function commitLint(options: CommitLintCommandOptions): void;
|
|
54
61
|
//#endregion
|
|
55
|
-
export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, ChangelogCommandOptions, CommitLintCommandOptions, PublishCommandOptions, ReleaseCommandOptions, changelog, commitLint,
|
|
62
|
+
export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, ChangelogCommandOptions, CommitLintCommandOptions, PublishCommandOptions, ReleaseCommandOptions, changelog, commitLint, getCommitMessage, getPackageJsons, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
|
package/dist/index.js
CHANGED
|
@@ -1,431 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { cancel, confirm, isCancel, select, spinner } from "@clack/prompts";
|
|
4
|
-
import fse from "fs-extra";
|
|
5
|
-
import { logger } from "rslog";
|
|
6
|
-
import semver from "semver";
|
|
7
|
-
import { x } from "tinyexec";
|
|
8
|
-
import conventionalChangelog from "conventional-changelog";
|
|
9
|
-
|
|
10
|
-
//#region src/commitLint.ts
|
|
11
|
-
const { readFileSync } = fse;
|
|
12
|
-
const COMMIT_HEADER_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(?:\(([^)]+)\))?(!)?:\s(.+)$/;
|
|
13
|
-
const COMMIT_MESSAGE_RE = new RegExp(COMMIT_HEADER_RE.source.replace(/\$$/, "") + "(?:\\n[\\s\\S]+)?$");
|
|
14
|
-
const ERROR_MESSAGE = "Commit message invalid.";
|
|
15
|
-
const WARNING_MESSAGE = `\
|
|
16
|
-
The rules for commit messages are as follows
|
|
17
|
-
|
|
18
|
-
Example:
|
|
19
|
-
|
|
20
|
-
feat: add a new feature
|
|
21
|
-
feat(ui/button): add a new feature in the ui/button scope
|
|
22
|
-
|
|
23
|
-
fix: fix a bug
|
|
24
|
-
fix(ui/button): fix a bug in the ui/button scope
|
|
25
|
-
|
|
26
|
-
docs: fix an error in the documentation
|
|
27
|
-
docs(ui/button): fix a documentation error in the ui/button scope
|
|
28
|
-
|
|
29
|
-
Allowed types:
|
|
30
|
-
- fix
|
|
31
|
-
- feat
|
|
32
|
-
- docs
|
|
33
|
-
- perf
|
|
34
|
-
- test
|
|
35
|
-
- types
|
|
36
|
-
- style
|
|
37
|
-
- build
|
|
38
|
-
- chore
|
|
39
|
-
- release
|
|
40
|
-
- refactor
|
|
41
|
-
- revert
|
|
42
|
-
- merge
|
|
43
|
-
- wip
|
|
44
|
-
|
|
45
|
-
Commit message reference: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y
|
|
46
|
-
参考阮一峰Commit message编写指南: https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html`;
|
|
47
|
-
function isVersionCommitMessage(message) {
|
|
48
|
-
return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
|
|
49
|
-
}
|
|
50
|
-
function getCommitMessage(commitMessagePath) {
|
|
51
|
-
return readFileSync(commitMessagePath, "utf-8").trim();
|
|
52
|
-
}
|
|
53
|
-
function commitLint(options) {
|
|
54
|
-
const { commitMessagePath, commitMessageRe = COMMIT_MESSAGE_RE, errorMessage = ERROR_MESSAGE, warningMessage = WARNING_MESSAGE } = options;
|
|
55
|
-
if (!commitMessagePath) {
|
|
56
|
-
logger.error("commitMessagePath is required");
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
const commitMessage = getCommitMessage(commitMessagePath);
|
|
60
|
-
const isValidCommitMessage = new RegExp(commitMessageRe).test(commitMessage);
|
|
61
|
-
if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
|
|
62
|
-
logger.error(errorMessage);
|
|
63
|
-
logger.warn(warningMessage);
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
//#region src/changelog.ts
|
|
70
|
-
const { createWriteStream } = fse;
|
|
71
|
-
const COMMIT_TYPE_MAP = {
|
|
72
|
-
feat: "Features",
|
|
73
|
-
fix: "Bug Fixes",
|
|
74
|
-
perf: "Performance Improvements",
|
|
75
|
-
revert: "Reverts",
|
|
76
|
-
refactor: "Code Refactoring",
|
|
77
|
-
docs: "Documentation",
|
|
78
|
-
style: "Styles",
|
|
79
|
-
test: "Tests",
|
|
80
|
-
build: "Build System",
|
|
81
|
-
ci: "Continuous Integration"
|
|
82
|
-
};
|
|
83
|
-
const ALWAYS_SHOW_TYPES = new Set([
|
|
84
|
-
"feat",
|
|
85
|
-
"fix",
|
|
86
|
-
"perf",
|
|
87
|
-
"revert",
|
|
88
|
-
"refactor"
|
|
89
|
-
]);
|
|
90
|
-
const BREAKING_CHANGE_RE = /BREAKING CHANGES?:\s*([\s\S]+)/;
|
|
91
|
-
const MAIN_TEMPLATE = `{{> header}}
|
|
92
|
-
|
|
93
|
-
{{> footer}}
|
|
94
|
-
{{#each commitGroups}}
|
|
95
|
-
|
|
96
|
-
{{#if title}}
|
|
97
|
-
### {{title}}
|
|
98
|
-
|
|
99
|
-
{{/if}}
|
|
100
|
-
{{#each commits}}
|
|
101
|
-
{{> commit root=@root}}
|
|
102
|
-
{{/each}}
|
|
103
|
-
|
|
104
|
-
{{/each}}
|
|
105
|
-
`;
|
|
106
|
-
function linkify(text, context, issues) {
|
|
107
|
-
let result = text;
|
|
108
|
-
const repoUrl = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
|
|
109
|
-
if (repoUrl) {
|
|
110
|
-
const issueBaseUrl = `${repoUrl}/issues/`;
|
|
111
|
-
result = result.replace(/#([0-9]+)/g, (_, issue) => {
|
|
112
|
-
issues.push(issue);
|
|
113
|
-
return `[#${issue}](${issueBaseUrl}${issue})`;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
if (context.host) result = result.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => username.includes("/") ? `@${username}` : `[@${username}](${context.host}/${username})`);
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
function extractBreakingText(commit) {
|
|
120
|
-
const body = typeof commit.body === "string" ? commit.body : "";
|
|
121
|
-
const footer = typeof commit.footer === "string" ? commit.footer : "";
|
|
122
|
-
const match = BREAKING_CHANGE_RE.exec(`${footer}\n${body}`);
|
|
123
|
-
if (match?.[1]) return match[1].trim();
|
|
124
|
-
if (typeof commit.subject === "string" && commit.subject) return commit.subject;
|
|
125
|
-
if (typeof commit.header === "string" && commit.header) return commit.header;
|
|
126
|
-
return "";
|
|
127
|
-
}
|
|
128
|
-
function tryParseHeader(commit) {
|
|
129
|
-
if (typeof commit.header !== "string") return null;
|
|
130
|
-
const match = COMMIT_HEADER_RE.exec(commit.header.trim());
|
|
131
|
-
if (!match) return null;
|
|
132
|
-
return {
|
|
133
|
-
type: match[1],
|
|
134
|
-
scope: match[2] || void 0,
|
|
135
|
-
subject: match[4] || void 0,
|
|
136
|
-
isBreaking: Boolean(match[3])
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
function processBreakingChanges(commit, context, issues) {
|
|
140
|
-
let discard = true;
|
|
141
|
-
commit.notes.forEach((note) => {
|
|
142
|
-
note.title = "BREAKING CHANGES";
|
|
143
|
-
discard = false;
|
|
144
|
-
});
|
|
145
|
-
const hadBreakingNotes = commit.notes.length > 0;
|
|
146
|
-
const addBreakingNote = () => {
|
|
147
|
-
if (!hadBreakingNotes) {
|
|
148
|
-
const text = linkify(extractBreakingText(commit), context, issues);
|
|
149
|
-
commit.notes.push({
|
|
150
|
-
title: "BREAKING CHANGES",
|
|
151
|
-
text
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
discard = false;
|
|
155
|
-
};
|
|
156
|
-
const parsed = tryParseHeader(commit);
|
|
157
|
-
if (parsed) {
|
|
158
|
-
if (!commit.type) commit.type = parsed.type;
|
|
159
|
-
if (!commit.scope && parsed.scope) commit.scope = parsed.scope;
|
|
160
|
-
if (!commit.subject && parsed.subject) commit.subject = parsed.subject;
|
|
161
|
-
if (parsed.isBreaking) addBreakingNote();
|
|
162
|
-
}
|
|
163
|
-
if (typeof commit.type === "string" && commit.type.endsWith("!")) {
|
|
164
|
-
commit.type = commit.type.slice(0, -1);
|
|
165
|
-
addBreakingNote();
|
|
166
|
-
}
|
|
167
|
-
return discard;
|
|
168
|
-
}
|
|
169
|
-
function mapCommitType(commit, discard) {
|
|
170
|
-
if (commit.revert) {
|
|
171
|
-
commit.type = "Reverts";
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
const mapped = COMMIT_TYPE_MAP[commit.type];
|
|
175
|
-
if (mapped) {
|
|
176
|
-
if (ALWAYS_SHOW_TYPES.has(commit.type) || !discard) {
|
|
177
|
-
commit.type = mapped;
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return !discard;
|
|
182
|
-
}
|
|
183
|
-
function createDefaultWriterOpts() {
|
|
184
|
-
return {
|
|
185
|
-
mainTemplate: MAIN_TEMPLATE,
|
|
186
|
-
transform(commit, context) {
|
|
187
|
-
const issues = [];
|
|
188
|
-
if (!mapCommitType(commit, processBreakingChanges(commit, context, issues))) return false;
|
|
189
|
-
if (commit.scope === "*") commit.scope = "";
|
|
190
|
-
if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
|
|
191
|
-
if (typeof commit.subject === "string") commit.subject = linkify(commit.subject, context, issues);
|
|
192
|
-
commit.references = commit.references.filter((ref) => !issues.includes(ref.issue));
|
|
193
|
-
return commit;
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function changelog({ releaseCount = 0, file = "CHANGELOG.md", preset = "angular", writerOpts = createDefaultWriterOpts() } = {}) {
|
|
198
|
-
const s = spinner();
|
|
199
|
-
s.start("Generating changelog");
|
|
200
|
-
return new Promise((resolve$1) => {
|
|
201
|
-
conventionalChangelog({
|
|
202
|
-
preset,
|
|
203
|
-
releaseCount
|
|
204
|
-
}, void 0, void 0, void 0, writerOpts).pipe(createWriteStream(resolve(process.cwd(), file))).on("close", () => {
|
|
205
|
-
s.stop("Changelog generated successfully!");
|
|
206
|
-
resolve$1();
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
//#endregion
|
|
212
|
-
//#region src/release.ts
|
|
213
|
-
const cwd = process.cwd();
|
|
214
|
-
const { writeFileSync, readJSONSync, existsSync, readdirSync } = fse;
|
|
215
|
-
const releaseTypes = [
|
|
216
|
-
"patch",
|
|
217
|
-
"minor",
|
|
218
|
-
"major",
|
|
219
|
-
"prepatch",
|
|
220
|
-
"preminor",
|
|
221
|
-
"premajor"
|
|
222
|
-
];
|
|
223
|
-
const BACK_HINT = "Back to previous step";
|
|
224
|
-
async function isWorktreeEmpty() {
|
|
225
|
-
return !(await x("git", ["status", "--porcelain"])).stdout;
|
|
226
|
-
}
|
|
227
|
-
async function isSameVersion(version) {
|
|
228
|
-
const s = spinner();
|
|
229
|
-
s.start("Check remote version...");
|
|
230
|
-
const packageJsones = getPackageJsons();
|
|
231
|
-
const packageJson = packageJsones.find((packageJson) => !packageJson.config.private) || packageJsones[0];
|
|
232
|
-
if (packageJson) {
|
|
233
|
-
const { config } = packageJson;
|
|
234
|
-
try {
|
|
235
|
-
await x("npm", [
|
|
236
|
-
"view",
|
|
237
|
-
`${config.name}@${version ?? config.version}`,
|
|
238
|
-
"version"
|
|
239
|
-
], { throwOnError: true });
|
|
240
|
-
s.cancel();
|
|
241
|
-
logger.warn(`The npm package has a same remote version ${version ?? config.version}.`);
|
|
242
|
-
return true;
|
|
243
|
-
} catch {
|
|
244
|
-
s.stop();
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
async function publish({ preRelease, checkRemoteVersion, npmTag }) {
|
|
250
|
-
const s = spinner();
|
|
251
|
-
s.start("Publishing all packages");
|
|
252
|
-
const args = [
|
|
253
|
-
"-r",
|
|
254
|
-
"publish",
|
|
255
|
-
"--no-git-checks",
|
|
256
|
-
"--access",
|
|
257
|
-
"public"
|
|
258
|
-
];
|
|
259
|
-
if (checkRemoteVersion && await isSameVersion()) {
|
|
260
|
-
logger.error("publishing automatically skipped.");
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (preRelease) args.push("--tag", "alpha");
|
|
264
|
-
else if (npmTag) args.push("--tag", npmTag);
|
|
265
|
-
try {
|
|
266
|
-
const ret = await x("pnpm", args, { throwOnError: true });
|
|
267
|
-
s.stop("Publish all packages successfully");
|
|
268
|
-
ret.stdout && logger.log(ret.stdout);
|
|
269
|
-
} catch (error) {
|
|
270
|
-
s.cancel("Publish all packages failed");
|
|
271
|
-
throw error?.output?.stderr ?? error;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
async function pushGit(version, remote = "origin", skipGitTag = false) {
|
|
275
|
-
const s = spinner();
|
|
276
|
-
s.start("Pushing to remote git repository");
|
|
277
|
-
await x("git", ["add", "."], { throwOnError: true });
|
|
278
|
-
await x("git", [
|
|
279
|
-
"commit",
|
|
280
|
-
"-m",
|
|
281
|
-
`v${version}`
|
|
282
|
-
], { throwOnError: true });
|
|
283
|
-
if (!skipGitTag) {
|
|
284
|
-
await x("git", ["tag", `v${version}`], { throwOnError: true });
|
|
285
|
-
await x("git", [
|
|
286
|
-
"push",
|
|
287
|
-
remote,
|
|
288
|
-
`v${version}`
|
|
289
|
-
], { throwOnError: true });
|
|
290
|
-
}
|
|
291
|
-
const ret = await x("git", ["push"], { throwOnError: true });
|
|
292
|
-
s.stop("Push remote repository successfully");
|
|
293
|
-
ret.stdout && logger.log(ret.stdout);
|
|
294
|
-
}
|
|
295
|
-
function getAllPackageJsons() {
|
|
296
|
-
const result = [resolve(cwd, "package.json")];
|
|
297
|
-
const packagesDir = resolve(cwd, "packages");
|
|
298
|
-
if (existsSync(packagesDir)) for (const name of readdirSync(packagesDir)) {
|
|
299
|
-
const pkgPath = resolve(packagesDir, name, "package.json");
|
|
300
|
-
if (existsSync(pkgPath)) result.push(pkgPath);
|
|
301
|
-
}
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
function getPackageJsons() {
|
|
305
|
-
return getAllPackageJsons().map((path) => {
|
|
306
|
-
return {
|
|
307
|
-
config: readJSONSync(path),
|
|
308
|
-
filePath: path
|
|
309
|
-
};
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
function updateVersion(version) {
|
|
313
|
-
getPackageJsons().forEach(({ config, filePath }) => {
|
|
314
|
-
config.version = version;
|
|
315
|
-
writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
async function confirmRegistry() {
|
|
319
|
-
const registry = (await x("npm", [
|
|
320
|
-
"config",
|
|
321
|
-
"get",
|
|
322
|
-
"registry"
|
|
323
|
-
])).stdout;
|
|
324
|
-
const ret = await confirm({ message: `Current registry is: ${registry}` });
|
|
325
|
-
if (isCancel(ret)) {
|
|
326
|
-
cancel("Operation cancelled.");
|
|
327
|
-
process.exit(0);
|
|
328
|
-
}
|
|
329
|
-
return ret;
|
|
330
|
-
}
|
|
331
|
-
async function confirmVersion(currentVersion, expectVersion) {
|
|
332
|
-
const ret = await select({
|
|
333
|
-
message: "Version confirm",
|
|
334
|
-
options: [`All packages version ${currentVersion} -> ${expectVersion}`, BACK_HINT].map((value) => ({
|
|
335
|
-
label: value,
|
|
336
|
-
value
|
|
337
|
-
}))
|
|
338
|
-
});
|
|
339
|
-
if (isCancel(ret)) {
|
|
340
|
-
cancel("Operation cancelled.");
|
|
341
|
-
process.exit(0);
|
|
342
|
-
}
|
|
343
|
-
return ret;
|
|
344
|
-
}
|
|
345
|
-
async function confirmRefs(remote = "origin") {
|
|
346
|
-
const { stdout } = await x("git", ["remote", "-v"]);
|
|
347
|
-
const reg = new RegExp(`${remote}\t(.*) \\(push`);
|
|
348
|
-
const repo = stdout.match(reg)?.[1];
|
|
349
|
-
const { stdout: branch } = await x("git", ["branch", "--show-current"]);
|
|
350
|
-
const ret = await confirm({ message: `Current refs ${repo}:refs/for/${styleText("blue", branch)}` });
|
|
351
|
-
if (isCancel(ret)) {
|
|
352
|
-
cancel("Operation cancelled.");
|
|
353
|
-
process.exit(0);
|
|
354
|
-
}
|
|
355
|
-
return ret;
|
|
356
|
-
}
|
|
357
|
-
async function getReleaseType() {
|
|
358
|
-
const releaseType = await select({
|
|
359
|
-
message: "Please select release type",
|
|
360
|
-
options: releaseTypes.map((type) => ({
|
|
361
|
-
label: type,
|
|
362
|
-
value: type
|
|
363
|
-
}))
|
|
364
|
-
});
|
|
365
|
-
if (isCancel(releaseType)) {
|
|
366
|
-
cancel("Operation cancelled.");
|
|
367
|
-
process.exit(0);
|
|
368
|
-
}
|
|
369
|
-
return releaseType;
|
|
370
|
-
}
|
|
371
|
-
async function getReleaseVersion(currentVersion) {
|
|
372
|
-
let isPreRelease = false;
|
|
373
|
-
let expectVersion = "";
|
|
374
|
-
let confirmVersionRet = "";
|
|
375
|
-
do {
|
|
376
|
-
const type = await getReleaseType();
|
|
377
|
-
isPreRelease = type.startsWith("pre");
|
|
378
|
-
expectVersion = semver.inc(currentVersion, type, `alpha.${Date.now()}`);
|
|
379
|
-
expectVersion = isPreRelease ? expectVersion.slice(0, -2) : expectVersion;
|
|
380
|
-
confirmVersionRet = await confirmVersion(currentVersion, expectVersion);
|
|
381
|
-
} while (confirmVersionRet === BACK_HINT);
|
|
382
|
-
return {
|
|
383
|
-
isPreRelease,
|
|
384
|
-
expectVersion
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
async function release(options) {
|
|
388
|
-
try {
|
|
389
|
-
const currentVersion = readJSONSync(resolve(cwd, "package.json")).version;
|
|
390
|
-
if (!currentVersion) {
|
|
391
|
-
logger.error("Your package is missing the version field");
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
if (!await isWorktreeEmpty()) {
|
|
395
|
-
logger.error("Git worktree is not empty, please commit changed");
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
if (!await confirmRefs(options.remote)) return;
|
|
399
|
-
if (!options.skipNpmPublish && !await confirmRegistry()) return;
|
|
400
|
-
const { isPreRelease, expectVersion } = await getReleaseVersion(currentVersion);
|
|
401
|
-
if (options.checkRemoteVersion && await isSameVersion(expectVersion)) {
|
|
402
|
-
logger.error("Please check remote version.");
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
updateVersion(expectVersion);
|
|
406
|
-
if (options.task) await options.task(expectVersion, currentVersion);
|
|
407
|
-
if (!options.skipNpmPublish) await publish({
|
|
408
|
-
preRelease: isPreRelease,
|
|
409
|
-
npmTag: options.npmTag
|
|
410
|
-
});
|
|
411
|
-
if (!isPreRelease) {
|
|
412
|
-
if (!options.skipChangelog) await changelog();
|
|
413
|
-
await pushGit(expectVersion, options.remote, options.skipGitTag);
|
|
414
|
-
}
|
|
415
|
-
logger.success(`Release version ${expectVersion} successfully!`);
|
|
416
|
-
if (isPreRelease) {
|
|
417
|
-
try {
|
|
418
|
-
await x("git", ["restore", "**/package.json"], { throwOnError: true });
|
|
419
|
-
} catch {}
|
|
420
|
-
try {
|
|
421
|
-
await x("git", ["restore", "package.json"], { throwOnError: true });
|
|
422
|
-
} catch {}
|
|
423
|
-
}
|
|
424
|
-
} catch (error) {
|
|
425
|
-
logger.error(error);
|
|
426
|
-
process.exit(1);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
//#endregion
|
|
431
|
-
export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
|
|
1
|
+
import { a as updateVersion, c as COMMIT_MESSAGE_RE, d as isVersionCommitMessage, i as release, l as commitLint, n as isSameVersion, o as changelog, r as publish, s as COMMIT_HEADER_RE, t as getPackageJsons, u as getCommitMessage } from "./src-BWrnR5U-.js";
|
|
2
|
+
export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, changelog, commitLint, getCommitMessage, getPackageJsons, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { createWriteStream, existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { styleText } from "node:util";
|
|
4
|
+
import { cancel, confirm, isCancel, select, spinner } from "@clack/prompts";
|
|
5
|
+
import { logger } from "rslog";
|
|
6
|
+
import semver from "semver";
|
|
7
|
+
import { x } from "tinyexec";
|
|
8
|
+
import conventionalChangelog from "conventional-changelog";
|
|
9
|
+
//#region src/commitLint.ts
|
|
10
|
+
const COMMIT_HEADER_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(?:\(([^)]+)\))?(!)?:\s(.+)$/;
|
|
11
|
+
const COMMIT_MESSAGE_RE = new RegExp(COMMIT_HEADER_RE.source.replace(/\$$/, "") + "(?:\\n[\\s\\S]+)?$");
|
|
12
|
+
const ERROR_MESSAGE = "Commit message invalid.";
|
|
13
|
+
const WARNING_MESSAGE = `\
|
|
14
|
+
The rules for commit messages are as follows
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
|
|
18
|
+
feat: add a new feature
|
|
19
|
+
feat(ui/button): add a new feature in the ui/button scope
|
|
20
|
+
|
|
21
|
+
fix: fix a bug
|
|
22
|
+
fix(ui/button): fix a bug in the ui/button scope
|
|
23
|
+
|
|
24
|
+
docs: fix an error in the documentation
|
|
25
|
+
docs(ui/button): fix a documentation error in the ui/button scope
|
|
26
|
+
|
|
27
|
+
Allowed types:
|
|
28
|
+
- fix
|
|
29
|
+
- feat
|
|
30
|
+
- docs
|
|
31
|
+
- perf
|
|
32
|
+
- test
|
|
33
|
+
- types
|
|
34
|
+
- style
|
|
35
|
+
- build
|
|
36
|
+
- chore
|
|
37
|
+
- release
|
|
38
|
+
- refactor
|
|
39
|
+
- revert
|
|
40
|
+
- merge
|
|
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`;
|
|
45
|
+
function isVersionCommitMessage(message) {
|
|
46
|
+
return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
|
|
47
|
+
}
|
|
48
|
+
function getCommitMessage(commitMessagePath) {
|
|
49
|
+
return readFileSync(commitMessagePath, "utf-8").trim();
|
|
50
|
+
}
|
|
51
|
+
function commitLint(options) {
|
|
52
|
+
const { commitMessagePath, commitMessageRe = COMMIT_MESSAGE_RE, errorMessage = ERROR_MESSAGE, warningMessage = WARNING_MESSAGE } = options;
|
|
53
|
+
if (!commitMessagePath) {
|
|
54
|
+
logger.error("commitMessagePath is required");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const commitMessage = getCommitMessage(commitMessagePath);
|
|
58
|
+
const isValidCommitMessage = new RegExp(commitMessageRe).test(commitMessage);
|
|
59
|
+
if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
|
|
60
|
+
logger.error(errorMessage);
|
|
61
|
+
logger.warn(warningMessage);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/changelog.ts
|
|
67
|
+
const COMMIT_TYPE_MAP = {
|
|
68
|
+
feat: "Features",
|
|
69
|
+
fix: "Bug Fixes",
|
|
70
|
+
perf: "Performance Improvements",
|
|
71
|
+
revert: "Reverts",
|
|
72
|
+
refactor: "Code Refactoring",
|
|
73
|
+
docs: "Documentation",
|
|
74
|
+
style: "Styles",
|
|
75
|
+
test: "Tests",
|
|
76
|
+
build: "Build System",
|
|
77
|
+
ci: "Continuous Integration"
|
|
78
|
+
};
|
|
79
|
+
const ALWAYS_SHOW_TYPES = new Set([
|
|
80
|
+
"feat",
|
|
81
|
+
"fix",
|
|
82
|
+
"perf",
|
|
83
|
+
"revert",
|
|
84
|
+
"refactor"
|
|
85
|
+
]);
|
|
86
|
+
const BREAKING_CHANGE_RE = /BREAKING CHANGES?:\s*([\s\S]+)/;
|
|
87
|
+
const MAIN_TEMPLATE = `{{> header}}
|
|
88
|
+
|
|
89
|
+
{{> footer}}
|
|
90
|
+
{{#each commitGroups}}
|
|
91
|
+
|
|
92
|
+
{{#if title}}
|
|
93
|
+
### {{title}}
|
|
94
|
+
|
|
95
|
+
{{/if}}
|
|
96
|
+
{{#each commits}}
|
|
97
|
+
{{> commit root=@root}}
|
|
98
|
+
{{/each}}
|
|
99
|
+
|
|
100
|
+
{{/each}}
|
|
101
|
+
`;
|
|
102
|
+
function linkify(text, context, issues) {
|
|
103
|
+
let result = text;
|
|
104
|
+
const repoUrl = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
|
|
105
|
+
if (repoUrl) {
|
|
106
|
+
const issueBaseUrl = `${repoUrl}/issues/`;
|
|
107
|
+
result = result.replace(/#([0-9]+)/g, (_, issue) => {
|
|
108
|
+
issues.push(issue);
|
|
109
|
+
return `[#${issue}](${issueBaseUrl}${issue})`;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (context.host) result = result.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => username.includes("/") ? `@${username}` : `[@${username}](${context.host}/${username})`);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
function extractBreakingText(commit) {
|
|
116
|
+
const body = typeof commit.body === "string" ? commit.body : "";
|
|
117
|
+
const footer = typeof commit.footer === "string" ? commit.footer : "";
|
|
118
|
+
const match = BREAKING_CHANGE_RE.exec(`${footer}\n${body}`);
|
|
119
|
+
if (match?.[1]) return match[1].trim();
|
|
120
|
+
if (typeof commit.subject === "string" && commit.subject) return commit.subject;
|
|
121
|
+
if (typeof commit.header === "string" && commit.header) return commit.header;
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
function tryParseHeader(commit) {
|
|
125
|
+
if (typeof commit.header !== "string") return null;
|
|
126
|
+
const match = COMMIT_HEADER_RE.exec(commit.header.trim());
|
|
127
|
+
if (!match) return null;
|
|
128
|
+
return {
|
|
129
|
+
type: match[1],
|
|
130
|
+
scope: match[2] || void 0,
|
|
131
|
+
subject: match[4] || void 0,
|
|
132
|
+
isBreaking: Boolean(match[3])
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function processBreakingChanges(commit, context, issues) {
|
|
136
|
+
let discard = true;
|
|
137
|
+
commit.notes.forEach((note) => {
|
|
138
|
+
note.title = "BREAKING CHANGES";
|
|
139
|
+
discard = false;
|
|
140
|
+
});
|
|
141
|
+
const hadBreakingNotes = commit.notes.length > 0;
|
|
142
|
+
const addBreakingNote = () => {
|
|
143
|
+
if (!hadBreakingNotes) {
|
|
144
|
+
const text = linkify(extractBreakingText(commit), context, issues);
|
|
145
|
+
commit.notes.push({
|
|
146
|
+
title: "BREAKING CHANGES",
|
|
147
|
+
text
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
discard = false;
|
|
151
|
+
};
|
|
152
|
+
const parsed = tryParseHeader(commit);
|
|
153
|
+
if (parsed) {
|
|
154
|
+
if (!commit.type) commit.type = parsed.type;
|
|
155
|
+
if (!commit.scope && parsed.scope) commit.scope = parsed.scope;
|
|
156
|
+
if (!commit.subject && parsed.subject) commit.subject = parsed.subject;
|
|
157
|
+
if (parsed.isBreaking) addBreakingNote();
|
|
158
|
+
}
|
|
159
|
+
if (typeof commit.type === "string" && commit.type.endsWith("!")) {
|
|
160
|
+
commit.type = commit.type.slice(0, -1);
|
|
161
|
+
addBreakingNote();
|
|
162
|
+
}
|
|
163
|
+
return discard;
|
|
164
|
+
}
|
|
165
|
+
function mapCommitType(commit, discard) {
|
|
166
|
+
if (commit.revert) {
|
|
167
|
+
commit.type = "Reverts";
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const mapped = COMMIT_TYPE_MAP[commit.type];
|
|
171
|
+
if (mapped) {
|
|
172
|
+
if (ALWAYS_SHOW_TYPES.has(commit.type) || !discard) {
|
|
173
|
+
commit.type = mapped;
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return !discard;
|
|
178
|
+
}
|
|
179
|
+
function createDefaultWriterOpts() {
|
|
180
|
+
return {
|
|
181
|
+
mainTemplate: MAIN_TEMPLATE,
|
|
182
|
+
transform(commit, context) {
|
|
183
|
+
const issues = [];
|
|
184
|
+
if (!mapCommitType(commit, processBreakingChanges(commit, context, issues))) return false;
|
|
185
|
+
if (commit.scope === "*") commit.scope = "";
|
|
186
|
+
if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
|
|
187
|
+
if (typeof commit.subject === "string") commit.subject = linkify(commit.subject, context, issues);
|
|
188
|
+
commit.references = commit.references.filter((ref) => !issues.includes(ref.issue));
|
|
189
|
+
return commit;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function changelog({ releaseCount = 0, file = "CHANGELOG.md", preset = "angular", writerOpts = createDefaultWriterOpts() } = {}) {
|
|
194
|
+
const s = spinner();
|
|
195
|
+
s.start("Generating changelog");
|
|
196
|
+
return new Promise((resolve$1) => {
|
|
197
|
+
conventionalChangelog({
|
|
198
|
+
preset,
|
|
199
|
+
releaseCount
|
|
200
|
+
}, void 0, void 0, void 0, writerOpts).pipe(createWriteStream(resolve(process.cwd(), file))).on("close", () => {
|
|
201
|
+
s.stop("Changelog generated successfully!");
|
|
202
|
+
resolve$1();
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/utils.ts
|
|
208
|
+
function readJSONSync(path) {
|
|
209
|
+
const content = readFileSync(path, "utf-8").replace(/^\uFEFF/, "");
|
|
210
|
+
try {
|
|
211
|
+
return JSON.parse(content);
|
|
212
|
+
} catch (err) {
|
|
213
|
+
err.message = `${path}: ${err.message}`;
|
|
214
|
+
throw err;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/release.ts
|
|
219
|
+
const cwd = () => process.cwd();
|
|
220
|
+
const releaseTypes = [
|
|
221
|
+
"patch",
|
|
222
|
+
"minor",
|
|
223
|
+
"major",
|
|
224
|
+
"prepatch",
|
|
225
|
+
"preminor",
|
|
226
|
+
"premajor"
|
|
227
|
+
];
|
|
228
|
+
const BACK_HINT = "Back to previous step";
|
|
229
|
+
async function isWorktreeEmpty() {
|
|
230
|
+
return !(await x("git", ["status", "--porcelain"])).stdout;
|
|
231
|
+
}
|
|
232
|
+
async function isSameVersion(version) {
|
|
233
|
+
const s = spinner();
|
|
234
|
+
s.start("Check remote version...");
|
|
235
|
+
const packageJsones = getPackageJsons();
|
|
236
|
+
const packageJson = packageJsones.find((packageJson) => !packageJson.config.private) || packageJsones[0];
|
|
237
|
+
if (packageJson) {
|
|
238
|
+
const { config } = packageJson;
|
|
239
|
+
try {
|
|
240
|
+
await x("npm", [
|
|
241
|
+
"view",
|
|
242
|
+
`${config.name}@${version ?? config.version}`,
|
|
243
|
+
"version"
|
|
244
|
+
], { throwOnError: true });
|
|
245
|
+
s.cancel();
|
|
246
|
+
logger.warn(`The npm package has a same remote version ${version ?? config.version}.`);
|
|
247
|
+
return true;
|
|
248
|
+
} catch {
|
|
249
|
+
s.stop();
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function publish({ preRelease, checkRemoteVersion, npmTag }) {
|
|
255
|
+
const s = spinner();
|
|
256
|
+
s.start("Publishing all packages");
|
|
257
|
+
const args = [
|
|
258
|
+
"-r",
|
|
259
|
+
"publish",
|
|
260
|
+
"--no-git-checks",
|
|
261
|
+
"--access",
|
|
262
|
+
"public"
|
|
263
|
+
];
|
|
264
|
+
if (checkRemoteVersion && await isSameVersion()) {
|
|
265
|
+
logger.error("publishing automatically skipped.");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (preRelease) args.push("--tag", "alpha");
|
|
269
|
+
else if (npmTag) args.push("--tag", npmTag);
|
|
270
|
+
try {
|
|
271
|
+
const ret = await x("pnpm", args, { throwOnError: true });
|
|
272
|
+
s.stop("Publish all packages successfully");
|
|
273
|
+
ret.stdout && logger.log(ret.stdout);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
s.cancel("Publish all packages failed");
|
|
276
|
+
throw error?.output?.stderr ?? error;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function pushGit(version, remote = "origin", skipGitTag = false) {
|
|
280
|
+
const s = spinner();
|
|
281
|
+
s.start("Pushing to remote git repository");
|
|
282
|
+
await x("git", ["add", "."], { throwOnError: true });
|
|
283
|
+
await x("git", [
|
|
284
|
+
"commit",
|
|
285
|
+
"-m",
|
|
286
|
+
`v${version}`
|
|
287
|
+
], { throwOnError: true });
|
|
288
|
+
if (!skipGitTag) {
|
|
289
|
+
await x("git", ["tag", `v${version}`], { throwOnError: true });
|
|
290
|
+
await x("git", [
|
|
291
|
+
"push",
|
|
292
|
+
remote,
|
|
293
|
+
`v${version}`
|
|
294
|
+
], { throwOnError: true });
|
|
295
|
+
}
|
|
296
|
+
const ret = await x("git", ["push"], { throwOnError: true });
|
|
297
|
+
s.stop("Push remote repository successfully");
|
|
298
|
+
ret.stdout && logger.log(ret.stdout);
|
|
299
|
+
}
|
|
300
|
+
function getPackageJsons() {
|
|
301
|
+
const packageJsons = [resolve(cwd(), "package.json")];
|
|
302
|
+
const packagesDir = resolve(cwd(), "packages");
|
|
303
|
+
if (existsSync(packagesDir)) for (const name of readdirSync(packagesDir)) {
|
|
304
|
+
const pkgPath = resolve(packagesDir, name, "package.json");
|
|
305
|
+
if (existsSync(pkgPath)) packageJsons.push(pkgPath);
|
|
306
|
+
}
|
|
307
|
+
return packageJsons.map((path) => {
|
|
308
|
+
return {
|
|
309
|
+
filePath: path,
|
|
310
|
+
config: readJSONSync(path)
|
|
311
|
+
};
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function updateVersion(version) {
|
|
315
|
+
getPackageJsons().forEach(({ config, filePath }) => {
|
|
316
|
+
config.version = version;
|
|
317
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
async function confirmRegistry() {
|
|
321
|
+
const registry = (await x("npm", [
|
|
322
|
+
"config",
|
|
323
|
+
"get",
|
|
324
|
+
"registry"
|
|
325
|
+
])).stdout;
|
|
326
|
+
const ret = await confirm({ message: `Current registry is: ${registry}` });
|
|
327
|
+
if (isCancel(ret)) {
|
|
328
|
+
cancel("Operation cancelled.");
|
|
329
|
+
process.exit(0);
|
|
330
|
+
}
|
|
331
|
+
return ret;
|
|
332
|
+
}
|
|
333
|
+
async function confirmVersion(currentVersion, expectVersion) {
|
|
334
|
+
const ret = await select({
|
|
335
|
+
message: "Version confirm",
|
|
336
|
+
options: [`All packages version ${currentVersion} -> ${expectVersion}`, BACK_HINT].map((value) => ({
|
|
337
|
+
label: value,
|
|
338
|
+
value
|
|
339
|
+
}))
|
|
340
|
+
});
|
|
341
|
+
if (isCancel(ret)) {
|
|
342
|
+
cancel("Operation cancelled.");
|
|
343
|
+
process.exit(0);
|
|
344
|
+
}
|
|
345
|
+
return ret;
|
|
346
|
+
}
|
|
347
|
+
async function confirmRefs(remote = "origin") {
|
|
348
|
+
const { stdout } = await x("git", ["remote", "-v"]);
|
|
349
|
+
const reg = new RegExp(`${remote}\t(.*) \\(push`);
|
|
350
|
+
const repo = stdout.match(reg)?.[1];
|
|
351
|
+
const { stdout: branch } = await x("git", ["branch", "--show-current"]);
|
|
352
|
+
const ret = await confirm({ message: `Current refs ${repo}:refs/for/${styleText("blue", branch)}` });
|
|
353
|
+
if (isCancel(ret)) {
|
|
354
|
+
cancel("Operation cancelled.");
|
|
355
|
+
process.exit(0);
|
|
356
|
+
}
|
|
357
|
+
return ret;
|
|
358
|
+
}
|
|
359
|
+
async function getReleaseType() {
|
|
360
|
+
const releaseType = await select({
|
|
361
|
+
message: "Please select release type",
|
|
362
|
+
options: releaseTypes.map((type) => ({
|
|
363
|
+
label: type,
|
|
364
|
+
value: type
|
|
365
|
+
}))
|
|
366
|
+
});
|
|
367
|
+
if (isCancel(releaseType)) {
|
|
368
|
+
cancel("Operation cancelled.");
|
|
369
|
+
process.exit(0);
|
|
370
|
+
}
|
|
371
|
+
return releaseType;
|
|
372
|
+
}
|
|
373
|
+
async function getReleaseVersion(currentVersion) {
|
|
374
|
+
let isPreRelease = false;
|
|
375
|
+
let expectVersion = "";
|
|
376
|
+
let confirmVersionRet = "";
|
|
377
|
+
do {
|
|
378
|
+
const type = await getReleaseType();
|
|
379
|
+
isPreRelease = type.startsWith("pre");
|
|
380
|
+
expectVersion = semver.inc(currentVersion, type, `alpha.${Date.now()}`);
|
|
381
|
+
expectVersion = isPreRelease ? expectVersion.slice(0, -2) : expectVersion;
|
|
382
|
+
confirmVersionRet = await confirmVersion(currentVersion, expectVersion);
|
|
383
|
+
} while (confirmVersionRet === BACK_HINT);
|
|
384
|
+
return {
|
|
385
|
+
isPreRelease,
|
|
386
|
+
expectVersion
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
async function release(options) {
|
|
390
|
+
try {
|
|
391
|
+
const currentVersion = readJSONSync(resolve(cwd(), "package.json")).version;
|
|
392
|
+
if (!currentVersion) {
|
|
393
|
+
logger.error("Your package is missing the version field");
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (!await isWorktreeEmpty()) {
|
|
397
|
+
logger.error("Git worktree is not empty, please commit changed");
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (!await confirmRefs(options.remote)) return;
|
|
401
|
+
if (!options.skipNpmPublish && !await confirmRegistry()) return;
|
|
402
|
+
const { isPreRelease, expectVersion } = await getReleaseVersion(currentVersion);
|
|
403
|
+
if (options.checkRemoteVersion && await isSameVersion(expectVersion)) {
|
|
404
|
+
logger.error("Please check remote version.");
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
updateVersion(expectVersion);
|
|
408
|
+
if (options.task) await options.task(expectVersion, currentVersion);
|
|
409
|
+
if (!options.skipNpmPublish) await publish({
|
|
410
|
+
preRelease: isPreRelease,
|
|
411
|
+
npmTag: options.npmTag
|
|
412
|
+
});
|
|
413
|
+
if (!isPreRelease) {
|
|
414
|
+
if (!options.skipChangelog) await changelog();
|
|
415
|
+
await pushGit(expectVersion, options.remote, options.skipGitTag);
|
|
416
|
+
}
|
|
417
|
+
logger.success(`Release version ${expectVersion} successfully!`);
|
|
418
|
+
if (isPreRelease) {
|
|
419
|
+
try {
|
|
420
|
+
await x("git", ["restore", "**/package.json"], { throwOnError: true });
|
|
421
|
+
} catch {}
|
|
422
|
+
try {
|
|
423
|
+
await x("git", ["restore", "package.json"], { throwOnError: true });
|
|
424
|
+
} catch {}
|
|
425
|
+
}
|
|
426
|
+
} catch (error) {
|
|
427
|
+
logger.error(error);
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
//#endregion
|
|
432
|
+
export { updateVersion as a, COMMIT_MESSAGE_RE as c, isVersionCommitMessage as d, release as i, commitLint as l, isSameVersion as n, changelog as o, publish as r, COMMIT_HEADER_RE as s, getPackageJsons as t, getCommitMessage as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@varlet/release",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "publish all packages, generate changelogs and check commit messages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"changelog",
|
|
@@ -42,33 +42,30 @@
|
|
|
42
42
|
"package.json": "prettier --write"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@clack/prompts": "^1.
|
|
45
|
+
"@clack/prompts": "^1.1.0",
|
|
46
46
|
"commander": "^11.1.0",
|
|
47
47
|
"conventional-changelog": "^5.1.0",
|
|
48
|
-
"
|
|
49
|
-
"rslog": "^2.0.0",
|
|
48
|
+
"rslog": "^2.0.1",
|
|
50
49
|
"semver": "^7.5.4",
|
|
51
|
-
"tinyexec": "^1.0.
|
|
50
|
+
"tinyexec": "^1.0.4"
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
53
|
"@configurajs/eslint": "^0.1.2",
|
|
55
54
|
"@configurajs/prettier": "^0.1.4",
|
|
56
55
|
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
|
|
57
56
|
"@types/conventional-changelog": "^3.1.5",
|
|
58
|
-
"@types/fs-extra": "^11.0.4",
|
|
59
57
|
"@types/node": "^22.14.0",
|
|
60
58
|
"@types/semver": "^7.5.5",
|
|
61
|
-
"@vitest/coverage-v8": "^4.0
|
|
59
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
62
60
|
"eslint": "^9.39.2",
|
|
63
61
|
"lint-staged": "^16.2.7",
|
|
64
62
|
"prettier": "^3.8.1",
|
|
65
63
|
"prettier-plugin-packagejson": "^3.0.0",
|
|
66
64
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
67
|
-
"rimraf": "^6.1.2",
|
|
68
65
|
"simple-git-hooks": "^2.13.1",
|
|
69
|
-
"tsdown": "^0.
|
|
66
|
+
"tsdown": "^0.21.4",
|
|
70
67
|
"typescript": "^5.9.3",
|
|
71
|
-
"vitest": "^4.0
|
|
68
|
+
"vitest": "^4.1.0"
|
|
72
69
|
},
|
|
73
70
|
"engines": {
|
|
74
71
|
"node": "^20.19.0 || >=22.12.0",
|
|
@@ -76,7 +73,6 @@
|
|
|
76
73
|
},
|
|
77
74
|
"scripts": {
|
|
78
75
|
"build": "tsdown",
|
|
79
|
-
"clean": "rimraf node_modules dist",
|
|
80
76
|
"commit-lint": "node dist/cli.js commit-lint",
|
|
81
77
|
"dev": "tsdown --watch",
|
|
82
78
|
"format": "eslint . --fix && prettier --write .",
|