@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.
- package/.claude/commands/generate-test-token.md +162 -0
- package/.claude/settings.local.json +5 -4
- package/.claude/skills/generate-test-token/SKILL.md +312 -0
- package/.claude/skills/use-commerce-cli/SKILL.md +58 -0
- package/README.md +8 -3
- package/bin/helpers/generate-test-token.ts +235 -0
- package/dist/bin/helpers/generate-test-token.js +223 -0
- package/package.json +3 -2
|
@@ -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(
|
|
30
|
-
"Bash(curl -s
|
|
31
|
-
"Bash(
|
|
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
|
-
## 📋 任务场景(
|
|
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
|
-
- ✅
|
|
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
|
+
"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",
|