@optima-chat/dev-skills 0.5.3 → 0.5.4

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.
@@ -0,0 +1,162 @@
1
+ # /generate-test-token - 生成测试 Access Token
2
+
3
+ 快速生成一个可用的测试 Access Token,包含完整的账户注册、token 获取和 merchant 设置。
4
+
5
+ **版本**: v0.5.4
6
+
7
+ ## 使用场景
8
+
9
+ **API 测试**: 快速获取可用的 access token 进行 API 调用测试
10
+ **开发调试**: 生成测试账户用于功能开发和调试
11
+ **集成测试**: 在 CI/CD 中自动生成测试账户
12
+
13
+ ## 🎯 使用方式:CLI 工具
14
+
15
+ 使用 `optima-generate-test-token` CLI 工具,它会自动完成所有设置:
16
+
17
+ ```bash
18
+ # 使用默认配置(随机生成账户信息)
19
+ optima-generate-test-token
20
+
21
+ # 自定义商户名称
22
+ optima-generate-test-token --business-name "我的测试店铺"
23
+
24
+ # 完全自定义
25
+ optima-generate-test-token \
26
+ --email "custom@example.com" \
27
+ --password "MyPass123" \
28
+ --business-name "Custom Shop" \
29
+ --phone "+1234567890"
30
+ ```
31
+
32
+ ## 工作流程
33
+
34
+ 该工具会自动完成以下步骤:
35
+
36
+ 1. **注册商家账户** - 在 Auth API 注册 merchant 角色用户
37
+ 2. **获取 Access Token** - 通过 OAuth 2.0 password grant 获取 token
38
+ 3. **设置 Merchant Profile** - 在 Commerce API 创建 merchant 资料
39
+ 4. **保存 Token 到文件** - 将 token 保存到临时文件,避免复制粘贴错误
40
+
41
+ ## 输出内容
42
+
43
+ 工具执行成功后会输出:
44
+
45
+ - 账户邮箱和密码
46
+ - User ID 和 Merchant ID
47
+ - **Token 文件路径**(token 已保存到该文件)
48
+ - 使用示例(包括 commerce CLI 和 curl)
49
+
50
+ ## 使用生成的 Token
51
+
52
+ ### 方式 1: 使用 commerce CLI(推荐)
53
+
54
+ ```bash
55
+ # 读取 token 并使用
56
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
57
+ OPTIMA_ENV=development \
58
+ commerce product list
59
+
60
+ # 创建商品
61
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
62
+ OPTIMA_ENV=development \
63
+ commerce product create \
64
+ --title "测试商品" \
65
+ --price 99.99 \
66
+ --stock 100
67
+ ```
68
+
69
+ ### 方式 2: 使用 curl
70
+
71
+ ```bash
72
+ # 查询商品
73
+ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-xxx.txt)" \
74
+ https://api.optima.chat/api/products
75
+
76
+ # 查询用户信息
77
+ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-xxx.txt)" \
78
+ https://auth.optima.chat/api/v1/users/me
79
+ ```
80
+
81
+ ## 命令参数
82
+
83
+ - `--email <email>` - 用户邮箱(默认:自动生成)
84
+ - `--password <password>` - 用户密码(默认:TestPassword123!)
85
+ - `--business-name <name>` - 商户名称(默认:自动生成)
86
+ - `--phone <phone>` - 联系电话(可选)
87
+ - `--address <address>` - 地址(可选)
88
+ - `--help, -h` - 显示帮助信息
89
+
90
+ ## 示例
91
+
92
+ ### 示例 1:快速生成
93
+
94
+ ```bash
95
+ optima-generate-test-token
96
+ ```
97
+
98
+ 输出:
99
+ ```
100
+ ✅ Test token generated successfully!
101
+
102
+ 📋 Details:
103
+ Email: test_1763996983959_wnjt4y@example.com
104
+ Password: TestPassword123!
105
+ User ID: 14bb1340-0ffc-41c8-aac6-c8b7a6bbb1a0
106
+ Role: merchant
107
+ Business Name: Test Merchant 1763996983959
108
+ Merchant ID: 14bb1340-0ffc-41c8-aac6-c8b7a6bbb1a0
109
+
110
+ 📁 Token File Path:
111
+ /tmp/optima-test-token-1763997011780.txt
112
+ ```
113
+
114
+ ### 示例 2:自定义商户信息
115
+
116
+ ```bash
117
+ optima-generate-test-token \
118
+ --business-name "Claude 测试商店" \
119
+ --phone "+8613800138000"
120
+ ```
121
+
122
+ ### 示例 3:使用 token 创建商品
123
+
124
+ ```bash
125
+ # 生成 token
126
+ optima-generate-test-token
127
+
128
+ # 使用 token(复制上面输出的文件路径)
129
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
130
+ OPTIMA_ENV=development \
131
+ commerce product create \
132
+ --title "陶瓷杯" \
133
+ --price 89 \
134
+ --stock 20
135
+ ```
136
+
137
+ ## ⚠️ 注意事项
138
+
139
+ 1. **仅用于开发环境** - 这些测试账户连接到 development 环境(api.optima.chat)
140
+ 2. **Token 有效期** - Token 默认有效期 15 分钟,请及时使用
141
+ 3. **临时文件** - Token 保存在系统临时目录,重启后可能被清理
142
+ 4. **环境变量** - 使用 commerce CLI 时需要设置 `OPTIMA_ENV=development`
143
+
144
+ ## 🔗 相关资源
145
+
146
+ - Commerce CLI: https://github.com/Optima-Chat/commerce-cli
147
+ - Auth API Docs: https://auth.optima.chat/docs
148
+ - Commerce API Docs: https://api.optima.chat/docs
149
+
150
+ ## 技术细节
151
+
152
+ **API 调用流程**:
153
+ 1. `POST /api/v1/auth/register/merchant` - 注册商家用户
154
+ 2. `POST /api/v1/oauth/token` - 获取 access token(password grant)
155
+ 3. `POST /api/merchants/me` - 设置 merchant profile
156
+
157
+ **使用的 Client ID**: `dev-skill-cli-he7fjmsp`
158
+
159
+ **默认 Merchant 信息**:
160
+ - 发货地址:中国深圳南山区科技园
161
+ - 联系电话:+8613800138000
162
+ - 联系邮箱:test@example.com
@@ -22,13 +22,14 @@
22
22
  "Bash(aws logs get-log-events:*)",
