growork 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/.claude/commands/push.md +48 -0
- package/.claude/settings.local.json +22 -0
- package/.mcp.json +14 -0
- package/README.md +244 -0
- package/bin/growork.js +2 -0
- package/claude.md +150 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +681 -0
- package/docs/product/prd-v1.0.md +418 -0
- package/docs/test/test-cases.md +188 -0
- package/growork.config.yaml +43 -0
- package/package.json +43 -0
- package/src/commands/init.ts +58 -0
- package/src/commands/list.ts +37 -0
- package/src/commands/sync.ts +77 -0
- package/src/index.ts +30 -0
- package/src/services/feishu.ts +360 -0
- package/src/services/notion.ts +129 -0
- package/src/utils/config.ts +95 -0
- package/test/backend-ai.md +539 -0
- package/test/backend-api.md +1236 -0
- package/test/prd-5spread.md +74 -0
- package/test/push-prd-notion.md +126 -0
- package/test/push.md +119 -0
- package/tests/config.test.ts +186 -0
- package/tests/feishu.test.ts +345 -0
- package/tests/notion.test.ts +273 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: Bash
|
|
3
|
+
argument-hint: "[commit message]"
|
|
4
|
+
description: 自动提交所有更改并推送到远程仓库
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 自动提交并推送代码
|
|
8
|
+
|
|
9
|
+
自动执行 git add、commit 和 push 操作。
|
|
10
|
+
|
|
11
|
+
### 当前状态
|
|
12
|
+
|
|
13
|
+
- 当前分支: !`git branch --show-current`
|
|
14
|
+
- Git 状态: !`git status --short`
|
|
15
|
+
|
|
16
|
+
### 执行任务
|
|
17
|
+
|
|
18
|
+
1. 查看当前所有变更:`git status`
|
|
19
|
+
2. 添加所有文件:`git add .`
|
|
20
|
+
3. 创建提交:
|
|
21
|
+
- 如果用户提供了提交信息($ARGUMENTS),使用该信息
|
|
22
|
+
- 如果没有提供,根据变更内容生成简洁明了的中文提交信息
|
|
23
|
+
4. 推送到远程:`git push`
|
|
24
|
+
5. 报告结果(显示提交哈希和推送状态)
|
|
25
|
+
|
|
26
|
+
### 提交信息规范
|
|
27
|
+
|
|
28
|
+
如果需要自动生成提交信息,请遵循以下原则:
|
|
29
|
+
- 使用中文
|
|
30
|
+
- 使用现在时态(例如:"添加功能" 而不是 "已添加功能")
|
|
31
|
+
- 简洁明了,总结主要变更
|
|
32
|
+
- 示例:"更新简历模型和UI"、"重构认证流程"、"修复导航bug"
|
|
33
|
+
|
|
34
|
+
### 错误处理
|
|
35
|
+
|
|
36
|
+
- 如果没有需要提交的变更,提示用户
|
|
37
|
+
- 如果推送失败(远程有新提交),建议先执行 `git pull --rebase`
|
|
38
|
+
- 如果有其他错误,显示错误信息并提供解决建议
|
|
39
|
+
|
|
40
|
+
### 使用示例
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 自动生成提交信息
|
|
44
|
+
/push
|
|
45
|
+
|
|
46
|
+
# 使用自定义提交信息
|
|
47
|
+
/push 添加面试功能模块
|
|
48
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash",
|
|
5
|
+
"Read",
|
|
6
|
+
"Write",
|
|
7
|
+
"Edit",
|
|
8
|
+
"Glob",
|
|
9
|
+
"Grep",
|
|
10
|
+
"Task",
|
|
11
|
+
"WebFetch",
|
|
12
|
+
"WebSearch",
|
|
13
|
+
"NotebookEdit",
|
|
14
|
+
"mcp__*",
|
|
15
|
+
"mcp__dart__*"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"enableAllProjectMcpServers": true,
|
|
19
|
+
"enabledMcpjsonServers": [
|
|
20
|
+
"dart-mcp"
|
|
21
|
+
]
|
|
22
|
+
}
|
package/.mcp.json
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# GroWork - 文档同步工具
|
|
2
|
+
|
|
3
|
+
把你的**飞书文档**和 **Notion 页面**自动下载到本地,变成 Markdown 文件。
|
|
4
|
+
|
|
5
|
+
这样 AI 工具(如 Claude、Cursor、Windsurf)就能直接读取你的产品文档,帮你写代码。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 这个工具能做什么?
|
|
10
|
+
|
|
11
|
+
✅ 自动下载飞书文档,转成 Markdown 格式
|
|
12
|
+
✅ 自动下载 Notion 页面,转成 Markdown 格式
|
|
13
|
+
✅ 一条命令同步所有文档
|
|
14
|
+
✅ 文档更新后,重新运行命令即可获取最新内容
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 安装步骤
|
|
19
|
+
|
|
20
|
+
### 第一步:安装 Node.js
|
|
21
|
+
|
|
22
|
+
GroWork 需要 Node.js 才能运行。如果你还没安装:
|
|
23
|
+
|
|
24
|
+
1. 打开 https://nodejs.org/
|
|
25
|
+
2. 点击绿色的 **"LTS"** 按钮下载
|
|
26
|
+
3. 双击下载的文件,按提示完成安装
|
|
27
|
+
|
|
28
|
+
**检查是否安装成功:**
|
|
29
|
+
|
|
30
|
+
打开「终端」(Mac)或「命令提示符」(Windows),输入:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
node -v
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
如果显示类似 `v18.17.0` 的版本号,说明安装成功。
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### 第二步:安装 GroWork
|
|
41
|
+
|
|
42
|
+
在终端中输入:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g growork
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
等待安装完成即可。
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 使用方法
|
|
53
|
+
|
|
54
|
+
### 1. 初始化项目
|
|
55
|
+
|
|
56
|
+
进入你的项目文件夹,运行:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
growork init
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
这会在当前目录创建一个 `growork.config.yaml` 配置文件。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### 2. 获取飞书凭证(如果你要同步飞书文档)
|
|
67
|
+
|
|
68
|
+
你需要在飞书开放平台创建一个应用,获取「App ID」和「App Secret」。
|
|
69
|
+
|
|
70
|
+
**详细步骤:**
|
|
71
|
+
|
|
72
|
+
1. **打开飞书开放平台**
|
|
73
|
+
- 国际版 Lark:https://open.larksuite.com/
|
|
74
|
+
- 国内版飞书:https://open.feishu.cn/
|
|
75
|
+
|
|
76
|
+
2. **创建应用**
|
|
77
|
+
- 点击「创建企业自建应用」
|
|
78
|
+
- 填写应用名称(随便起,比如「文档同步」)
|
|
79
|
+
- 点击「创建」
|
|
80
|
+
|
|
81
|
+
3. **获取凭证**
|
|
82
|
+
- 在应用详情页,找到「凭证与基础信息」
|
|
83
|
+
- 复制 **App ID**(以 `cli_` 开头)
|
|
84
|
+
- 复制 **App Secret**
|
|
85
|
+
|
|
86
|
+
4. **开通权限**
|
|
87
|
+
- 点击左侧「权限管理」
|
|
88
|
+
- 搜索并开通以下权限:
|
|
89
|
+
- `docx:document:readonly`(读取文档)
|
|
90
|
+
- `wiki:wiki:readonly`(读取知识库)
|
|
91
|
+
- 点击「批量开通」
|
|
92
|
+
|
|
93
|
+
5. **发布应用**
|
|
94
|
+
- 点击「版本管理与发布」
|
|
95
|
+
- 点击「创建版本」,填写版本号(如 1.0.0)
|
|
96
|
+
- 提交审核(企业内部应用一般自动通过)
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### 3. 获取 Notion 凭证(如果你要同步 Notion 页面)
|
|
101
|
+
|
|
102
|
+
**详细步骤:**
|
|
103
|
+
|
|
104
|
+
1. **创建 Integration**
|
|
105
|
+
- 打开 https://www.notion.so/my-integrations
|
|
106
|
+
- 点击「New integration」
|
|
107
|
+
- 填写名称(随便起,比如「文档同步」)
|
|
108
|
+
- 选择你的 Workspace
|
|
109
|
+
- 点击「Submit」
|
|
110
|
+
|
|
111
|
+
2. **复制 Token**
|
|
112
|
+
- 在 Integration 详情页,点击「Show」查看 Token
|
|
113
|
+
- 复制这个 Token(以 `ntn_` 或 `secret_` 开头)
|
|
114
|
+
|
|
115
|
+
3. **给页面授权**(重要!)
|
|
116
|
+
- 打开你要同步的 Notion 页面
|
|
117
|
+
- 点击右上角「···」→「Connections」→「Connect to」
|
|
118
|
+
- 选择你刚创建的 Integration
|
|
119
|
+
- **每个要同步的页面都需要做这一步!**
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### 4. 编辑配置文件
|
|
124
|
+
|
|
125
|
+
用任意文本编辑器打开 `growork.config.yaml`,填入你的凭证和文档链接:
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
# 飞书配置(如果不用飞书,可以删除这部分)
|
|
129
|
+
feishu:
|
|
130
|
+
appId: "cli_你的AppID" # 替换成你的 App ID
|
|
131
|
+
appSecret: "你的AppSecret" # 替换成你的 App Secret
|
|
132
|
+
domain: "lark" # 国际版用 lark,国内版用 feishu
|
|
133
|
+
|
|
134
|
+
# Notion 配置(如果不用 Notion,可以删除这部分)
|
|
135
|
+
notion:
|
|
136
|
+
token: "ntn_你的Token" # 替换成你的 Token
|
|
137
|
+
|
|
138
|
+
# 要同步的文档列表
|
|
139
|
+
docs:
|
|
140
|
+
# 飞书文档示例
|
|
141
|
+
- name: prd # 给文档起个名字(英文,方便记忆)
|
|
142
|
+
type: feishu # 类型:feishu
|
|
143
|
+
url: "https://xxx.larksuite.com/wiki/xxxxx" # 文档链接
|
|
144
|
+
output: "docs/prd.md" # 保存到哪里
|
|
145
|
+
|
|
146
|
+
# Notion 页面示例
|
|
147
|
+
- name: design # 给文档起个名字
|
|
148
|
+
type: notion # 类型:notion
|
|
149
|
+
url: "https://notion.so/xxxxx" # 页面链接
|
|
150
|
+
output: "docs/design.md" # 保存到哪里
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**如何获取文档链接?**
|
|
154
|
+
|
|
155
|
+
- **飞书**:打开文档,直接复制浏览器地址栏的链接
|
|
156
|
+
- **Notion**:打开页面,点击右上角「Share」→「Copy link」
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### 5. 同步文档
|
|
161
|
+
|
|
162
|
+
运行以下命令,自动下载所有文档:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
growork sync
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
同步完成后,文档会保存到你配置的 `output` 路径。
|
|
169
|
+
|
|
170
|
+
**只同步某一个文档:**
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
growork sync prd
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**查看所有已配置的文档:**
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
growork list
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 常见问题
|
|
185
|
+
|
|
186
|
+
### Q: 提示「权限不足」或「401」错误
|
|
187
|
+
|
|
188
|
+
**飞书文档:**
|
|
189
|
+
- 确认应用已开通 `docx:document:readonly` 和 `wiki:wiki:readonly` 权限
|
|
190
|
+
- 确认应用已发布上线
|
|
191
|
+
- 确认你有权限访问该文档
|
|
192
|
+
|
|
193
|
+
**Notion 页面:**
|
|
194
|
+
- 确认你已经把 Integration 连接到了该页面(见上面第 3 步的「给页面授权」)
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### Q: 提示「找不到命令」或「command not found」
|
|
199
|
+
|
|
200
|
+
Node.js 可能没有正确安装,或者 npm 全局路径没有加入系统 PATH。
|
|
201
|
+
|
|
202
|
+
尝试重新安装 Node.js,或者使用 `npx` 运行:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npx growork sync
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### Q: 同步后文档是空的
|
|
211
|
+
|
|
212
|
+
- 检查文档链接是否正确
|
|
213
|
+
- 检查你是否有权限访问该文档
|
|
214
|
+
- 飞书知识库文档需要使用 `/wiki/` 格式的链接
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### Q: 如何更新已同步的文档?
|
|
219
|
+
|
|
220
|
+
直接再次运行 `growork sync`,会自动覆盖本地文件。
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 支持的文档类型
|
|
225
|
+
|
|
226
|
+
| 平台 | 支持的内容 |
|
|
227
|
+
| --- | --- |
|
|
228
|
+
| 飞书 | 普通文档 (`/docx/`)、知识库 (`/wiki/`) |
|
|
229
|
+
| Notion | 任意页面(包含数据库的页面会自动转为表格) |
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 需要帮助?
|
|
234
|
+
|
|
235
|
+
如果遇到问题,可以:
|
|
236
|
+
|
|
237
|
+
1. 在 GitHub 上提 Issue:https://github.com/你的仓库/issues
|
|
238
|
+
2. 检查上面的「常见问题」部分
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
package/bin/growork.js
ADDED
package/claude.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# GroWork 架构原则
|
|
2
|
+
|
|
3
|
+
## 核心原则:用最少的代码实现功能
|
|
4
|
+
|
|
5
|
+
### 为什么
|
|
6
|
+
|
|
7
|
+
- 代码越少,bug 越少
|
|
8
|
+
- 代码越少,维护成本越低
|
|
9
|
+
- 代码越少,理解成本越低
|
|
10
|
+
- AI Agent 时代,简洁的代码更容易被 AI 理解和修改
|
|
11
|
+
|
|
12
|
+
### 具体实践
|
|
13
|
+
|
|
14
|
+
#### 1. 不要提前抽象
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// ❌ 不要这样:还没用到就提前封装
|
|
18
|
+
class DocumentSyncerFactory {
|
|
19
|
+
create(type: string): DocumentSyncer { ... }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ✅ 应该这样:直接写,等真正需要时再抽象
|
|
23
|
+
async function syncFeishuDoc(url: string, output: string) { ... }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
#### 2. 不要写"可能用到"的代码
|
|
27
|
+
|
|
28
|
+
- 只实现当前需求,不实现"将来可能需要"的功能
|
|
29
|
+
- 删掉所有注释掉的代码
|
|
30
|
+
- 删掉所有未使用的函数、变量、导入
|
|
31
|
+
|
|
32
|
+
#### 3. 优先使用标准库和成熟依赖
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// ❌ 不要自己造轮子
|
|
36
|
+
function parseYaml(content: string) { ... }
|
|
37
|
+
|
|
38
|
+
// ✅ 使用成熟的库
|
|
39
|
+
import yaml from 'yaml'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### 4. 一个函数只做一件事
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// ❌ 不要这样:一个函数做太多事
|
|
46
|
+
async function syncDoc(config) {
|
|
47
|
+
const yaml = readFile(...)
|
|
48
|
+
const parsed = parseYaml(yaml)
|
|
49
|
+
for (const doc of parsed.docs) {
|
|
50
|
+
const content = await fetchFeishu(doc.url)
|
|
51
|
+
const md = convertToMarkdown(content)
|
|
52
|
+
writeFile(doc.output, md)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ✅ 应该这样:职责分离,但不过度拆分
|
|
57
|
+
async function syncDoc(doc: DocConfig) {
|
|
58
|
+
const content = await fetchFeishuDoc(doc.url)
|
|
59
|
+
await writeFile(doc.output, content)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### 5. 避免过度配置化
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// ❌ 不要这样:过度灵活
|
|
67
|
+
interface Config {
|
|
68
|
+
outputFormat: 'markdown' | 'html' | 'json'
|
|
69
|
+
templatePath?: string
|
|
70
|
+
customConverter?: (content: any) => string
|
|
71
|
+
hooks?: { beforeSync?: () => void, afterSync?: () => void }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ✅ 应该这样:满足当前需求即可
|
|
75
|
+
interface DocConfig {
|
|
76
|
+
name: string
|
|
77
|
+
url: string
|
|
78
|
+
output: string
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### 6. 错误处理要简洁
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// ❌ 不要这样:过度防御
|
|
86
|
+
try {
|
|
87
|
+
const result = await fetchDoc(url)
|
|
88
|
+
if (!result) throw new Error('Empty result')
|
|
89
|
+
if (!result.data) throw new Error('No data')
|
|
90
|
+
if (!result.data.content) throw new Error('No content')
|
|
91
|
+
return result.data.content
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (e instanceof NetworkError) { ... }
|
|
94
|
+
else if (e instanceof AuthError) { ... }
|
|
95
|
+
else if (e instanceof TimeoutError) { ... }
|
|
96
|
+
else { ... }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ✅ 应该这样:让错误自然抛出,在顶层统一处理
|
|
100
|
+
const { data } = await fetchDoc(url)
|
|
101
|
+
return data.content
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### 7. 目录结构保持扁平
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
// ❌ 不要这样:过深的嵌套
|
|
108
|
+
src/
|
|
109
|
+
core/
|
|
110
|
+
services/
|
|
111
|
+
sync/
|
|
112
|
+
feishu/
|
|
113
|
+
index.ts
|
|
114
|
+
|
|
115
|
+
// ✅ 应该这样:扁平简洁
|
|
116
|
+
src/
|
|
117
|
+
commands/
|
|
118
|
+
services/
|
|
119
|
+
utils/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 代码规范
|
|
123
|
+
|
|
124
|
+
### 命名
|
|
125
|
+
|
|
126
|
+
- 文件名:小写 + 连字符,如 `feishu-sync.ts`
|
|
127
|
+
- 函数名:动词开头,如 `syncDoc`, `parseConfig`
|
|
128
|
+
- 布尔变量:is/has/should 开头,如 `isValid`
|
|
129
|
+
|
|
130
|
+
### 注释
|
|
131
|
+
|
|
132
|
+
- 好的代码不需要注释
|
|
133
|
+
- 只在"为什么"不明显时写注释,不要写"做什么"的注释
|
|
134
|
+
- 删掉所有 TODO 注释,要么现在做,要么建 issue
|
|
135
|
+
|
|
136
|
+
### 依赖
|
|
137
|
+
|
|
138
|
+
- 能用标准库解决的不引入新依赖
|
|
139
|
+
- 优先选择零依赖或依赖少的库
|
|
140
|
+
- 定期清理未使用的依赖
|
|
141
|
+
|
|
142
|
+
## 检查清单
|
|
143
|
+
|
|
144
|
+
提交代码前问自己:
|
|
145
|
+
|
|
146
|
+
- [ ] 这个函数/文件/模块可以删掉吗?
|
|
147
|
+
- [ ] 这段代码有更简单的写法吗?
|
|
148
|
+
- [ ] 这个抽象真的需要吗?
|
|
149
|
+
- [ ] 这个配置项真的会用到吗?
|
|
150
|
+
- [ ] 新人看到这段代码能立刻理解吗?
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|