byteplan-cli 1.2.0 → 1.2.2
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/package.json +1 -1
- package/src/api.js +78 -22
- package/src/cli.js +7 -0
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -6,7 +6,7 @@ import Conf from 'conf';
|
|
|
6
6
|
import dotenv from 'dotenv';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import { join } from 'path';
|
|
9
|
-
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
10
10
|
|
|
11
11
|
const configDir = join(homedir(), '.byteplan');
|
|
12
12
|
const envFile = join(configDir, '.env');
|
|
@@ -38,6 +38,30 @@ const DEFAULT_MENU_HEADERS = {
|
|
|
38
38
|
let currentEnv = process.env.BP_ENV || 'uat';
|
|
39
39
|
let currentToken = process.env.ACCESS_TOKEN || null;
|
|
40
40
|
|
|
41
|
+
// 统一的响应处理函数
|
|
42
|
+
async function handleResponse(response) {
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
|
|
45
|
+
// 检查 HTTP 状态码
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
// 401 表示 token 无效或过期
|
|
48
|
+
if (response.status === 401) {
|
|
49
|
+
throw new Error('Token invalid or expired. Please run "byteplan login" to re-authenticate.');
|
|
50
|
+
}
|
|
51
|
+
// 其他 HTTP 错误
|
|
52
|
+
const errMsg = data.message || data.error_description || data.msg || `HTTP ${response.status}`;
|
|
53
|
+
throw new Error('API error: ' + errMsg);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 检查响应中的错误字段(有些 API 返回 200 但包含错误信息)
|
|
57
|
+
if (data.error || data.code === 'ERROR' || data.success === false) {
|
|
58
|
+
const errMsg = data.message || data.msg || data.error_description || JSON.stringify(data);
|
|
59
|
+
throw new Error('API error: ' + errMsg);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return data;
|
|
63
|
+
}
|
|
64
|
+
|
|
41
65
|
export function setEnvironment(env) {
|
|
42
66
|
if (ENVIRONMENTS[env]) {
|
|
43
67
|
currentEnv = env;
|
|
@@ -87,7 +111,7 @@ export async function getPublicKey() {
|
|
|
87
111
|
// 保存凭证到 .env
|
|
88
112
|
function saveCredentials(data) {
|
|
89
113
|
const envPath = join(homedir(), '.byteplan', '.env');
|
|
90
|
-
|
|
114
|
+
|
|
91
115
|
const lines = [];
|
|
92
116
|
lines.push('BP_ENV=' + currentEnv);
|
|
93
117
|
lines.push('BP_USER=' + data.username);
|
|
@@ -101,10 +125,42 @@ function saveCredentials(data) {
|
|
|
101
125
|
if (data.expiresIn) {
|
|
102
126
|
lines.push('TOKEN_EXPIRES_IN=' + (Date.now() + data.expiresIn * 1000));
|
|
103
127
|
}
|
|
104
|
-
|
|
128
|
+
|
|
105
129
|
writeFileSync(envPath, lines.join('\n') + '\n');
|
|
106
130
|
}
|
|
107
131
|
|
|
132
|
+
// 保存 token 到 .env(切换租户时使用)
|
|
133
|
+
export function saveToken(accessToken, refreshToken, expiresIn) {
|
|
134
|
+
const envPath = join(homedir(), '.byteplan', '.env');
|
|
135
|
+
|
|
136
|
+
// 读取现有的 .env 内容
|
|
137
|
+
let existingLines = [];
|
|
138
|
+
if (existsSync(envPath)) {
|
|
139
|
+
existingLines = readFileSync(envPath, 'utf-8').split('\n').filter(line =>
|
|
140
|
+
!line.startsWith('ACCESS_TOKEN=') &&
|
|
141
|
+
!line.startsWith('REFRESH_TOKEN=') &&
|
|
142
|
+
!line.startsWith('TOKEN_EXPIRES_IN=')
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 添加新的 token 信息
|
|
147
|
+
const newLines = [...existingLines];
|
|
148
|
+
if (accessToken) {
|
|
149
|
+
newLines.push('ACCESS_TOKEN=' + accessToken);
|
|
150
|
+
}
|
|
151
|
+
if (refreshToken) {
|
|
152
|
+
newLines.push('REFRESH_TOKEN=' + refreshToken);
|
|
153
|
+
}
|
|
154
|
+
if (expiresIn) {
|
|
155
|
+
newLines.push('TOKEN_EXPIRES_IN=' + (Date.now() + expiresIn * 1000));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
writeFileSync(envPath, newLines.join('\n') + '\n');
|
|
159
|
+
|
|
160
|
+
// 更新内存中的 token
|
|
161
|
+
setToken(accessToken);
|
|
162
|
+
}
|
|
163
|
+
|
|
108
164
|
// 登录
|
|
109
165
|
export async function login(username, password, env = 'uat') {
|
|
110
166
|
if (env) setEnvironment(env);
|
|
@@ -212,8 +268,8 @@ export async function getUserInfo(token) {
|
|
|
212
268
|
'authorization': 'Bearer ' + (token || currentToken),
|
|
213
269
|
},
|
|
214
270
|
});
|
|
215
|
-
|
|
216
|
-
return response
|
|
271
|
+
|
|
272
|
+
return handleResponse(response);
|
|
217
273
|
}
|
|
218
274
|
|
|
219
275
|
// 切换租户
|
|
@@ -227,27 +283,27 @@ export async function switchTenant(token, tenantId) {
|
|
|
227
283
|
'authorization': 'Bearer ' + (token || currentToken),
|
|
228
284
|
},
|
|
229
285
|
});
|
|
230
|
-
|
|
231
|
-
return response
|
|
286
|
+
|
|
287
|
+
return handleResponse(response);
|
|
232
288
|
}
|
|
233
289
|
|
|
234
290
|
// 查询模型列表
|
|
235
291
|
export async function queryModels(token, options = {}) {
|
|
236
292
|
const { page = 0, size = 100 } = options;
|
|
237
293
|
const baseUrl = getBaseUrl();
|
|
238
|
-
|
|
294
|
+
|
|
239
295
|
const headers = {
|
|
240
296
|
'accept': 'application/json, text/plain, */*',
|
|
241
297
|
'authorization': 'Bearer ' + (token || currentToken),
|
|
242
298
|
...DEFAULT_MENU_HEADERS,
|
|
243
299
|
};
|
|
244
|
-
|
|
300
|
+
|
|
245
301
|
const response = await fetch(baseUrl + '/data/api/model/query?page=' + page + '&size=' + size, {
|
|
246
302
|
method: 'GET',
|
|
247
303
|
headers,
|
|
248
304
|
});
|
|
249
|
-
|
|
250
|
-
return response
|
|
305
|
+
|
|
306
|
+
return handleResponse(response);
|
|
251
307
|
}
|
|
252
308
|
|
|
253
309
|
// 获取模型字段
|
|
@@ -263,8 +319,8 @@ export async function getModelColumns(token, modelCodes) {
|
|
|
263
319
|
},
|
|
264
320
|
body: JSON.stringify(modelCodes),
|
|
265
321
|
});
|
|
266
|
-
|
|
267
|
-
return response
|
|
322
|
+
|
|
323
|
+
return handleResponse(response);
|
|
268
324
|
}
|
|
269
325
|
|
|
270
326
|
// 查询模型数据
|
|
@@ -283,15 +339,15 @@ export async function getModelData(token, modelCode, params = {}) {
|
|
|
283
339
|
...params,
|
|
284
340
|
}),
|
|
285
341
|
});
|
|
286
|
-
|
|
287
|
-
return response
|
|
342
|
+
|
|
343
|
+
return handleResponse(response);
|
|
288
344
|
}
|
|
289
345
|
|
|
290
346
|
// 获取维度值
|
|
291
347
|
export async function getDimValues(token, dimCode, options = {}) {
|
|
292
348
|
const { page = 0, size = 100 } = options;
|
|
293
349
|
const baseUrl = getBaseUrl();
|
|
294
|
-
|
|
350
|
+
|
|
295
351
|
const response = await fetch(baseUrl + '/data/api/online/lov/DATA_DIM_VALUE_LOV?dimCode=' + dimCode + '&page=' + page + '&size=' + size, {
|
|
296
352
|
method: 'POST',
|
|
297
353
|
headers: {
|
|
@@ -302,18 +358,18 @@ export async function getDimValues(token, dimCode, options = {}) {
|
|
|
302
358
|
},
|
|
303
359
|
body: JSON.stringify({ dimCode, page, size }),
|
|
304
360
|
});
|
|
305
|
-
|
|
306
|
-
return response
|
|
361
|
+
|
|
362
|
+
return handleResponse(response);
|
|
307
363
|
}
|
|
308
364
|
|
|
309
365
|
// 获取 LOV 值
|
|
310
366
|
export async function getLovValues(token, lovCode, options = {}) {
|
|
311
367
|
const { keywords = null } = options;
|
|
312
368
|
const baseUrl = getBaseUrl();
|
|
313
|
-
|
|
369
|
+
|
|
314
370
|
const body = {};
|
|
315
371
|
if (keywords) body.keywords = keywords;
|
|
316
|
-
|
|
372
|
+
|
|
317
373
|
const response = await fetch(baseUrl + '/data/api/online/lov/' + lovCode, {
|
|
318
374
|
method: 'POST',
|
|
319
375
|
headers: {
|
|
@@ -324,6 +380,6 @@ export async function getLovValues(token, lovCode, options = {}) {
|
|
|
324
380
|
},
|
|
325
381
|
body: JSON.stringify(body),
|
|
326
382
|
});
|
|
327
|
-
|
|
328
|
-
return response
|
|
383
|
+
|
|
384
|
+
return handleResponse(response);
|
|
329
385
|
}
|
package/src/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getModelData,
|
|
17
17
|
getDimValues,
|
|
18
18
|
getLovValues,
|
|
19
|
+
saveToken,
|
|
19
20
|
} from './api.js';
|
|
20
21
|
import { skillsCmd } from './commands/skills.js';
|
|
21
22
|
|
|
@@ -141,12 +142,18 @@ tenantCmd
|
|
|
141
142
|
await loginWithEnv();
|
|
142
143
|
const result = await switchTenant(null, tenantId);
|
|
143
144
|
|
|
145
|
+
// 保存切换后的新 token
|
|
146
|
+
if (result.access_token) {
|
|
147
|
+
saveToken(result.access_token, result.refresh_token, result.expires_in);
|
|
148
|
+
}
|
|
149
|
+
|
|
144
150
|
printJSON({
|
|
145
151
|
success: true,
|
|
146
152
|
tenant: {
|
|
147
153
|
tenantId: tenantId,
|
|
148
154
|
tenantName: result.data?.tenantName || '',
|
|
149
155
|
},
|
|
156
|
+
tokenUpdated: !!result.access_token,
|
|
150
157
|
});
|
|
151
158
|
} catch (error) {
|
|
152
159
|
printError(error);
|