23
23
  "Bash(npm install:*)",
24
24
  "Bash(optima-dev-skills:*)",
25
+ "Bash(optima-generate-test-token:*)",
26
+ "Bash(optima-query-db:*)",
25
27
  "Bash(gh variable set:*)",
26
28
  "Bash(npm publish:*)",
27
- "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=staging&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
28
29
  "Bash(python3:*)",
29
- "Bash(curl -s \"https://secrets.optima.onl/api/v1/folders?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
30
- "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
31
- "Bash(gh api:*)"
30
+ "Bash(gh api:*)",
31
+ "Bash(curl -s http://auth.optima.chat/openapi.json)",
32
+ "Bash(curl -s https://auth.optima.chat/openapi.json)"
32
33
  ],
33
34
  "deny": [],
34
35
  "ask": []
@@ -0,0 +1,312 @@
1
+ ---
2
+ name: "generate-test-token"
3
+ description: "当用户请求生成测试 token、创建测试账户、获取 access token、需要测试 API、API 测试、测试账户时,使用此技能。自动完成账户注册、token 获取和 merchant 设置。"
4
+ allowed-tools: ["Bash", "SlashCommand"]
5
+ ---
6
+
7
+ # 生成测试 Access Token
8
+
9
+ 当你需要为 API 测试生成一个可用的 access token 时,使用这个场景。
10
+
11
+ ## 🎯 执行方式:使用 CLI 工具
12
+
13
+ **重要**:无论用户使用 `/generate-test-token` 命令还是直接请求生成测试 token,都应该使用 `optima-generate-test-token` CLI 工具:
14
+
15
+ ```bash
16
+ optima-generate-test-token [options]
17
+ ```
18
+
19
+ **为什么使用 CLI 工具**:
20
+ - ✅ 自动注册商家账户(Auth API)
21
+ - ✅ 自动获取 OAuth access token
22
+ - ✅ 自动设置 merchant profile(Commerce API)
23
+ - ✅ Token 保存到文件,避免复制错误
24
+ - ✅ 一条命令完成所有设置
25
+
26
+ ## 🎯 适用情况
27
+
28
+ - 需要测试 Commerce API 或 Auth API
29
+ - 开发新功能需要测试账户
30
+ - 调试 API 调用问题
31
+ - CI/CD 集成测试
32
+ - 演示功能需要临时账户
33
+
34
+ ## 🚀 快速操作
35
+
36
+ ### 基本使用
37
+
38
+ ```bash
39
+ # 使用默认配置(最简单)
40
+ optima-generate-test-token
41
+
42
+ # 自定义商户名称
43
+ optima-generate-test-token --business-name "我的测试店铺"
44
+
45
+ # 完全自定义
46
+ optima-generate-test-token \
47
+ --email "test@example.com" \
48
+ --password "MyPassword123" \
49
+ --business-name "测试商店"
50
+ ```
51
+
52
+ ### 使用生成的 Token
53
+
54
+ 工具执行后会输出 token 文件路径,例如:`/tmp/optima-test-token-1763997011780.txt`
55
+
56
+ **方式 1: 使用 commerce CLI**
57
+
58
+ ```bash
59
+ # 查询商品列表
60
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
61
+ OPTIMA_ENV=development \
62
+ commerce product list
63
+
64
+ # 创建商品
65
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
66
+ OPTIMA_ENV=development \
67
+ commerce product create \
68
+ --title "测试商品" \
69
+ --description "这是一个测试商品" \
70
+ --price 99.99 \
71
+ --stock 100 \
72
+ --currency USD \
73
+ --status active
74
+ ```
75
+
76
+ **方式 2: 使用 curl**
77
+
78
+ ```bash
79
+ # 查询用户信息
80
+ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-xxx.txt)" \
81
+ https://auth.optima.chat/api/v1/users/me
82
+
83
+ # 查询商品
84
+ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-xxx.txt)" \
85
+ https://api.optima.chat/api/products
86
+ ```
87
+
88
+ ## 📋 常见使用场景
89
+
90
+ ### 场景 1:快速 API 测试
91
+
92
+ **用户请求**:"我需要测试一下商品创建 API"
93
+
94
+ **步骤**:
95
+ 1. 生成 token:`optima-generate-test-token`
96
+ 2. 记录输出的 token 文件路径
97
+ 3. 使用 token 创建商品:
98
+ ```bash
99
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
100
+ OPTIMA_ENV=development \
101
+ commerce product create --title "测试商品" --price 99.99 --stock 100
102
+ ```
103
+
104
+ ### 场景 2:调试 API 调用
105
+
106
+ **用户请求**:"帮我生成一个测试账户,我要调试订单 API"
107
+
108
+ **步骤**:
109
+ 1. 生成测试账户和 token:`optima-generate-test-token --business-name "订单测试店铺"`
110
+ 2. 保存输出的账户信息(email, password, merchant_id)
111
+ 3. 使用 token 查询订单:
112
+ ```bash
113
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
114
+ OPTIMA_ENV=development \
115
+ commerce order list
116
+ ```
117
+
118
+ ### 场景 3:演示功能
119
+
120
+ **用户请求**:"创建一个演示账户,我要展示商品管理功能"
121
+
122
+ **步骤**:
123
+ 1. 生成演示账户:`optima-generate-test-token --business-name "演示商店"`
124
+ 2. 使用 token 创建演示数据:
125
+ ```bash
126
+ TOKEN_FILE=/tmp/optima-test-token-xxx.txt
127
+
128
+ # 创建多个商品
129
+ OPTIMA_TOKEN=$(cat $TOKEN_FILE) OPTIMA_ENV=development \
130
+ commerce product create --title "商品A" --price 49.99 --stock 50
131
+
132
+ OPTIMA_TOKEN=$(cat $TOKEN_FILE) OPTIMA_ENV=development \
133
+ commerce product create --title "商品B" --price 89.99 --stock 30
134
+ ```
135
+
136
+ ### 场景 4:CI/CD 集成测试
137
+
138
+ **用户请求**:"在 CI 环境中自动生成测试账户"
139
+
140
+ **步骤**:
141
+ 1. 在 CI 脚本中调用:
142
+ ```bash
143
+ # 生成 token 并保存路径
144
+ TOKEN_OUTPUT=$(optima-generate-test-token 2>&1)
145
+ TOKEN_FILE=$(echo "$TOKEN_OUTPUT" | grep "Token File Path" -A 1 | tail -1 | xargs)
146
+
147
+ # 在环境变量中设置
148
+ export OPTIMA_TOKEN=$(cat $TOKEN_FILE)
149
+ export OPTIMA_ENV=development
150
+
151
+ # 运行测试
152
+ npm run test:api
153
+ ```
154
+
155
+ ## 📋 工具输出说明
156
+
157
+ 成功执行后会输出:
158
+
159
+ ```
160
+ ✅ Test token generated successfully!
161
+
162
+ 📋 Details:
163
+ Email: test_1763996983959_wnjt4y@example.com
164
+ Password: TestPassword123!
165
+ User ID: 14bb1340-0ffc-41c8-aac6-c8b7a6bbb1a0
166
+ Role: merchant
167
+ Business Name: Test Merchant 1763996983959
168
+ Merchant ID: 14bb1340-0ffc-41c8-aac6-c8b7a6bbb1a0
169
+
170
+ 📁 Token File Path:
171
+ /tmp/optima-test-token-1763997011780.txt
172
+
173
+ 💡 Usage Examples:
174
+ # Read token from file:
175
+ TOKEN=$(cat /tmp/optima-test-token-1763997011780.txt)
176
+
177
+ # Use with commerce CLI:
178
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-1763997011780.txt) OPTIMA_ENV=development commerce product list
179
+
180
+ # Use in curl:
181
+ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-1763997011780.txt)" https://api.optima.chat/api/products
182
+ ```
183
+
184
+ **关键信息**:
185
+ - **Email/Password**: 账户登录凭证,可用于后续登录
186
+ - **Merchant ID**: 商户 ID,部分 API 可能需要
187
+ - **Token File Path**: Token 文件路径,这是最重要的信息!
188
+
189
+ ## ⚠️ 注意事项
190
+
191
+ ### 环境设置
192
+
193
+ 使用 commerce CLI 时**必须**设置环境变量:
194
+ ```bash
195
+ OPTIMA_ENV=development # 必需,指定 development 环境
196
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) # 必需,读取 token
197
+ ```
198
+
199
+ ### Token 有效期
200
+
201
+ - Token 默认有效期为 **15 分钟**
202
+ - 如果 token 过期,重新运行 `optima-generate-test-token` 即可
203
+ - 错误信息:"Invalid or expired token"
204
+
205
+ ### 文件管理
206
+
207
+ - Token 保存在系统临时目录(`/tmp/` 或 `/var/folders/...`)
208
+ - 系统重启后可能被清理
209
+ - 建议在使用完成后手动删除敏感文件
210
+
211
+ ### 只能用于开发环境
212
+
213
+ - 生成的账户注册到 **development 环境**
214
+ - API 地址:
215
+ - Auth: `https://auth.optima.chat`
216
+ - Commerce: `https://api.optima.chat`
217
+ - **不能用于** production 或 stage 环境
218
+
219
+ ## 💡 最佳实践
220
+
221
+ ### 1. Token 文件路径管理
222
+
223
+ ```bash
224
+ # 方法 1:直接从输出复制路径
225
+ optima-generate-test-token
226
+ # 复制输出中的 "Token File Path"
227
+
228
+ # 方法 2:保存到变量
229
+ TOKEN_FILE=$(optima-generate-test-token 2>&1 | grep "Token File Path" -A 1 | tail -1 | xargs)
230
+ OPTIMA_TOKEN=$(cat "$TOKEN_FILE")
231
+ ```
232
+
233
+ ### 2. 重复使用同一个 token
234
+
235
+ ```bash
236
+ # 将 token 路径保存到环境变量
237
+ export TOKEN_FILE=/tmp/optima-test-token-1763997011780.txt
238
+
239
+ # 后续使用
240
+ OPTIMA_TOKEN=$(cat $TOKEN_FILE) OPTIMA_ENV=development commerce product list
241
+ OPTIMA_TOKEN=$(cat $TOKEN_FILE) OPTIMA_ENV=development commerce order list
242
+ ```
243
+
244
+ ### 3. 自定义账户信息(可选)
245
+
246
+ 只有在需要特定账户信息时才自定义:
247
+
248
+ ```bash
249
+ # 自定义商户名称
250
+ optima-generate-test-token --business-name "我的专属测试店铺"
251
+
252
+ # 完全自定义(适合重复测试)
253
+ optima-generate-test-token \
254
+ --email "mytest@example.com" \
255
+ --password "MyStrongPassword123!" \
256
+ --business-name "固定测试店铺"
257
+ ```
258
+
259
+ ### 4. 清理测试数据
260
+
261
+ ```bash
262
+ # 测试完成后删除 token 文件
263
+ rm /tmp/optima-test-token-*.txt
264
+ ```
265
+
266
+ ## 🔧 故障排查
267
+
268
+ ### 问题 1:Token 无效
269
+
270
+ **错误信息**: "Invalid or expired token"
271
+
272
+ **解决方案**:
273
+ - Token 已过期(15分钟),重新生成
274
+ - 环境变量设置错误,检查 `OPTIMA_ENV=development`
275
+ - Token 文件路径错误,检查文件是否存在
276
+
277
+ ### 问题 2:Merchant profile 未设置
278
+
279
+ **错误信息**: "Merchant profile setup required"
280
+
281
+ **解决方案**:
282
+ - 这不应该发生,工具会自动设置
283
+ - 检查工具输出是否显示 "✓ Merchant profile setup complete"
284
+ - 如果没有,可能是网络问题,重新运行
285
+
286
+ ### 问题 3:命令不存在
287
+
288
+ **错误信息**: "command not found: optima-generate-test-token"
289
+
290
+ **解决方案**:
291
+ ```bash
292
+ # 安装或更新工具
293
+ npm install -g @optima-chat/dev-skills@latest
294
+
295
+ # 或本地使用
296
+ npx @optima-chat/dev-skills generate-test-token
297
+ ```
298
+
299
+ ## 🔗 相关命令
300
+
301
+ - `optima-generate-test-token` - CLI 生成工具(主要方式)
302
+ - `/generate-test-token` - Slash 命令(备用方式,详细使用方法请查看 `/generate-test-token --help`)
303
+ - `commerce auth login` - Commerce CLI 登录
304
+ - `commerce product create` - 创建商品
305
+ - `commerce order list` - 查询订单
306
+
307
+ ## 📚 更多资源
308
+
309
+ - **Commerce CLI**: https://github.com/Optima-Chat/commerce-cli
310
+ - **Auth API Docs**: https://auth.optima.chat/docs
311
+ - **Commerce API Docs**: https://api.optima.chat/docs
312
+ - **OAuth 2.0 文档**: https://auth.optima.chat/docs#/OAuth%202.0
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: "use-commerce-cli"
3
+ description: "当用户需要管理电商店铺(商品、订单、库存、运费、集合、首页、国际化)时,使用此技能。"
4
+ allowed-tools: ["Bash"]
5
+ ---
6
+
7
+ # 使用 Commerce CLI
8
+
9
+ ## 何时使用
10
+
11
+ 用户需要管理电商功能:商品、订单、库存、运费、集合、首页、国际化。
12
+
13
+ ## 前提
14
+
15
+ 用户已有 access token(通过 `optima-generate-test-token` 生成)。
16
+
17
+ ## Token 传递方式
18
+
19
+ **必须**同时设置 `OPTIMA_TOKEN` 和 `OPTIMA_ENV`:
20
+
21
+ ```bash
22
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
23
+ OPTIMA_ENV=development \
24
+ commerce <command>
25
+ ```
26
+
27
+ ## 示例
28
+
29
+ ```bash
30
+ # 创建商品
31
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
32
+ OPTIMA_ENV=development \
33
+ commerce product create --title "测试商品" --price 99.99 --stock 100
34
+
35
+ # 查询商品
36
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
37
+ OPTIMA_ENV=development \
38
+ commerce product list
39
+
40
+ # 查询订单
41
+ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
42
+ OPTIMA_ENV=development \
43
+ commerce order list
44
+ ```
45
+
46
+ ## 安装项目 Skills(可选)
47
+
48
+ ```bash
49
+ commerce init
50
+ ```
51
+
52
+ 在 `.claude/skills/` 安装完整 Skills,之后可用自然语言管理店铺。
53
+
54
+ ## 环境说明
55
+
56
+ `optima-generate-test-token` 生成的 token 连接到:
57
+ - API: `api.optima.chat`
58
+ - 环境变量:`OPTIMA_ENV=development`
package/README.md CHANGED
@@ -23,12 +23,13 @@ Optima Dev Skills 让 Claude Code 能够直接在 **CI、Stage、Prod** 三个
23
23
  - **任务驱动** - 基于具体任务场景(查看日志、调用 API),不是抽象分类
