openspec-stat 1.0.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 +234 -0
- package/README.zh-CN.md +234 -0
- package/dist/cjs/branch-selector.d.ts +7 -0
- package/dist/cjs/branch-selector.js +124 -0
- package/dist/cjs/cli.d.ts +2 -0
- package/dist/cjs/cli.js +151 -0
- package/dist/cjs/config.d.ts +3 -0
- package/dist/cjs/config.js +66 -0
- package/dist/cjs/formatters.d.ts +7 -0
- package/dist/cjs/formatters.js +222 -0
- package/dist/cjs/git-analyzer.d.ts +10 -0
- package/dist/cjs/git-analyzer.js +170 -0
- package/dist/cjs/i18n/index.d.ts +7 -0
- package/dist/cjs/i18n/index.js +84 -0
- package/dist/cjs/i18n/locales/en.json +72 -0
- package/dist/cjs/i18n/locales/zh-CN.json +72 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +50 -0
- package/dist/cjs/stats-aggregator.d.ts +7 -0
- package/dist/cjs/stats-aggregator.js +117 -0
- package/dist/cjs/time-utils.d.ts +6 -0
- package/dist/cjs/time-utils.js +55 -0
- package/dist/cjs/types.d.ts +77 -0
- package/dist/cjs/types.js +17 -0
- package/dist/esm/branch-selector.d.ts +7 -0
- package/dist/esm/branch-selector.js +218 -0
- package/dist/esm/cli.d.ts +2 -0
- package/dist/esm/cli.js +157 -0
- package/dist/esm/config.d.ts +3 -0
- package/dist/esm/config.js +78 -0
- package/dist/esm/formatters.d.ts +7 -0
- package/dist/esm/formatters.js +207 -0
- package/dist/esm/git-analyzer.d.ts +10 -0
- package/dist/esm/git-analyzer.js +335 -0
- package/dist/esm/i18n/index.d.ts +7 -0
- package/dist/esm/i18n/index.js +49 -0
- package/dist/esm/i18n/locales/en.json +72 -0
- package/dist/esm/i18n/locales/zh-CN.json +72 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/stats-aggregator.d.ts +7 -0
- package/dist/esm/stats-aggregator.js +149 -0
- package/dist/esm/time-utils.d.ts +6 -0
- package/dist/esm/time-utils.js +31 -0
- package/dist/esm/types.d.ts +77 -0
- package/dist/esm/types.js +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# openspec-stat
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/openspec-stat)
|
|
4
|
+
[](https://npmjs.com/package/openspec-stat)
|
|
5
|
+
|
|
6
|
+
A CLI tool for tracking team members' OpenSpec proposals and code changes in Git repositories.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ✅ Track Git commits within specified time ranges
|
|
11
|
+
- ✅ Identify commits containing both OpenSpec proposals and code changes
|
|
12
|
+
- ✅ Group statistics by author (commits, proposals, code changes)
|
|
13
|
+
- ✅ Support multiple branches and wildcard filtering
|
|
14
|
+
- ✅ Author name mapping (handle multiple Git accounts for the same person)
|
|
15
|
+
- ✅ Track only recently active members (default: 2 weeks)
|
|
16
|
+
- ✅ Multiple output formats: Table, JSON, CSV, Markdown
|
|
17
|
+
- ✅ Internationalization support: English and Chinese (简体中文)
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### Global Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g openspec-stat
|
|
25
|
+
# or
|
|
26
|
+
pnpm add -g openspec-stat
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Local Project Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install openspec-stat --save-dev
|
|
33
|
+
# or
|
|
34
|
+
pnpm add -D openspec-stat
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
Run in a Git repository directory:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
openspec-stat
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This will track commits in the default time range (yesterday 20:00 ~ today 20:00).
|
|
48
|
+
|
|
49
|
+
### Command Line Options
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
openspec-stat [options]
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
-r, --repo <path> Repository path (default: current directory)
|
|
56
|
+
-b, --branches <branches> Branch list, comma-separated (e.g., origin/master,origin/release/v1.0)
|
|
57
|
+
-s, --since <datetime> Start time (default: yesterday 20:00)
|
|
58
|
+
-u, --until <datetime> End time (default: today 20:00)
|
|
59
|
+
-a, --author <name> Filter by specific author
|
|
60
|
+
--json Output in JSON format
|
|
61
|
+
--csv Output in CSV format
|
|
62
|
+
--markdown Output in Markdown format
|
|
63
|
+
-c, --config <path> Configuration file path
|
|
64
|
+
-v, --verbose Verbose output mode
|
|
65
|
+
-l, --lang <language> Language for output (en, zh-CN) (default: "en")
|
|
66
|
+
-V, --version Display version number
|
|
67
|
+
-h, --help Display help information
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Examples
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Track default time range
|
|
74
|
+
openspec-stat
|
|
75
|
+
|
|
76
|
+
# Track specific time range
|
|
77
|
+
openspec-stat --since "2024-01-01 00:00:00" --until "2024-01-31 23:59:59"
|
|
78
|
+
|
|
79
|
+
# Track specific branches
|
|
80
|
+
openspec-stat --branches "origin/master,origin/release/v1.0"
|
|
81
|
+
|
|
82
|
+
# Track specific author
|
|
83
|
+
openspec-stat --author "John Doe"
|
|
84
|
+
|
|
85
|
+
# Output JSON format
|
|
86
|
+
openspec-stat --json > stats.json
|
|
87
|
+
|
|
88
|
+
# Output Markdown report
|
|
89
|
+
openspec-stat --markdown > report.md
|
|
90
|
+
|
|
91
|
+
# Verbose output mode
|
|
92
|
+
openspec-stat --verbose
|
|
93
|
+
|
|
94
|
+
# Use custom configuration file
|
|
95
|
+
openspec-stat --config ./my-config.json
|
|
96
|
+
|
|
97
|
+
# Use Chinese output
|
|
98
|
+
openspec-stat --lang zh-CN
|
|
99
|
+
|
|
100
|
+
# Combine with other options
|
|
101
|
+
openspec-stat --lang zh-CN --verbose
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Configuration File
|
|
105
|
+
|
|
106
|
+
Create `.openspec-stats.json` or `openspec-stats.config.json` in the project root:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"defaultBranches": [
|
|
111
|
+
"origin/master",
|
|
112
|
+
"origin/main",
|
|
113
|
+
"origin/release/*"
|
|
114
|
+
],
|
|
115
|
+
"defaultSinceHours": -30,
|
|
116
|
+
"defaultUntilHours": 18,
|
|
117
|
+
"authorMapping": {
|
|
118
|
+
"John Doe": "John Doe",
|
|
119
|
+
"john.doe@company.com": "John Doe",
|
|
120
|
+
"johnd": "John Doe"
|
|
121
|
+
},
|
|
122
|
+
"openspecDir": "openspec/",
|
|
123
|
+
"excludeExtensions": [
|
|
124
|
+
".md",
|
|
125
|
+
".txt",
|
|
126
|
+
".png",
|
|
127
|
+
".jpg",
|
|
128
|
+
".jpeg",
|
|
129
|
+
".gif",
|
|
130
|
+
".svg",
|
|
131
|
+
".ico",
|
|
132
|
+
".webp"
|
|
133
|
+
],
|
|
134
|
+
"activeUserWeeks": 2
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Configuration Options
|
|
139
|
+
|
|
140
|
+
- **defaultBranches**: Default branches to track (supports wildcards)
|
|
141
|
+
- **defaultSinceHours**: Default start time offset (hours, negative means going back)
|
|
142
|
+
- **defaultUntilHours**: Default end time (hour of the day)
|
|
143
|
+
- **authorMapping**: Author name mapping to unify multiple Git accounts for the same person
|
|
144
|
+
- **openspecDir**: OpenSpec proposals directory (default: `openspec/`)
|
|
145
|
+
- **excludeExtensions**: File extensions to exclude (not counted as code changes)
|
|
146
|
+
- **activeUserWeeks**: Active user time window (weeks, default: 2)
|
|
147
|
+
|
|
148
|
+
## Statistics Logic
|
|
149
|
+
|
|
150
|
+
The tool identifies commits that meet both conditions:
|
|
151
|
+
|
|
152
|
+
1. Contains file changes in the `openspec/` directory (OpenSpec proposals)
|
|
153
|
+
2. Contains code file changes (excluding documentation files)
|
|
154
|
+
|
|
155
|
+
Statistics include:
|
|
156
|
+
|
|
157
|
+
- **Commits**: Total number of qualifying commits
|
|
158
|
+
- **OpenSpec Proposals**: Counted by `openspec/changes/{proposal-name}` directories
|
|
159
|
+
- **Code Files**: Number of modified code files
|
|
160
|
+
- **Additions**: Lines of code added
|
|
161
|
+
- **Deletions**: Lines of code deleted
|
|
162
|
+
- **Net Changes**: Additions - Deletions
|
|
163
|
+
|
|
164
|
+
## Output Formats
|
|
165
|
+
|
|
166
|
+
### Table Format (Default)
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
📊 OpenSpec Statistics Report
|
|
170
|
+
Time Range: 2024-01-01 00:00:00 ~ 2024-01-31 23:59:59
|
|
171
|
+
Branches: origin/master
|
|
172
|
+
Total Commits: 15
|
|
173
|
+
|
|
174
|
+
┌──────────┬─────────┬──────────────────┬────────────┬───────────┬───────────┬─────────────┐
|
|
175
|
+
│ Author │ Commits │ OpenSpec Proposals│ Code Files │ Additions │ Deletions │ Net Changes │
|
|
176
|
+
├──────────┼─────────┼──────────────────┼────────────┼───────────┼───────────┼─────────────┤
|
|
177
|
+
│ John Doe │ 8 │ 3 │ 45 │ +1234 │ -567 │ +667 │
|
|
178
|
+
│ Jane S. │ 7 │ 2 │ 32 │ +890 │ -234 │ +656 │
|
|
179
|
+
└──────────┴─────────┴──────────────────┴────────────┴───────────┴───────────┴─────────────┘
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### JSON Format
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
openspec-stat --json
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### CSV Format
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
openspec-stat --csv > stats.csv
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Markdown Format
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
openspec-stat --markdown > report.md
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Language Support
|
|
201
|
+
|
|
202
|
+
The tool supports both English and Chinese output. You can specify the language using the `--lang` option:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# English output (default)
|
|
206
|
+
openspec-stat --lang en
|
|
207
|
+
|
|
208
|
+
# Chinese output
|
|
209
|
+
openspec-stat --lang zh-CN
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The tool will also automatically detect your system language. If your system locale is set to Chinese, the output will default to Chinese.
|
|
213
|
+
|
|
214
|
+
For a Chinese version of this README, see [README.zh-CN.md](./README.zh-CN.md).
|
|
215
|
+
|
|
216
|
+
## Development
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Install dependencies
|
|
220
|
+
pnpm install
|
|
221
|
+
|
|
222
|
+
# Development mode
|
|
223
|
+
pnpm dev
|
|
224
|
+
|
|
225
|
+
# Build
|
|
226
|
+
pnpm build
|
|
227
|
+
|
|
228
|
+
# Local testing
|
|
229
|
+
node dist/esm/cli.js
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## LICENSE
|
|
233
|
+
|
|
234
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# openspec-stat
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/openspec-stat)
|
|
4
|
+
[](https://npmjs.com/package/openspec-stat)
|
|
5
|
+
|
|
6
|
+
用于追踪团队成员在 Git 仓库中的 OpenSpec 提案和代码变更的命令行工具。
|
|
7
|
+
|
|
8
|
+
[English](./README.md) | 简体中文
|
|
9
|
+
|
|
10
|
+
## 功能特性
|
|
11
|
+
|
|
12
|
+
- ✅ 追踪指定时间范围内的 Git 提交
|
|
13
|
+
- ✅ 识别同时包含 OpenSpec 提案和代码变更的提交
|
|
14
|
+
- ✅ 按作者分组统计(提交数、提案数、代码变更)
|
|
15
|
+
- ✅ 支持多分支和通配符过滤
|
|
16
|
+
- ✅ 作者名称映射(处理同一人的多个 Git 账号)
|
|
17
|
+
- ✅ 仅追踪最近活跃的成员(默认:2 周)
|
|
18
|
+
- ✅ 多种输出格式:表格、JSON、CSV、Markdown
|
|
19
|
+
- ✅ 国际化支持:英文和中文
|
|
20
|
+
|
|
21
|
+
## 安装
|
|
22
|
+
|
|
23
|
+
### 全局安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g openspec-stat
|
|
27
|
+
# 或
|
|
28
|
+
pnpm add -g openspec-stat
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 本地项目安装
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install openspec-stat --save-dev
|
|
35
|
+
# 或
|
|
36
|
+
pnpm add -D openspec-stat
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 使用方法
|
|
40
|
+
|
|
41
|
+
### 基本用法
|
|
42
|
+
|
|
43
|
+
在 Git 仓库目录中运行:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
openspec-stat
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
这将追踪默认时间范围内的提交(昨天 20:00 ~ 今天 20:00)。
|
|
50
|
+
|
|
51
|
+
### 命令行选项
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
openspec-stat [选项]
|
|
55
|
+
|
|
56
|
+
选项:
|
|
57
|
+
-r, --repo <path> 仓库路径(默认:当前目录)
|
|
58
|
+
-b, --branches <branches> 分支列表,逗号分隔(例如:origin/master,origin/release/v1.0)
|
|
59
|
+
-s, --since <datetime> 开始时间(默认:昨天 20:00)
|
|
60
|
+
-u, --until <datetime> 结束时间(默认:今天 20:00)
|
|
61
|
+
-a, --author <name> 按特定作者筛选
|
|
62
|
+
--json 以 JSON 格式输出
|
|
63
|
+
--csv 以 CSV 格式输出
|
|
64
|
+
--markdown 以 Markdown 格式输出
|
|
65
|
+
-c, --config <path> 配置文件路径
|
|
66
|
+
-v, --verbose 详细输出模式
|
|
67
|
+
-l, --lang <language> 输出语言(en, zh-CN)(默认:"en")
|
|
68
|
+
-V, --version 显示版本号
|
|
69
|
+
-h, --help 显示帮助信息
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 使用示例
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# 追踪默认时间范围
|
|
76
|
+
openspec-stat
|
|
77
|
+
|
|
78
|
+
# 追踪特定时间范围
|
|
79
|
+
openspec-stat --since "2024-01-01 00:00:00" --until "2024-01-31 23:59:59"
|
|
80
|
+
|
|
81
|
+
# 追踪特定分支
|
|
82
|
+
openspec-stat --branches "origin/master,origin/release/v1.0"
|
|
83
|
+
|
|
84
|
+
# 追踪特定作者
|
|
85
|
+
openspec-stat --author "张三"
|
|
86
|
+
|
|
87
|
+
# 输出 JSON 格式
|
|
88
|
+
openspec-stat --json > stats.json
|
|
89
|
+
|
|
90
|
+
# 输出 Markdown 报告
|
|
91
|
+
openspec-stat --markdown > report.md
|
|
92
|
+
|
|
93
|
+
# 详细输出模式
|
|
94
|
+
openspec-stat --verbose
|
|
95
|
+
|
|
96
|
+
# 使用自定义配置文件
|
|
97
|
+
openspec-stat --config ./my-config.json
|
|
98
|
+
|
|
99
|
+
# 使用中文输出
|
|
100
|
+
openspec-stat --lang zh-CN
|
|
101
|
+
|
|
102
|
+
# 组合多个选项
|
|
103
|
+
openspec-stat --lang zh-CN --verbose
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 配置文件
|
|
107
|
+
|
|
108
|
+
在项目根目录创建 `.openspec-stats.json` 或 `openspec-stats.config.json`:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"defaultBranches": [
|
|
113
|
+
"origin/master",
|
|
114
|
+
"origin/main",
|
|
115
|
+
"origin/release/*"
|
|
116
|
+
],
|
|
117
|
+
"defaultSinceHours": -30,
|
|
118
|
+
"defaultUntilHours": 18,
|
|
119
|
+
"authorMapping": {
|
|
120
|
+
"张三": "张三",
|
|
121
|
+
"zhangsan@company.com": "张三",
|
|
122
|
+
"zs": "张三"
|
|
123
|
+
},
|
|
124
|
+
"openspecDir": "openspec/",
|
|
125
|
+
"excludeExtensions": [
|
|
126
|
+
".md",
|
|
127
|
+
".txt",
|
|
128
|
+
".png",
|
|
129
|
+
".jpg",
|
|
130
|
+
".jpeg",
|
|
131
|
+
".gif",
|
|
132
|
+
".svg",
|
|
133
|
+
".ico",
|
|
134
|
+
".webp"
|
|
135
|
+
],
|
|
136
|
+
"activeUserWeeks": 2
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 配置选项说明
|
|
141
|
+
|
|
142
|
+
- **defaultBranches**:默认追踪的分支(支持通配符)
|
|
143
|
+
- **defaultSinceHours**:默认开始时间偏移(小时,负数表示往前推)
|
|
144
|
+
- **defaultUntilHours**:默认结束时间(当天的小时数)
|
|
145
|
+
- **authorMapping**:作者名称映射,用于统一同一人的多个 Git 账号
|
|
146
|
+
- **openspecDir**:OpenSpec 提案目录(默认:`openspec/`)
|
|
147
|
+
- **excludeExtensions**:排除的文件扩展名(不计入代码变更)
|
|
148
|
+
- **activeUserWeeks**:活跃用户时间窗口(周,默认:2)
|
|
149
|
+
|
|
150
|
+
## 统计逻辑
|
|
151
|
+
|
|
152
|
+
工具会识别同时满足以下两个条件的提交:
|
|
153
|
+
|
|
154
|
+
1. 包含 `openspec/` 目录中的文件变更(OpenSpec 提案)
|
|
155
|
+
2. 包含代码文件变更(排除文档文件)
|
|
156
|
+
|
|
157
|
+
统计内容包括:
|
|
158
|
+
|
|
159
|
+
- **提交数**:符合条件的提交总数
|
|
160
|
+
- **OpenSpec 提案**:按 `openspec/changes/{提案名称}` 目录统计
|
|
161
|
+
- **代码文件**:修改的代码文件数量
|
|
162
|
+
- **新增行数**:新增的代码行数
|
|
163
|
+
- **删除行数**:删除的代码行数
|
|
164
|
+
- **净变更**:新增行数 - 删除行数
|
|
165
|
+
|
|
166
|
+
## 输出格式
|
|
167
|
+
|
|
168
|
+
### 表格格式(默认)
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
📊 OpenSpec 统计报告
|
|
172
|
+
时间范围:2024-01-01 00:00:00 ~ 2024-01-31 23:59:59
|
|
173
|
+
分支:origin/master
|
|
174
|
+
总提交数:15
|
|
175
|
+
|
|
176
|
+
┌──────────┬─────────┬──────────────────┬────────────┬───────────┬───────────┬─────────────┐
|
|
177
|
+
│ 作者 │ 提交数 │ 提案数 │ 代码文件 │ 新增行数 │ 删除行数 │ 净变更 │
|
|
178
|
+
├──────────┼─────────┼──────────────────┼────────────┼───────────┼───────────┼─────────────┤
|
|
179
|
+
│ 张三 │ 8 │ 3 │ 45 │ +1234 │ -567 │ +667 │
|
|
180
|
+
│ 李四 │ 7 │ 2 │ 32 │ +890 │ -234 │ +656 │
|
|
181
|
+
└──────────┴─────────┴──────────────────┴────────────┴───────────┴───────────┴─────────────┘
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### JSON 格式
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
openspec-stat --json
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### CSV 格式
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
openspec-stat --csv > stats.csv
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Markdown 格式
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
openspec-stat --markdown > report.md
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## 语言支持
|
|
203
|
+
|
|
204
|
+
工具支持英文和中文输出。您可以使用 `--lang` 选项指定语言:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# 英文输出(默认)
|
|
208
|
+
openspec-stat --lang en
|
|
209
|
+
|
|
210
|
+
# 中文输出
|
|
211
|
+
openspec-stat --lang zh-CN
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
工具还会自动检测您的系统语言。如果您的系统区域设置为中文,输出将默认使用中文。
|
|
215
|
+
|
|
216
|
+
## 开发
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# 安装依赖
|
|
220
|
+
pnpm install
|
|
221
|
+
|
|
222
|
+
# 开发模式
|
|
223
|
+
pnpm dev
|
|
224
|
+
|
|
225
|
+
# 构建
|
|
226
|
+
pnpm build
|
|
227
|
+
|
|
228
|
+
# 本地测试
|
|
229
|
+
node dist/esm/cli.js
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 许可证
|
|
233
|
+
|
|
234
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface BranchInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
lastCommitDate: Date;
|
|
4
|
+
commitCount: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function getActiveBranches(repoPath: string, limit?: number): Promise<BranchInfo[]>;
|
|
7
|
+
export declare function selectBranches(repoPath: string, defaultBranches?: string[]): Promise<string[]>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/branch-selector.ts
|
|
30
|
+
var branch_selector_exports = {};
|
|
31
|
+
__export(branch_selector_exports, {
|
|
32
|
+
getActiveBranches: () => getActiveBranches,
|
|
33
|
+
selectBranches: () => selectBranches
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(branch_selector_exports);
|
|
36
|
+
var import_prompts = require("@inquirer/prompts");
|
|
37
|
+
var import_simple_git = __toESM(require("simple-git"));
|
|
38
|
+
var import_chalk = __toESM(require("chalk"));
|
|
39
|
+
var import_i18n = require("./i18n/index.js");
|
|
40
|
+
async function getActiveBranches(repoPath, limit = 10) {
|
|
41
|
+
const git = (0, import_simple_git.default)(repoPath);
|
|
42
|
+
const branches = await git.branch(["-r"]);
|
|
43
|
+
const branchNames = branches.all.filter((b) => !b.includes("HEAD"));
|
|
44
|
+
const branchInfos = [];
|
|
45
|
+
for (const branchName of branchNames) {
|
|
46
|
+
try {
|
|
47
|
+
const log = await git.log({
|
|
48
|
+
"--max-count": "1",
|
|
49
|
+
[branchName]: null
|
|
50
|
+
});
|
|
51
|
+
if (log.latest) {
|
|
52
|
+
branchInfos.push({
|
|
53
|
+
name: branchName,
|
|
54
|
+
lastCommitDate: new Date(log.latest.date),
|
|
55
|
+
commitCount: 0
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
branchInfos.sort((a, b) => b.lastCommitDate.getTime() - a.lastCommitDate.getTime());
|
|
63
|
+
return branchInfos.slice(0, limit);
|
|
64
|
+
}
|
|
65
|
+
async function selectBranches(repoPath, defaultBranches) {
|
|
66
|
+
console.log(import_chalk.default.blue((0, import_i18n.t)("branch.fetching")));
|
|
67
|
+
const activeBranches = await getActiveBranches(repoPath, 10);
|
|
68
|
+
if (activeBranches.length === 0) {
|
|
69
|
+
console.log(import_chalk.default.yellow((0, import_i18n.t)("warning.noBranches")));
|
|
70
|
+
return defaultBranches || [];
|
|
71
|
+
}
|
|
72
|
+
const choices = activeBranches.map((branch) => ({
|
|
73
|
+
name: `${branch.name} (${(0, import_i18n.t)("branch.lastCommit", { date: branch.lastCommitDate.toLocaleDateString() })})`,
|
|
74
|
+
value: branch.name,
|
|
75
|
+
checked: false
|
|
76
|
+
}));
|
|
77
|
+
choices.push({
|
|
78
|
+
name: import_chalk.default.gray((0, import_i18n.t)("branch.customSeparator")),
|
|
79
|
+
value: "__custom__",
|
|
80
|
+
checked: false
|
|
81
|
+
});
|
|
82
|
+
const mode = await (0, import_prompts.select)({
|
|
83
|
+
message: (0, import_i18n.t)("branch.selectMode"),
|
|
84
|
+
choices: [
|
|
85
|
+
{ name: (0, import_i18n.t)("branch.mode.select"), value: "select" },
|
|
86
|
+
{ name: (0, import_i18n.t)("branch.mode.default"), value: "default" },
|
|
87
|
+
{ name: (0, import_i18n.t)("branch.mode.custom"), value: "custom" }
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
if (mode === "default") {
|
|
91
|
+
return defaultBranches || [];
|
|
92
|
+
}
|
|
93
|
+
if (mode === "custom") {
|
|
94
|
+
const customInput = await (0, import_prompts.input)({
|
|
95
|
+
message: (0, import_i18n.t)("branch.customInput"),
|
|
96
|
+
default: (defaultBranches == null ? void 0 : defaultBranches.join(", ")) || ""
|
|
97
|
+
});
|
|
98
|
+
return customInput.split(",").map((b) => b.trim()).filter((b) => b);
|
|
99
|
+
}
|
|
100
|
+
const selected = await (0, import_prompts.checkbox)({
|
|
101
|
+
message: (0, import_i18n.t)("branch.selectPrompt"),
|
|
102
|
+
choices: choices.slice(0, -1),
|
|
103
|
+
pageSize: 15
|
|
104
|
+
});
|
|
105
|
+
if (selected.length > 0) {
|
|
106
|
+
console.log(import_chalk.default.green((0, import_i18n.t)("branch.selected")));
|
|
107
|
+
selected.forEach((branch) => {
|
|
108
|
+
console.log(import_chalk.default.green(` • ${branch}`));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (selected.includes("__custom__")) {
|
|
112
|
+
const customInput = await (0, import_prompts.input)({
|
|
113
|
+
message: (0, import_i18n.t)("branch.additionalInput")
|
|
114
|
+
});
|
|
115
|
+
const customBranches = customInput.split(",").map((b) => b.trim()).filter((b) => b);
|
|
116
|
+
return [...selected.filter((b) => b !== "__custom__"), ...customBranches];
|
|
117
|
+
}
|
|
118
|
+
return selected.length > 0 ? selected : defaultBranches || [];
|
|
119
|
+
}
|
|
120
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
121
|
+
0 && (module.exports = {
|
|
122
|
+
getActiveBranches,
|
|
123
|
+
selectBranches
|
|
124
|
+
});
|