@optima-chat/dev-skills 0.5.4 → 0.6.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/generate-test-token.md +16 -6
- package/.claude/skills/generate-test-token/SKILL.md +7 -3
- package/.claude/skills/use-commerce-cli/SKILL.md +7 -1
- package/README.md +44 -23
- package/bin/helpers/generate-test-token.ts +53 -15
- package/dist/bin/helpers/generate-test-token.js +45 -16
- package/package.json +1 -1
|
@@ -15,18 +15,22 @@
|
|
|
15
15
|
使用 `optima-generate-test-token` CLI 工具,它会自动完成所有设置:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
#
|
|
18
|
+
# Development 环境(默认)
|
|
19
19
|
optima-generate-test-token
|
|
20
20
|
|
|
21
|
+
# Production 环境
|
|
22
|
+
optima-generate-test-token --env production
|
|
23
|
+
|
|
21
24
|
# 自定义商户名称
|
|
22
|
-
optima-generate-test-token --business-name "我的测试店铺"
|
|
25
|
+
optima-generate-test-token --business-name "我的测试店铺" --env production
|
|
23
26
|
|
|
24
27
|
# 完全自定义
|
|
25
28
|
optima-generate-test-token \
|
|
26
29
|
--email "custom@example.com" \
|
|
27
30
|
--password "MyPass123" \
|
|
28
31
|
--business-name "Custom Shop" \
|
|
29
|
-
--phone "+1234567890"
|
|
32
|
+
--phone "+1234567890" \
|
|
33
|
+
--env production
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
## 工作流程
|
|
@@ -85,6 +89,7 @@ curl -H "Authorization: Bearer $(cat /tmp/optima-test-token-xxx.txt)" \
|
|
|
85
89
|
- `--business-name <name>` - 商户名称(默认:自动生成)
|
|
86
90
|
- `--phone <phone>` - 联系电话(可选)
|
|
87
91
|
- `--address <address>` - 地址(可选)
|
|
92
|
+
- `--env <environment>` - 环境:development(默认)或 production
|
|
88
93
|
- `--help, -h` - 显示帮助信息
|
|
89
94
|
|
|
90
95
|
## 示例
|
|
@@ -136,10 +141,10 @@ commerce product create \
|
|
|
136
141
|
|
|
137
142
|
## ⚠️ 注意事项
|
|
138
143
|
|
|
139
|
-
1.
|
|
144
|
+
1. **支持两个环境** - Development(默认)和 Production,通过 `--env` 参数指定
|
|
140
145
|
2. **Token 有效期** - Token 默认有效期 15 分钟,请及时使用
|
|
141
146
|
3. **临时文件** - Token 保存在系统临时目录,重启后可能被清理
|
|
142
|
-
4. **环境变量** - 使用 commerce CLI
|
|
147
|
+
4. **环境变量** - 使用 commerce CLI 时需要设置对应的 `OPTIMA_ENV`(development 或 production)
|
|
143
148
|
|
|
144
149
|
## 🔗 相关资源
|
|
145
150
|
|
|
@@ -154,7 +159,12 @@ commerce product create \
|
|
|
154
159
|
2. `POST /api/v1/oauth/token` - 获取 access token(password grant)
|
|
155
160
|
3. `POST /api/merchants/me` - 设置 merchant profile
|
|
156
161
|
|
|
157
|
-
|
|
162
|
+
**环境配置**:
|
|
163
|
+
|
|
164
|
+
| 环境 | Auth API | Commerce API | Client ID |
|
|
165
|
+
|------|----------|--------------|-----------|
|
|
166
|
+
| Development(默认) | auth.optima.chat | api.optima.chat | dev-skill-cli-he7fjmsp |
|
|
167
|
+
| Production | auth.optima.shop | api.optima.shop | dev-skill-cli-0cyyqxox |
|
|
158
168
|
|
|
159
169
|
**默认 Merchant 信息**:
|
|
160
170
|
- 发货地址:中国深圳南山区科技园
|
|
@@ -36,17 +36,21 @@ optima-generate-test-token [options]
|
|
|
36
36
|
### 基本使用
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
#
|
|
39
|
+
# Development 环境(默认)
|
|
40
40
|
optima-generate-test-token
|
|
41
41
|
|
|
42
|
+
# Production 环境
|
|
43
|
+
optima-generate-test-token --env production
|
|
44
|
+
|
|
42
45
|
# 自定义商户名称
|
|
43
|
-
optima-generate-test-token --business-name "我的测试店铺"
|
|
46
|
+
optima-generate-test-token --business-name "我的测试店铺" --env production
|
|
44
47
|
|
|
45
48
|
# 完全自定义
|
|
46
49
|
optima-generate-test-token \
|
|
47
50
|
--email "test@example.com" \
|
|
48
51
|
--password "MyPassword123" \
|
|
49
|
-
--business-name "测试商店"
|
|
52
|
+
--business-name "测试商店" \
|
|
53
|
+
--env production
|
|
50
54
|
```
|
|
51
55
|
|
|
52
56
|
### 使用生成的 Token
|
|
@@ -53,6 +53,12 @@ commerce init
|
|
|
53
53
|
|
|
54
54
|
## 环境说明
|
|
55
55
|
|
|
56
|
-
`optima-generate-test-token`
|
|
56
|
+
`optima-generate-test-token` 支持两个环境:
|
|
57
|
+
|
|
58
|
+
**Development**(默认):
|
|
57
59
|
- API: `api.optima.chat`
|
|
58
60
|
- 环境变量:`OPTIMA_ENV=development`
|
|
61
|
+
|
|
62
|
+
**Production**(使用 `--env production`):
|
|
63
|
+
- API: `api.optima.shop`
|
|
64
|
+
- 环境变量:`OPTIMA_ENV=production`
|
package/README.md
CHANGED
|
@@ -23,13 +23,14 @@ Optima Dev Skills 让 Claude Code 能够直接在 **CI、Stage、Prod** 三个
|
|
|
23
23
|
- **任务驱动** - 基于具体任务场景(查看日志、调用 API),不是抽象分类
|
|
24
24
|
- **跨环境协作** - 统一的命令在 CI、Stage、Prod 三个环境中使用
|
|
25
25
|
|
|
26
|
-
## 📋 任务场景(
|
|
26
|
+
## 📋 任务场景(4 个)
|
|
27
27
|
|
|
28
28
|
当 Claude Code 识别到以下任务时,会自动加载对应的 Skill:
|
|
29
29
|
|
|
30
30
|
- **logs** - 查看 CI/Stage/Prod 的服务器日志
|
|
31
31
|
- **query-db** - 查询 CI/Stage/Prod 的数据库
|
|
32
32
|
- **generate-test-token** - 生成测试 Access Token 用于 API 测试
|
|
33
|
+
- **use-commerce-cli** - 使用 Commerce CLI 管理电商店铺
|
|
33
34
|
|
|
34
35
|
## 👤 用户故事
|
|
35
36
|
|
|
@@ -103,14 +104,20 @@ Claude:
|
|
|
103
104
|
optima-dev-skills/
|
|
104
105
|
├── .claude/
|
|
105
106
|
│ ├── commands/
|
|
106
|
-
│ │ ├── logs.md
|
|
107
|
-
│ │
|
|
107
|
+
│ │ ├── logs.md # /logs - 查看服务日志
|
|
108
|
+
│ │ ├── query-db.md # /query-db - 查询数据库
|
|
109
|
+
│ │ └── generate-test-token.md # /generate-test-token - 生成测试 token
|
|
108
110
|
│ │
|
|
109
111
|
│ └── skills/
|
|
110
|
-
│ ├── logs/
|
|
111
|
-
│
|
|
112
|
-
│
|
|
113
|
-
│
|
|
112
|
+
│ ├── logs/ # 日志查看 skill
|
|
113
|
+
│ ├── query-db/ # 数据库查询 skill
|
|
114
|
+
│ ├── generate-test-token/ # 测试 token 生成 skill
|
|
115
|
+
│ └── use-commerce-cli/ # Commerce CLI 使用 skill
|
|
116
|
+
│
|
|
117
|
+
├── bin/
|
|
118
|
+
│ └── helpers/
|
|
119
|
+
│ ├── query-db.ts # CLI: 数据库查询
|
|
120
|
+
│ └── generate-test-token.ts # CLI: 生成测试 token
|
|
114
121
|
│
|
|
115
122
|
└── docs/
|
|
116
123
|
└── COMMANDS_DESIGN.md
|
|
@@ -132,22 +139,35 @@ Claude:
|
|
|
132
139
|
3. 问题定位:Stage RDS 连接配置问题
|
|
133
140
|
```
|
|
134
141
|
|
|
135
|
-
### 示例 2
|
|
142
|
+
### 示例 2:生成测试 token 并管理店铺
|
|
136
143
|
|
|
137
144
|
```bash
|
|
138
|
-
#
|
|
139
|
-
$ optima-
|
|
145
|
+
# 1. 生成测试 token
|
|
146
|
+
$ optima-generate-test-token
|
|
147
|
+
|
|
148
|
+
✅ Test token generated successfully!
|
|
149
|
+
📁 Token File Path: /tmp/optima-test-token-xxx.txt
|
|
150
|
+
|
|
151
|
+
# 2. 使用 token 创建商品
|
|
152
|
+
$ OPTIMA_TOKEN=$(cat /tmp/optima-test-token-xxx.txt) \
|
|
153
|
+
OPTIMA_ENV=development \
|
|
154
|
+
commerce product create --title "测试商品" --price 99.99 --stock 100
|
|
155
|
+
|
|
156
|
+
{
|
|
157
|
+
"success": true,
|
|
158
|
+
"data": {
|
|
159
|
+
"product_id": "xxx",
|
|
160
|
+
"name": "测试商品",
|
|
161
|
+
"price": "99.99"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
140
165
|
|
|
141
|
-
|
|
142
|
-
✓ Loaded Infisical config from GitHub Variables
|
|
143
|
-
✓ Obtained Infisical access token
|
|
144
|
-
✓ Retrieved database credentials from Infisical
|
|
145
|
-
✓ SSH tunnel established on port 15433
|
|
166
|
+
### 示例 3:使用 CLI 工具快速查询
|
|
146
167
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
(1 行记录)
|
|
168
|
+
```bash
|
|
169
|
+
# 查询 Prod 用户数
|
|
170
|
+
$ optima-query-db user-auth "SELECT COUNT(*) FROM users" prod
|
|
151
171
|
|
|
152
172
|
# 查询 Stage 商品列表
|
|
153
173
|
$ optima-query-db commerce-backend "SELECT id, title FROM products LIMIT 5" stage
|
|
@@ -202,16 +222,17 @@ $ optima-query-db commerce-backend "SELECT id, title FROM products LIMIT 5" stag
|
|
|
202
222
|
|
|
203
223
|
## 🛠️ 开发状态
|
|
204
224
|
|
|
205
|
-
**当前版本**: 0.5.
|
|
225
|
+
**当前版本**: 0.5.4
|
|
206
226
|
|
|
207
227
|
**已完成**:
|
|
208
|
-
- ✅
|
|
209
|
-
- ✅
|
|
228
|
+
- ✅ 3 个跨环境命令:`/logs`、`/query-db`、`/generate-test-token`
|
|
229
|
+
- ✅ 4 个任务场景:`logs`、`query-db`、`generate-test-token`、`use-commerce-cli`
|
|
210
230
|
- ✅ 支持 CI、Stage、Prod 三个环境
|
|
211
231
|
- ✅ CI 环境通过 SSH + Docker 访问
|
|
212
232
|
- ✅ Stage/Prod 通过 SSH 隧道访问 RDS
|
|
213
|
-
- ✅ TypeScript CLI 工具:`optima-query-db`
|
|
233
|
+
- ✅ TypeScript CLI 工具:`optima-query-db`、`optima-generate-test-token`
|
|
214
234
|
- ✅ 通过 Infisical 动态获取密钥
|
|
235
|
+
- ✅ 自动生成测试 token 并设置 merchant profile
|
|
215
236
|
|
|
216
237
|
**设计原则**:
|
|
217
238
|
- 命令提供信息(URL、路径、凭证位置),不实现复杂逻辑
|
|
@@ -24,9 +24,29 @@ interface MerchantSetupResponse {
|
|
|
24
24
|
user_id: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
type Environment = 'development' | 'production';
|
|
28
|
+
|
|
29
|
+
interface EnvironmentConfig {
|
|
30
|
+
authUrl: string;
|
|
31
|
+
apiUrl: string;
|
|
32
|
+
clientId: string;
|
|
33
|
+
envName: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ENV_CONFIG: Record<Environment, EnvironmentConfig> = {
|
|
37
|
+
development: {
|
|
38
|
+
authUrl: 'https://auth.optima.chat',
|
|
39
|
+
apiUrl: 'https://api.optima.chat',
|
|
40
|
+
clientId: 'dev-skill-cli-he7fjmsp',
|
|
41
|
+
envName: 'development'
|
|
42
|
+
},
|
|
43
|
+
production: {
|
|
44
|
+
authUrl: 'https://auth.optima.shop',
|
|
45
|
+
apiUrl: 'https://api.optima.shop',
|
|
46
|
+
clientId: 'dev-skill-cli-0cyyqxox',
|
|
47
|
+
envName: 'production'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
30
50
|
|
|
31
51
|
async function httpRequest<T>(url: string, options: RequestInit = {}): Promise<T> {
|
|
32
52
|
const response = await fetch(url, {
|
|
@@ -49,6 +69,7 @@ async function registerMerchant(
|
|
|
49
69
|
email: string,
|
|
50
70
|
password: string,
|
|
51
71
|
businessName: string,
|
|
72
|
+
config: EnvironmentConfig,
|
|
52
73
|
phone?: string,
|
|
53
74
|
address?: string
|
|
54
75
|
): Promise<RegisterResponse> {
|
|
@@ -59,7 +80,7 @@ async function registerMerchant(
|
|
|
59
80
|
if (address) payload.address = address;
|
|
60
81
|
|
|
61
82
|
try {
|
|
62
|
-
const result = await httpRequest<RegisterResponse>(`${
|
|
83
|
+
const result = await httpRequest<RegisterResponse>(`${config.authUrl}/api/v1/auth/register/merchant`, {
|
|
63
84
|
method: 'POST',
|
|
64
85
|
body: JSON.stringify(payload)
|
|
65
86
|
});
|
|
@@ -75,16 +96,16 @@ async function registerMerchant(
|
|
|
75
96
|
}
|
|
76
97
|
}
|
|
77
98
|
|
|
78
|
-
async function getToken(email: string, password: string,
|
|
99
|
+
async function getToken(email: string, password: string, config: EnvironmentConfig): Promise<string> {
|
|
79
100
|
console.log(`\n🔑 Obtaining access token...`);
|
|
80
101
|
|
|
81
102
|
const formData = new URLSearchParams();
|
|
82
103
|
formData.append('username', email);
|
|
83
104
|
formData.append('password', password);
|
|
84
105
|
formData.append('grant_type', 'password');
|
|
85
|
-
formData.append('client_id', clientId);
|
|
106
|
+
formData.append('client_id', config.clientId);
|
|
86
107
|
|
|
87
|
-
const result = await httpRequest<TokenResponse>(`${
|
|
108
|
+
const result = await httpRequest<TokenResponse>(`${config.authUrl}/api/v1/oauth/token`, {
|
|
88
109
|
method: 'POST',
|
|
89
110
|
headers: {
|
|
90
111
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
@@ -96,7 +117,7 @@ async function getToken(email: string, password: string, clientId: string = DEFA
|
|
|
96
117
|
return result.access_token;
|
|
97
118
|
}
|
|
98
119
|
|
|
99
|
-
async function setupMerchantProfile(token: string, businessName: string): Promise<MerchantSetupResponse> {
|
|
120
|
+
async function setupMerchantProfile(token: string, businessName: string, config: EnvironmentConfig): Promise<MerchantSetupResponse> {
|
|
100
121
|
console.log(`\n🏪 Setting up merchant profile in Commerce API...`);
|
|
101
122
|
|
|
102
123
|
const payload = {
|
|
@@ -111,7 +132,7 @@ async function setupMerchantProfile(token: string, businessName: string): Promis
|
|
|
111
132
|
};
|
|
112
133
|
|
|
113
134
|
try {
|
|
114
|
-
const result = await httpRequest<MerchantSetupResponse>(`${
|
|
135
|
+
const result = await httpRequest<MerchantSetupResponse>(`${config.apiUrl}/api/merchants/me`, {
|
|
115
136
|
method: 'POST',
|
|
116
137
|
headers: {
|
|
117
138
|
Authorization: `Bearer ${token}`
|
|
@@ -145,6 +166,7 @@ async function main() {
|
|
|
145
166
|
let businessName = defaultBusinessName;
|
|
146
167
|
let phone: string | undefined;
|
|
147
168
|
let address: string | undefined;
|
|
169
|
+
let environment: Environment = 'development';
|
|
148
170
|
|
|
149
171
|
// 解析命令行参数
|
|
150
172
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -160,6 +182,14 @@ async function main() {
|
|
|
160
182
|
phone = args[++i];
|
|
161
183
|
} else if (arg === '--address' && args[i + 1]) {
|
|
162
184
|
address = args[++i];
|
|
185
|
+
} else if (arg === '--env' && args[i + 1]) {
|
|
186
|
+
const envArg = args[++i];
|
|
187
|
+
if (envArg === 'development' || envArg === 'production') {
|
|
188
|
+
environment = envArg;
|
|
189
|
+
} else {
|
|
190
|
+
console.error(`❌ Invalid environment: ${envArg}. Must be 'development' or 'production'.`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
163
193
|
} else if (arg === '--help' || arg === '-h') {
|
|
164
194
|
console.log(`
|
|
165
195
|
Usage: generate-test-token [options]
|
|
@@ -170,32 +200,39 @@ Options:
|
|
|
170
200
|
--business-name <name> Merchant business name (default: auto-generated)
|
|
171
201
|
--phone <phone> Merchant phone number (optional)
|
|
172
202
|
--address <address> Merchant address (optional)
|
|
203
|
+
--env <environment> Environment: development (default) or production
|
|
173
204
|
--help, -h Show this help message
|
|
174
205
|
|
|
175
206
|
Example:
|
|
176
207
|
generate-test-token
|
|
208
|
+
generate-test-token --env production
|
|
177
209
|
generate-test-token --business-name "My Test Shop" --phone "+1234567890"
|
|
178
|
-
generate-test-token --email "custom@example.com" --password "MyPass123"
|
|
210
|
+
generate-test-token --email "custom@example.com" --password "MyPass123" --env production
|
|
179
211
|
`);
|
|
180
212
|
process.exit(0);
|
|
181
213
|
}
|
|
182
214
|
}
|
|
183
215
|
|
|
216
|
+
const config = ENV_CONFIG[environment];
|
|
217
|
+
|
|
184
218
|
try {
|
|
185
219
|
console.log('🚀 Starting test token generation...\n');
|
|
220
|
+
console.log(`Environment: ${config.envName}`);
|
|
221
|
+
console.log(`Auth API: ${config.authUrl}`);
|
|
222
|
+
console.log(`Commerce API: ${config.apiUrl}\n`);
|
|
186
223
|
console.log(`Using credentials:`);
|
|
187
224
|
console.log(` Email: ${email}`);
|
|
188
225
|
console.log(` Password: ${password}`);
|
|
189
226
|
console.log(` Business Name: ${businessName}`);
|
|
190
227
|
|
|
191
228
|
// 1. 注册 merchant(直接注册为商家)
|
|
192
|
-
const user = await registerMerchant(email, password, businessName, phone, address);
|
|
229
|
+
const user = await registerMerchant(email, password, businessName, config, phone, address);
|
|
193
230
|
|
|
194
231
|
// 2. 获取 token
|
|
195
|
-
const token = await getToken(email, password);
|
|
232
|
+
const token = await getToken(email, password, config);
|
|
196
233
|
|
|
197
234
|
// 3. 设置 merchant profile(Commerce API)
|
|
198
|
-
const merchantProfile = await setupMerchantProfile(token, businessName);
|
|
235
|
+
const merchantProfile = await setupMerchantProfile(token, businessName, config);
|
|
199
236
|
|
|
200
237
|
// 4. 保存 token 到临时文件
|
|
201
238
|
const tmpDir = os.tmpdir();
|
|
@@ -209,6 +246,7 @@ Example:
|
|
|
209
246
|
console.log('\n' + '='.repeat(80));
|
|
210
247
|
console.log('✅ Test token generated successfully!\n');
|
|
211
248
|
console.log('📋 Details:');
|
|
249
|
+
console.log(` Environment: ${config.envName}`);
|
|
212
250
|
console.log(` Email: ${email}`);
|
|
213
251
|
console.log(` Password: ${password}`);
|
|
214
252
|
console.log(` User ID: ${user.user_id || 'N/A'}`);
|
|
@@ -221,9 +259,9 @@ Example:
|
|
|
221
259
|
console.log(` # Read token from file:`);
|
|
222
260
|
console.log(` TOKEN=$(cat ${tokenFilePath})\n`);
|
|
223
261
|
console.log(` # Use with commerce CLI:`);
|
|
224
|
-
console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV
|
|
262
|
+
console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV=${config.envName} commerce product list\n`);
|
|
225
263
|
console.log(` # Use in curl:`);
|
|
226
|
-
console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})"
|
|
264
|
+
console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})" ${config.apiUrl}/api/products\n`);
|
|
227
265
|
console.log('='.repeat(80));
|
|
228
266
|
|
|
229
267
|
} catch (error: any) {
|
|
@@ -37,9 +37,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const os = __importStar(require("os"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const ENV_CONFIG = {
|
|
41
|
+
development: {
|
|
42
|
+
authUrl: 'https://auth.optima.chat',
|
|
43
|
+
apiUrl: 'https://api.optima.chat',
|
|
44
|
+
clientId: 'dev-skill-cli-he7fjmsp',
|
|
45
|
+
envName: 'development'
|
|
46
|
+
},
|
|
47
|
+
production: {
|
|
48
|
+
authUrl: 'https://auth.optima.shop',
|
|
49
|
+
apiUrl: 'https://api.optima.shop',
|
|
50
|
+
clientId: 'dev-skill-cli-0cyyqxox',
|
|
51
|
+
envName: 'production'
|
|
52
|
+
}
|
|
53
|
+
};
|
|
43
54
|
async function httpRequest(url, options = {}) {
|
|
44
55
|
const response = await fetch(url, {
|
|
45
56
|
...options,
|
|
@@ -54,7 +65,7 @@ async function httpRequest(url, options = {}) {
|
|
|
54
65
|
}
|
|
55
66
|
return response.json();
|
|
56
67
|
}
|
|
57
|
-
async function registerMerchant(email, password, businessName, phone, address) {
|
|
68
|
+
async function registerMerchant(email, password, businessName, config, phone, address) {
|
|
58
69
|
console.log(`\n📝 Registering merchant: ${email}...`);
|
|
59
70
|
const payload = { email, password, business_name: businessName };
|
|
60
71
|
if (phone)
|
|
@@ -62,7 +73,7 @@ async function registerMerchant(email, password, businessName, phone, address) {
|
|
|
62
73
|
if (address)
|
|
63
74
|
payload.address = address;
|
|
64
75
|
try {
|
|
65
|
-
const result = await httpRequest(`${
|
|
76
|
+
const result = await httpRequest(`${config.authUrl}/api/v1/auth/register/merchant`, {
|
|
66
77
|
method: 'POST',
|
|
67
78
|
body: JSON.stringify(payload)
|
|
68
79
|
});
|
|
@@ -77,14 +88,14 @@ async function registerMerchant(email, password, businessName, phone, address) {
|
|
|
77
88
|
throw error;
|
|
78
89
|
}
|
|
79
90
|
}
|
|
80
|
-
async function getToken(email, password,
|
|
91
|
+
async function getToken(email, password, config) {
|
|
81
92
|
console.log(`\n🔑 Obtaining access token...`);
|
|
82
93
|
const formData = new URLSearchParams();
|
|
83
94
|
formData.append('username', email);
|
|
84
95
|
formData.append('password', password);
|
|
85
96
|
formData.append('grant_type', 'password');
|
|
86
|
-
formData.append('client_id', clientId);
|
|
87
|
-
const result = await httpRequest(`${
|
|
97
|
+
formData.append('client_id', config.clientId);
|
|
98
|
+
const result = await httpRequest(`${config.authUrl}/api/v1/oauth/token`, {
|
|
88
99
|
method: 'POST',
|
|
89
100
|
headers: {
|
|
90
101
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
@@ -94,7 +105,7 @@ async function getToken(email, password, clientId = DEFAULT_CLIENT_ID) {
|
|
|
94
105
|
console.log(`✓ Access token obtained`);
|
|
95
106
|
return result.access_token;
|
|
96
107
|
}
|
|
97
|
-
async function setupMerchantProfile(token, businessName) {
|
|
108
|
+
async function setupMerchantProfile(token, businessName, config) {
|
|
98
109
|
console.log(`\n🏪 Setting up merchant profile in Commerce API...`);
|
|
99
110
|
const payload = {
|
|
100
111
|
name: businessName,
|
|
@@ -107,7 +118,7 @@ async function setupMerchantProfile(token, businessName) {
|
|
|
107
118
|
contact_email: 'test@example.com'
|
|
108
119
|
};
|
|
109
120
|
try {
|
|
110
|
-
const result = await httpRequest(`${
|
|
121
|
+
const result = await httpRequest(`${config.apiUrl}/api/merchants/me`, {
|
|
111
122
|
method: 'POST',
|
|
112
123
|
headers: {
|
|
113
124
|
Authorization: `Bearer ${token}`
|
|
@@ -138,6 +149,7 @@ async function main() {
|
|
|
138
149
|
let businessName = defaultBusinessName;
|
|
139
150
|
let phone;
|
|
140
151
|
let address;
|
|
152
|
+
let environment = 'development';
|
|
141
153
|
// 解析命令行参数
|
|
142
154
|
for (let i = 0; i < args.length; i++) {
|
|
143
155
|
const arg = args[i];
|
|
@@ -156,6 +168,16 @@ async function main() {
|
|
|
156
168
|
else if (arg === '--address' && args[i + 1]) {
|
|
157
169
|
address = args[++i];
|
|
158
170
|
}
|
|
171
|
+
else if (arg === '--env' && args[i + 1]) {
|
|
172
|
+
const envArg = args[++i];
|
|
173
|
+
if (envArg === 'development' || envArg === 'production') {
|
|
174
|
+
environment = envArg;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
console.error(`❌ Invalid environment: ${envArg}. Must be 'development' or 'production'.`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
159
181
|
else if (arg === '--help' || arg === '-h') {
|
|
160
182
|
console.log(`
|
|
161
183
|
Usage: generate-test-token [options]
|
|
@@ -166,28 +188,34 @@ Options:
|
|
|
166
188
|
--business-name <name> Merchant business name (default: auto-generated)
|
|
167
189
|
--phone <phone> Merchant phone number (optional)
|
|
168
190
|
--address <address> Merchant address (optional)
|
|
191
|
+
--env <environment> Environment: development (default) or production
|
|
169
192
|
--help, -h Show this help message
|
|
170
193
|
|
|
171
194
|
Example:
|
|
172
195
|
generate-test-token
|
|
196
|
+
generate-test-token --env production
|
|
173
197
|
generate-test-token --business-name "My Test Shop" --phone "+1234567890"
|
|
174
|
-
generate-test-token --email "custom@example.com" --password "MyPass123"
|
|
198
|
+
generate-test-token --email "custom@example.com" --password "MyPass123" --env production
|
|
175
199
|
`);
|
|
176
200
|
process.exit(0);
|
|
177
201
|
}
|
|
178
202
|
}
|
|
203
|
+
const config = ENV_CONFIG[environment];
|
|
179
204
|
try {
|
|
180
205
|
console.log('🚀 Starting test token generation...\n');
|
|
206
|
+
console.log(`Environment: ${config.envName}`);
|
|
207
|
+
console.log(`Auth API: ${config.authUrl}`);
|
|
208
|
+
console.log(`Commerce API: ${config.apiUrl}\n`);
|
|
181
209
|
console.log(`Using credentials:`);
|
|
182
210
|
console.log(` Email: ${email}`);
|
|
183
211
|
console.log(` Password: ${password}`);
|
|
184
212
|
console.log(` Business Name: ${businessName}`);
|
|
185
213
|
// 1. 注册 merchant(直接注册为商家)
|
|
186
|
-
const user = await registerMerchant(email, password, businessName, phone, address);
|
|
214
|
+
const user = await registerMerchant(email, password, businessName, config, phone, address);
|
|
187
215
|
// 2. 获取 token
|
|
188
|
-
const token = await getToken(email, password);
|
|
216
|
+
const token = await getToken(email, password, config);
|
|
189
217
|
// 3. 设置 merchant profile(Commerce API)
|
|
190
|
-
const merchantProfile = await setupMerchantProfile(token, businessName);
|
|
218
|
+
const merchantProfile = await setupMerchantProfile(token, businessName, config);
|
|
191
219
|
// 4. 保存 token 到临时文件
|
|
192
220
|
const tmpDir = os.tmpdir();
|
|
193
221
|
const tokenFileName = `optima-test-token-${Date.now()}.txt`;
|
|
@@ -198,6 +226,7 @@ Example:
|
|
|
198
226
|
console.log('\n' + '='.repeat(80));
|
|
199
227
|
console.log('✅ Test token generated successfully!\n');
|
|
200
228
|
console.log('📋 Details:');
|
|
229
|
+
console.log(` Environment: ${config.envName}`);
|
|
201
230
|
console.log(` Email: ${email}`);
|
|
202
231
|
console.log(` Password: ${password}`);
|
|
203
232
|
console.log(` User ID: ${user.user_id || 'N/A'}`);
|
|
@@ -210,9 +239,9 @@ Example:
|
|
|
210
239
|
console.log(` # Read token from file:`);
|
|
211
240
|
console.log(` TOKEN=$(cat ${tokenFilePath})\n`);
|
|
212
241
|
console.log(` # Use with commerce CLI:`);
|
|
213
|
-
console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV
|
|
242
|
+
console.log(` OPTIMA_TOKEN=$(cat ${tokenFilePath}) OPTIMA_ENV=${config.envName} commerce product list\n`);
|
|
214
243
|
console.log(` # Use in curl:`);
|
|
215
|
-
console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})"
|
|
244
|
+
console.log(` curl -H "Authorization: Bearer $(cat ${tokenFilePath})" ${config.apiUrl}/api/products\n`);
|
|
216
245
|
console.log('='.repeat(80));
|
|
217
246
|
}
|
|
218
247
|
catch (error) {
|