24
24
  - **跨环境协作** - 统一的命令在 CI、Stage、Prod 三个环境中使用
25
25
 
26
- ## 📋 任务场景(2 个)
26
+ ## 📋 任务场景(3 个)
27
27
 
28
28
  当 Claude Code 识别到以下任务时,会自动加载对应的 Skill:
29
29
 
30
30
  - **logs** - 查看 CI/Stage/Prod 的服务器日志
31
31
  - **query-db** - 查询 CI/Stage/Prod 的数据库
32
+ - **generate-test-token** - 生成测试 Access Token 用于 API 测试
32
33
 
33
34
  ## 👤 用户故事
34
35
 
@@ -72,10 +73,12 @@ Claude:
72
73
  |------|------|------|--------|
73
74
  | `/logs` | 查看服务日志 | `/logs commerce-backend 100` | ✅ |
74
75
  | `/query-db` | 查询数据库 | `/query-db user-auth "SELECT COUNT(*) FROM users"` | ✅ |
76
+ | `/generate-test-token` | 生成测试 token | `/generate-test-token` | 🔧 Development |
75
77
 
76
78
  **说明**:
77
79
  - 命令支持 CI、Stage、Prod 三个环境
78
80
  - 默认使用 CI 环境,适合日常开发
81
+ - `/generate-test-token` 生成的账户用于 development 环境(api.optima.chat)
79
82
  - Claude Code 会根据上下文自动选择环境和执行方式
80
83
 
81
84
  ## 🛠️ CLI 工具
@@ -85,12 +88,14 @@ Claude:
85
88
  | 工具 | 说明 | 示例 |
86
89
  |------|------|------|
87
90
  | `optima-query-db` | 数据库查询工具 | `optima-query-db user-auth "SELECT COUNT(*) FROM users" prod` |
91
+ | `optima-generate-test-token` | 生成测试 token | `optima-generate-test-token --business-name "测试店铺"` |
88
92
 
89
93
  **特点**:
90
- - ✅ 支持 CI、Stage、Prod 三个环境
94
+ - ✅ 支持 CI、Stage、Prod 三个环境(query-db)
91
95
  - ✅ 自动管理 SSH 隧道和密钥
92
96
  - ✅ 可在任何终端直接使用
93
- - ✅ Claude Code `/query-db` 命令内部也使用此工具
97
+ - ✅ 自动注册账户、获取 token、设置 merchant profile(generate-test-token)
98
+ - ✅ Claude Code 的命令内部也使用这些工具
94
99
 
95
100
  ## 🏗️ 项目结构
96
101
 
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as fs from 'fs';
4
+ import * as os from 'os';
5
+ import * as path from 'path';
6
+
7
+ interface RegisterResponse {
8
+ email: string;
9
+ user_id: string;
10
+ role: string;
11
+ is_active: boolean;
12
+ created_at: string;
13
+ updated_at: string;
14
+ }
15
+
16
+ interface TokenResponse {
17
+ access_token: string;
18
+ token_type: string;
19
+ }
20
+
21
+ interface MerchantSetupResponse {
22
+ merchant_id: string;
23
+ business_name: string;
24
+ user_id: string;
25
+ }
26
+
27
+ const AUTH_BASE_URL = 'https://auth.optima.chat';
28
+ const COMMERCE_API_URL = 'https://api.optima.chat';
29
+ const DEFAULT_CLIENT_ID = 'dev-skill-cli-he7fjmsp';
30
+
31
+ async function httpRequest<T>(url: string, options: RequestInit = {}): Promise<T> {
32
+ const response = await fetch(url, {
33
+ ...options,
34
+ headers: {
35
+ 'Content-Type': 'application/json',
36
+ ...options.headers
37
+ }
38
+ });
39
+
40
+ if (!response.ok) {
41
+ const text = await response.text();
42
+ throw new Error(`HTTP ${response.status}: ${text}`);
43
+ }
44
+
45
+ return response.json() as Promise<T>;
46
+ }
47
+
48
+ async function registerMerchant(
49
+ email: string,
50
+ password: string,
51
+ businessName: string,
52
+ phone?: string,
53
+ address?: string
54
+ ): Promise<RegisterResponse> {
55
+ console.log(`\n📝 Registering merchant: ${email}...`);
56
+
57
+ const payload: any = { email, password, business_name: businessName };
58
+ if (phone) payload.phone = phone;
59
+ if (address) payload.address = address;
60
+
61
+ try {
62
+ const result = await httpRequest<RegisterResponse>(`${AUTH_BASE_URL}/api/v1/auth/register/merchant`, {
63
+ method: 'POST',
64
+ body: JSON.stringify(payload)
65
+ });
66
+
67
+ console.log(`✓ Merchant registered successfully (ID: ${result.user_id})`);
68
+ return result;
69
+ } catch (error: any) {
70
+ if (error.message.includes('409') || error.message.includes('already exists')) {
71
+ console.log(`ℹ Merchant already exists, proceeding to login...`);
72
+ return { email, user_id: '', role: 'merchant', is_active: true, created_at: '', updated_at: '' };
73
+ }
74
+ throw error;
75
+ }
76
+ }
77
+
78
+ async function getToken(email: string, password: string, clientId: string = DEFAULT_CLIENT_ID): Promise<string> {
79
+ console.log(`\n🔑 Obtaining access token...`);
80
+
81
+ const formData = new URLSearchParams();
82
+ formData.append('username', email);
83
+ formData.append('password', password);
84
+ formData.append('grant_type', 'password');
85
+ formData.append('client_id', clientId);
86
+
87
+ const result = await httpRequest<TokenResponse>(`${AUTH_BASE_URL}/api/v1/oauth/token`, {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/x-www-form-urlencoded'
91
+ },
92
+ body: formData.toString()
93
+ });
94
+
95
+ console.log(`✓ Access token obtained`);
96
+ return result.access_token;
97
+ }
98
+
99
+ async function setupMerchantProfile(token: string, businessName: string): Promise<MerchantSetupResponse> {
100
+ console.log(`\n🏪 Setting up merchant profile in Commerce API...`);
101
+
102
+ const payload = {
103
+ name: businessName,
104
+ origin_country_alpha2: 'CN',
105
+ origin_city: '深圳',
106
+ origin_state: '广东省',
107
+ origin_line_1: '南山区科技园',
108
+ contact_name: '测试用户',
109
+ contact_phone: '+8613800138000',
110
+ contact_email: 'test@example.com'
111
+ };
112
+
113
+ try {
114
+ const result = await httpRequest<MerchantSetupResponse>(`${COMMERCE_API_URL}/api/merchants/me`, {
115
+ method: 'POST',
116
+ headers: {
117
+ Authorization: `Bearer ${token}`
118
+ },
119
+ body: JSON.stringify(payload)
120
+ });
121
+
122
+ console.log(`✓ Merchant profile setup complete (ID: ${result.merchant_id})`);
123
+ return result;
124
+ } catch (error: any) {
125
+ if (error.message.includes('409') || error.message.includes('already exists')) {
126
+ console.log(`ℹ Merchant profile already exists`);
127
+ return { merchant_id: '', business_name: businessName, user_id: '' };
128
+ }
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ async function main() {
134
+ const args = process.argv.slice(2);
135
+
136
+ // 生成随机测试账户
137
+ const timestamp = Date.now();
138
+ const randomStr = Math.random().toString(36).substring(2, 8);
139
+ const defaultEmail = `test_${timestamp}_${randomStr}@example.com`;
140
+ const defaultPassword = 'TestPassword123!';
141
+ const defaultBusinessName = `Test Merchant ${timestamp}`;
142
+
143
+ let email = defaultEmail;
144
+ let password = defaultPassword;
145
+ let businessName = defaultBusinessName;
146
+ let phone: string | undefined;
147
+ let address: string | undefined;
148
+
149
+ // 解析命令行参数
150
+ for (let i = 0; i < args.length; i++) {
151
+ const arg = args[i];
152
+
153
+ if (arg === '--email' && args[i + 1]) {
154
+ email = args[++i];
155
+ } else if (arg === '--password' && args[i + 1]) {
156
+ password = args[++i];
157
+ } else if (arg === '--business-name' && args[i + 1]) {
158
+ businessName = args[++i];
159
+ } else if (arg === '--phone' && args[i + 1]) {
160
+ phone = args[++i];
161
+ } else if (arg === '--address' && args[i + 1]) {
162
+ address = args[++i];
163
+ } else if (arg === '--help' || arg === '-h') {
164
+ console.log(`
165
+ Usage: generate-test-token [options]
166
+
167
+ Options:
168
+ --email <email> User email (default: auto-generated)
169
+ --password <password> User password (default: TestPassword123!)
170
+ --business-name <name> Merchant business name (default: auto-generated)
171
+ --phone <phone> Merchant phone number (optional)
172
+ --address <address> Merchant address (optional)
173
+ --help, -h Show this help message
174
+
175
+ Example:
176
+ generate-test-token
177
+ generate-test-token --business-name "My Test Shop" --phone "+1234567890"
178
+ generate-test-token --email "custom@example.com" --password "MyPass123"
179
+ `);
180
+ process.exit(0);
181
+ }
182
+ }
183
+
184
+ try {
185
+ console.log('🚀 Starting test token generation...\n');
186
+ console.log(`Using credentials:`);
187
+ console.log(` Email: ${email}`);
188
+ console.log(` Password: ${password}`);
189
+ console.log(` Business Name: ${businessName}`);
190
+
191
+ // 1. 注册 merchant(直接注册为商家)
192
+ const user = await registerMerchant(email, password, businessName, phone, address);
193
+
194
+ // 2. 获取 token
195
+ const token = await getToken(email, password);
196
+
197
+ // 3. 设置 merchant profile(Commerce API)
198
+ const merchantProfile = await setupMerchantProfile(token, businessName);
199
+
200
+ // 4. 保存 token 到临时文件
201
+ const tmpDir = os.tmpdir();
202
+ const tokenFileName = `optima-test-token-${Date.now()}.txt`;
203
+ const tokenFilePath = path.join(tmpDir, tokenFileName);
204
+
205
+ fs.writeFileSync(tokenFilePath, token, 'utf-8');
206
+ console.log(`\n💾 Token saved to temporary file`);
207
+
208
+ // 输出结果
209
+ console.log('\n' + '='.repeat(80));
210
+ console.log('✅ Test token generated successfully!\n');
211
+ console.log('📋 Details:');
212
+ console.log(` Email: ${email}`);
213
+ console.log(` Password: ${password}`);
214
+ console.log(` User ID: ${user.user_id || 'N/A'}`);
215
+ console.log(` Role: ${user.role}`);
216
+ console.log(` Business Name: ${businessName}`);
217
+ console.log(` Merchant ID: ${merchantProfile.merchant_id || 'N/A'}\n`);
218
+ console.log('📁 Token File Path:');
219
+ console.log(` ${tokenFilePath}\n`);
220
+ console.log('💡 Usage Examples:');
221
+ console.log(` # Read token from file:`);
222
+ console.log(` TOKEN=$(cat ${tokenFilePath})\n`);
223
+ console.log(` # Use with commerce CLI:`);
224
+ console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV=development commerce product list\n`);
225
+ console.log(` # Use in curl:`);
226
+ console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})" https://api.optima.chat/api/products\n`);
227
+ console.log('='.repeat(80));
228
+
229
+ } catch (error: any) {
230
+ console.error('\n❌ Error:', error.message);
231
+ process.exit(1);
232
+ }
233
+ }
234
+
235
+ main();
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const AUTH_BASE_URL = 'https://auth.optima.chat';
41
+ const COMMERCE_API_URL = 'https://api.optima.chat';
42
+ const DEFAULT_CLIENT_ID = 'dev-skill-cli-he7fjmsp';
43
+ async function httpRequest(url, options = {}) {
44
+ const response = await fetch(url, {
45
+ ...options,
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ ...options.headers
49
+ }
50
+ });
51
+ if (!response.ok) {
52
+ const text = await response.text();
53
+ throw new Error(`HTTP ${response.status}: ${text}`);
54
+ }
55
+ return response.json();
56
+ }
57
+ async function registerMerchant(email, password, businessName, phone, address) {
58
+ console.log(`\n📝 Registering merchant: ${email}...`);
59
+ const payload = { email, password, business_name: businessName };
60
+ if (phone)
61
+ payload.phone = phone;
62
+ if (address)
63
+ payload.address = address;
64
+ try {
65
+ const result = await httpRequest(`${AUTH_BASE_URL}/api/v1/auth/register/merchant`, {
66
+ method: 'POST',
67
+ body: JSON.stringify(payload)
68
+ });
69
+ console.log(`✓ Merchant registered successfully (ID: ${result.user_id})`);
70
+ return result;
71
+ }
72
+ catch (error) {
73
+ if (error.message.includes('409') || error.message.includes('already exists')) {
74
+ console.log(`ℹ Merchant already exists, proceeding to login...`);
75
+ return { email, user_id: '', role: 'merchant', is_active: true, created_at: '', updated_at: '' };
76
+ }
77
+ throw error;
78
+ }
79
+ }
80
+ async function getToken(email, password, clientId = DEFAULT_CLIENT_ID) {
81
+ console.log(`\n🔑 Obtaining access token...`);
82
+ const formData = new URLSearchParams();
83
+ formData.append('username', email);
84
+ formData.append('password', password);
85
+ formData.append('grant_type', 'password');
86
+ formData.append('client_id', clientId);
87
+ const result = await httpRequest(`${AUTH_BASE_URL}/api/v1/oauth/token`, {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/x-www-form-urlencoded'
91
+ },
92
+ body: formData.toString()
93
+ });
94
+ console.log(`✓ Access token obtained`);
95
+ return result.access_token;
96
+ }
97
+ async function setupMerchantProfile(token, businessName) {
98
+ console.log(`\n🏪 Setting up merchant profile in Commerce API...`);
99
+ const payload = {
100
+ name: businessName,
101
+ origin_country_alpha2: 'CN',
102
+ origin_city: '深圳',
103
+ origin_state: '广东省',
104
+ origin_line_1: '南山区科技园',
105
+ contact_name: '测试用户',
106
+ contact_phone: '+8613800138000',
107
+ contact_email: 'test@example.com'
108
+ };
109
+ try {
110
+ const result = await httpRequest(`${COMMERCE_API_URL}/api/merchants/me`, {
111
+ method: 'POST',
112
+ headers: {
113
+ Authorization: `Bearer ${token}`
114
+ },
115
+ body: JSON.stringify(payload)
116
+ });
117
+ console.log(`✓ Merchant profile setup complete (ID: ${result.merchant_id})`);
118
+ return result;
119
+ }
120
+ catch (error) {
121
+ if (error.message.includes('409') || error.message.includes('already exists')) {
122
+ console.log(`ℹ Merchant profile already exists`);
123
+ return { merchant_id: '', business_name: businessName, user_id: '' };
124
+ }
125
+ throw error;
126
+ }
127
+ }
128
+ async function main() {
129
+ const args = process.argv.slice(2);
130
+ // 生成随机测试账户
131
+ const timestamp = Date.now();
132
+ const randomStr = Math.random().toString(36).substring(2, 8);
133
+ const defaultEmail = `test_${timestamp}_${randomStr}@example.com`;
134
+ const defaultPassword = 'TestPassword123!';
135
+ const defaultBusinessName = `Test Merchant ${timestamp}`;
136
+ let email = defaultEmail;
137
+ let password = defaultPassword;
138
+ let businessName = defaultBusinessName;
139
+ let phone;
140
+ let address;
141
+ // 解析命令行参数
142
+ for (let i = 0; i < args.length; i++) {
143
+ const arg = args[i];
144
+ if (arg === '--email' && args[i + 1]) {
145
+ email = args[++i];
146
+ }
147
+ else if (arg === '--password' && args[i + 1]) {
148
+ password = args[++i];
149
+ }
150
+ else if (arg === '--business-name' && args[i + 1]) {
151
+ businessName = args[++i];
152
+ }
153
+ else if (arg === '--phone' && args[i + 1]) {
154
+ phone = args[++i];
155
+ }
156
+ else if (arg === '--address' && args[i + 1]) {
157
+ address = args[++i];
158
+ }
159
+ else if (arg === '--help' || arg === '-h') {
160
+ console.log(`
161
+ Usage: generate-test-token [options]
162
+
163
+ Options:
164
+ --email <email> User email (default: auto-generated)
165
+ --password <password> User password (default: TestPassword123!)
166
+ --business-name <name> Merchant business name (default: auto-generated)
167
+ --phone <phone> Merchant phone number (optional)
168
+ --address <address> Merchant address (optional)
169
+ --help, -h Show this help message
170
+
171
+ Example:
172
+ generate-test-token
173
+ generate-test-token --business-name "My Test Shop" --phone "+1234567890"
174
+ generate-test-token --email "custom@example.com" --password "MyPass123"
175
+ `);
176
+ process.exit(0);
177
+ }
178
+ }
179
+ try {
180
+ console.log('🚀 Starting test token generation...\n');
181
+ console.log(`Using credentials:`);
182
+ console.log(` Email: ${email}`);
183
+ console.log(` Password: ${password}`);
184
+ console.log(` Business Name: ${businessName}`);
185
+ // 1. 注册 merchant(直接注册为商家)
186
+ const user = await registerMerchant(email, password, businessName, phone, address);
187
+ // 2. 获取 token
188
+ const token = await getToken(email, password);
189
+ // 3. 设置 merchant profile(Commerce API)
190
+ const merchantProfile = await setupMerchantProfile(token, businessName);
191
+ // 4. 保存 token 到临时文件
192
+ const tmpDir = os.tmpdir();
193
+ const tokenFileName = `optima-test-token-${Date.now()}.txt`;
194
+ const tokenFilePath = path.join(tmpDir, tokenFileName);
195
+ fs.writeFileSync(tokenFilePath, token, 'utf-8');
196
+ console.log(`\n💾 Token saved to temporary file`);
197
+ // 输出结果
198
+ console.log('\n' + '='.repeat(80));
199
+ console.log('✅ Test token generated successfully!\n');
200
+ console.log('📋 Details:');
201
+ console.log(` Email: ${email}`);
202
+ console.log(` Password: ${password}`);
203
+ console.log(` User ID: ${user.user_id || 'N/A'}`);
204
+ console.log(` Role: ${user.role}`);
205
+ console.log(` Business Name: ${businessName}`);
206
+ console.log(` Merchant ID: ${merchantProfile.merchant_id || 'N/A'}\n`);
207
+ console.log('📁 Token File Path:');
208
+ console.log(` ${tokenFilePath}\n`);
209
+ console.log('💡 Usage Examples:');
210
+ console.log(` # Read token from file:`);
211
+ console.log(` TOKEN=$(cat ${tokenFilePath})\n`);
212
+ console.log(` # Use with commerce CLI:`);
213
+ console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV=development commerce product list\n`);
214
+ console.log(` # Use in curl:`);
215
+ console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})" https://api.optima.chat/api/products\n`);
216
+ console.log('='.repeat(80));
217
+ }
218
+ catch (error) {
219
+ console.error('\n❌ Error:', error.message);
220
+ process.exit(1);
221
+ }
222
+ }
223
+ main();
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@optima-chat/dev-skills",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Claude Code Skills for Optima development team - cross-environment collaboration tools",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "optima-dev-skills": "./bin/cli.js",
8
- "optima-query-db": "./dist/bin/helpers/query-db.js"
8
+ "optima-query-db": "./dist/bin/helpers/query-db.js",
9
+ "optima-generate-test-token": "./dist/bin/helpers/generate-test-token.js"
9
10
  },
10
11
  "scripts": {
11
12
  "postinstall": "node scripts/install.js",