@optima-chat/commerce-cli 1.5.1 → 1.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/dist/api/rest/auth.d.ts +0 -4
- package/dist/api/rest/auth.d.ts.map +1 -1
- package/dist/api/rest/auth.js +1 -17
- package/dist/api/rest/auth.js.map +1 -1
- package/dist/api/rest/base.d.ts +1 -1
- package/dist/api/rest/base.js +4 -4
- package/dist/api/rest/base.js.map +1 -1
- package/dist/commands/auth/index.d.ts.map +1 -1
- package/dist/commands/auth/index.js +1 -5
- package/dist/commands/auth/index.js.map +1 -1
- package/dist/commands/auth/login.d.ts.map +1 -1
- package/dist/commands/auth/login.js +61 -15
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.d.ts.map +1 -1
- package/dist/commands/auth/logout.js +10 -56
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/whoami.d.ts.map +1 -1
- package/dist/commands/auth/whoami.js +34 -26
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/utils/config.d.ts +13 -45
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +128 -214
- package/dist/utils/config.js.map +1 -1
- package/package.json +1 -2
- package/dist/commands/auth/switch.d.ts +0 -3
- package/dist/commands/auth/switch.d.ts.map +0 -1
- package/dist/commands/auth/switch.js +0 -111
- package/dist/commands/auth/switch.js.map +0 -1
- package/dist/commands/auth/test-refresh.d.ts +0 -3
- package/dist/commands/auth/test-refresh.d.ts.map +0 -1
- package/dist/commands/auth/test-refresh.js +0 -43
- package/dist/commands/auth/test-refresh.js.map +0 -1
package/dist/utils/config.d.ts
CHANGED
|
@@ -2,25 +2,20 @@ export type Environment = 'production' | 'stage' | 'development';
|
|
|
2
2
|
interface UserData {
|
|
3
3
|
id: string;
|
|
4
4
|
email: string;
|
|
5
|
-
name
|
|
6
|
-
role: string;
|
|
5
|
+
name?: string;
|
|
7
6
|
}
|
|
8
7
|
interface EnvironmentConfig {
|
|
9
8
|
authUrl: string;
|
|
10
9
|
apiUrl: string;
|
|
11
10
|
storeDomain: string;
|
|
12
11
|
clientId: string;
|
|
13
|
-
configFile: string;
|
|
14
12
|
}
|
|
15
13
|
export declare const ENV_CONFIG: Record<Environment, EnvironmentConfig>;
|
|
16
14
|
/**
|
|
17
|
-
*
|
|
15
|
+
* 获取当前环境
|
|
16
|
+
* 优先级:OPTIMA_ENV 环境变量 > token.json 的 env 字段 > 默认 production
|
|
18
17
|
*/
|
|
19
18
|
export declare function getCurrentEnvironment(): Environment;
|
|
20
|
-
/**
|
|
21
|
-
* 设置当前激活的环境
|
|
22
|
-
*/
|
|
23
|
-
export declare function setCurrentEnvironment(env: Environment): void;
|
|
24
19
|
/**
|
|
25
20
|
* 获取当前环境的配置信息
|
|
26
21
|
*/
|
|
@@ -28,10 +23,10 @@ export declare function getCurrentEnvConfig(): EnvironmentConfig;
|
|
|
28
23
|
/**
|
|
29
24
|
* 保存认证令牌
|
|
30
25
|
*/
|
|
31
|
-
export declare function saveTokens(access_token: string, refresh_token: string, expires_in: number): void;
|
|
26
|
+
export declare function saveTokens(access_token: string, refresh_token: string, expires_in: number, env: Environment, user?: UserData): void;
|
|
32
27
|
/**
|
|
33
|
-
*
|
|
34
|
-
* 优先级:OPTIMA_TOKEN 环境变量 > ~/.optima/token
|
|
28
|
+
* 获取访问令牌
|
|
29
|
+
* 优先级:OPTIMA_TOKEN 环境变量 > ~/.optima/token.json
|
|
35
30
|
*/
|
|
36
31
|
export declare function getAccessToken(): string | null;
|
|
37
32
|
/**
|
|
@@ -39,28 +34,21 @@ export declare function getAccessToken(): string | null;
|
|
|
39
34
|
*/
|
|
40
35
|
export declare function getTokenExpiresAt(): number | null;
|
|
41
36
|
/**
|
|
42
|
-
* 检查 token
|
|
43
|
-
* 采用提前 5 分钟刷新策略,避免以下问题:
|
|
44
|
-
* 1. 请求过程中 token 过期
|
|
45
|
-
* 2. 网络延迟导致刷新不及时
|
|
37
|
+
* 检查 token 是否过期
|
|
46
38
|
*/
|
|
47
39
|
export declare function isTokenExpired(): boolean;
|
|
48
|
-
/**
|
|
49
|
-
* 获取刷新令牌
|
|
50
|
-
*/
|
|
51
|
-
export declare function getRefreshToken(): string | null;
|
|
52
40
|
/**
|
|
53
41
|
* 检查是否已认证(不检查过期)
|
|
54
42
|
*/
|
|
55
43
|
export declare function isAuthenticated(): boolean;
|
|
56
44
|
/**
|
|
57
|
-
*
|
|
45
|
+
* 确保有效的访问令牌
|
|
58
46
|
* @returns 有效的访问令牌,如果无法获取则返回 null
|
|
59
|
-
* @throws AuthenticationError 当 token
|
|
47
|
+
* @throws AuthenticationError 当 token 过期时
|
|
60
48
|
*/
|
|
61
49
|
export declare function ensureValidToken(): Promise<string | null>;
|
|
62
50
|
/**
|
|
63
|
-
*
|
|
51
|
+
* 保存用户信息到 token.json
|
|
64
52
|
*/
|
|
65
53
|
export declare function saveUser(user: UserData): void;
|
|
66
54
|
/**
|
|
@@ -68,45 +56,25 @@ export declare function saveUser(user: UserData): void;
|
|
|
68
56
|
*/
|
|
69
57
|
export declare function getUser(): UserData | null;
|
|
70
58
|
/**
|
|
71
|
-
*
|
|
59
|
+
* 清除配置(登出)- 删除 token.json
|
|
72
60
|
*/
|
|
73
61
|
export declare function clearConfig(): void;
|
|
74
|
-
/**
|
|
75
|
-
* 清除指定环境的配置
|
|
76
|
-
*/
|
|
77
|
-
export declare function clearConfigForEnv(env: Environment): void;
|
|
78
|
-
/**
|
|
79
|
-
* 清除所有环境的配置
|
|
80
|
-
*/
|
|
81
|
-
export declare function clearAllConfigs(): void;
|
|
82
62
|
/**
|
|
83
63
|
* 获取配置文件路径
|
|
84
64
|
*/
|
|
85
65
|
export declare function getConfigPath(): string;
|
|
86
66
|
/**
|
|
87
67
|
* 获取 Commerce API URL
|
|
88
|
-
* 优先级:环境变量 >
|
|
68
|
+
* 优先级:环境变量 > 当前环境配置
|
|
89
69
|
*/
|
|
90
70
|
export declare function getApiUrl(): string;
|
|
91
71
|
/**
|
|
92
72
|
* 获取 Auth API URL
|
|
93
|
-
* 优先级:环境变量 >
|
|
73
|
+
* 优先级:环境变量 > 当前环境配置
|
|
94
74
|
*/
|
|
95
75
|
export declare function getAuthUrl(): string;
|
|
96
|
-
/**
|
|
97
|
-
* 设置 Commerce API URL
|
|
98
|
-
*/
|
|
99
|
-
export declare function setApiUrl(url: string): void;
|
|
100
|
-
/**
|
|
101
|
-
* 设置 Auth API URL
|
|
102
|
-
*/
|
|
103
|
-
export declare function setAuthUrl(url: string): void;
|
|
104
76
|
/**
|
|
105
77
|
* 获取店铺前端域名
|
|
106
|
-
* 根据当前环境返回对应的前端域名
|
|
107
|
-
* - production: optima.shop
|
|
108
|
-
* - stage: stage.optima.shop
|
|
109
|
-
* - development: optima.sh
|
|
110
78
|
*/
|
|
111
79
|
export declare function getStoreDomain(): string;
|
|
112
80
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,OAAO,GAAG,aAAa,CAAC;AAKjE,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAcD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAmB7D,CAAC;AAoFF;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,CAenD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,iBAAiB,CAGvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,WAAW,EAChB,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAWN;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAS9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAGjD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CASxC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+B/D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAM7C;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,QAAQ,GAAG,IAAI,CAGzC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAGvC"}
|
package/dist/utils/config.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Conf from 'conf';
|
|
2
1
|
import { readFileSync, existsSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';
|
|
3
2
|
import { join } from 'path';
|
|
4
3
|
import { homedir } from 'os';
|
|
@@ -9,95 +8,110 @@ export const ENV_CONFIG = {
|
|
|
9
8
|
apiUrl: 'https://api.optima.shop',
|
|
10
9
|
storeDomain: 'optima.shop',
|
|
11
10
|
clientId: 'optima-cli-cwkbnadr',
|
|
12
|
-
configFile: 'config-prod.json',
|
|
13
11
|
},
|
|
14
12
|
stage: {
|
|
15
|
-
authUrl: 'https://auth
|
|
13
|
+
authUrl: 'https://auth.stage.optima.onl',
|
|
16
14
|
apiUrl: 'https://api-stage.optima.shop',
|
|
17
15
|
storeDomain: 'stage.optima.shop',
|
|
18
16
|
clientId: 'optima-cli-c5ljkuwx',
|
|
19
|
-
configFile: 'config-stage.json',
|
|
20
17
|
},
|
|
21
18
|
development: {
|
|
22
19
|
authUrl: 'https://auth.optima.chat',
|
|
23
20
|
apiUrl: 'https://api.optima.chat',
|
|
24
21
|
storeDomain: 'optima.sh',
|
|
25
22
|
clientId: 'optima-cli-q1hiavyg',
|
|
26
|
-
configFile: 'config-dev.json',
|
|
27
23
|
},
|
|
28
24
|
};
|
|
29
|
-
// ==============
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
//
|
|
33
|
-
const configCache = new Map();
|
|
25
|
+
// ============== Token 文件路径 ==============
|
|
26
|
+
const OPTIMA_DIR = join(homedir(), '.optima');
|
|
27
|
+
const TOKEN_FILE = join(OPTIMA_DIR, 'token.json');
|
|
28
|
+
// ============== 环境映射 ==============
|
|
34
29
|
/**
|
|
35
|
-
*
|
|
30
|
+
* 将 token.json 的 env 字段映射到 Environment 类型
|
|
36
31
|
*/
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
function tokenEnvToEnvironment(tokenEnv) {
|
|
33
|
+
switch (tokenEnv) {
|
|
34
|
+
case 'prod':
|
|
35
|
+
return 'production';
|
|
36
|
+
case 'stage':
|
|
37
|
+
return 'stage';
|
|
38
|
+
case 'ci':
|
|
39
|
+
return 'development';
|
|
40
|
+
default:
|
|
41
|
+
return 'production';
|
|
40
42
|
}
|
|
41
|
-
const envConfig = ENV_CONFIG[env];
|
|
42
|
-
const conf = new Conf({
|
|
43
|
-
projectName: 'commerce-cli',
|
|
44
|
-
configName: envConfig.configFile.replace('.json', ''), // Conf 会自动添加 .json
|
|
45
|
-
encryptionKey: 'commerce-cli-secret-key-2025',
|
|
46
|
-
defaults: {
|
|
47
|
-
tokens: null,
|
|
48
|
-
user: null,
|
|
49
|
-
api_url: envConfig.apiUrl,
|
|
50
|
-
auth_url: envConfig.authUrl,
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
configCache.set(env, conf);
|
|
54
|
-
return conf;
|
|
55
43
|
}
|
|
56
44
|
/**
|
|
57
|
-
*
|
|
45
|
+
* 将 Environment 类型映射到 token.json 的 env 字段
|
|
58
46
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
function environmentToTokenEnv(env) {
|
|
48
|
+
switch (env) {
|
|
49
|
+
case 'production':
|
|
50
|
+
return 'prod';
|
|
51
|
+
case 'stage':
|
|
52
|
+
return 'stage';
|
|
53
|
+
case 'development':
|
|
54
|
+
return 'ci';
|
|
55
|
+
default:
|
|
56
|
+
return 'prod';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ============== Token 文件操作 ==============
|
|
60
|
+
/**
|
|
61
|
+
* 从 ~/.optima/token.json 读取 token 数据
|
|
62
|
+
*/
|
|
63
|
+
function getOptimaToken() {
|
|
64
|
+
if (!existsSync(TOKEN_FILE)) {
|
|
65
|
+
return null;
|
|
64
66
|
}
|
|
65
|
-
// 2. 从配置文件读取
|
|
66
67
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (data.env && ['production', 'stage', 'development'].includes(data.env)) {
|
|
70
|
-
return data.env;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
68
|
+
const content = readFileSync(TOKEN_FILE, 'utf-8');
|
|
69
|
+
return JSON.parse(content);
|
|
73
70
|
}
|
|
74
71
|
catch (error) {
|
|
75
|
-
//
|
|
72
|
+
// 文件读取或解析失败
|
|
73
|
+
return null;
|
|
76
74
|
}
|
|
77
|
-
// 3. 默认使用生产环境
|
|
78
|
-
return 'production';
|
|
79
75
|
}
|
|
80
76
|
/**
|
|
81
|
-
*
|
|
77
|
+
* 保存 token 到 ~/.optima/token.json
|
|
78
|
+
*/
|
|
79
|
+
function saveOptimaToken(token) {
|
|
80
|
+
// 确保目录存在
|
|
81
|
+
mkdirSync(OPTIMA_DIR, { recursive: true });
|
|
82
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(token, null, 2), 'utf-8');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 删除 ~/.optima/token.json
|
|
82
86
|
*/
|
|
83
|
-
|
|
87
|
+
function deleteOptimaToken() {
|
|
84
88
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const data = { env };
|
|
89
|
-
writeFileSync(currentEnvFile, JSON.stringify(data, null, 2), 'utf-8');
|
|
89
|
+
if (existsSync(TOKEN_FILE)) {
|
|
90
|
+
unlinkSync(TOKEN_FILE);
|
|
91
|
+
}
|
|
90
92
|
}
|
|
91
93
|
catch (error) {
|
|
92
|
-
|
|
94
|
+
// 忽略删除失败
|
|
93
95
|
}
|
|
94
96
|
}
|
|
97
|
+
// ============== 公开 API ==============
|
|
95
98
|
/**
|
|
96
|
-
*
|
|
99
|
+
* 获取当前环境
|
|
100
|
+
* 优先级:OPTIMA_ENV 环境变量 > token.json 的 env 字段 > 默认 production
|
|
97
101
|
*/
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
export function getCurrentEnvironment() {
|
|
103
|
+
// 1. 优先从环境变量读取
|
|
104
|
+
const envFromEnv = process.env.OPTIMA_ENV;
|
|
105
|
+
if (envFromEnv && ['production', 'stage', 'development'].includes(envFromEnv)) {
|
|
106
|
+
return envFromEnv;
|
|
107
|
+
}
|
|
108
|
+
// 2. 从 token.json 读取
|
|
109
|
+
const token = getOptimaToken();
|
|
110
|
+
if (token?.env) {
|
|
111
|
+
return tokenEnvToEnvironment(token.env);
|
|
112
|
+
}
|
|
113
|
+
// 3. 默认使用生产环境
|
|
114
|
+
return 'production';
|
|
101
115
|
}
|
|
102
116
|
/**
|
|
103
117
|
* 获取当前环境的配置信息
|
|
@@ -106,247 +120,147 @@ export function getCurrentEnvConfig() {
|
|
|
106
120
|
const env = getCurrentEnvironment();
|
|
107
121
|
return ENV_CONFIG[env];
|
|
108
122
|
}
|
|
109
|
-
// ============== 向后兼容的配置变量(使用当前环境) ==============
|
|
110
|
-
const config = getConfig();
|
|
111
|
-
/**
|
|
112
|
-
* 从 ~/.optima/token 文件读取 token
|
|
113
|
-
*/
|
|
114
|
-
function getTokenFromFile() {
|
|
115
|
-
const tokenFile = join(homedir(), '.optima', 'token');
|
|
116
|
-
if (!existsSync(tokenFile)) {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
try {
|
|
120
|
-
return readFileSync(tokenFile, 'utf-8').trim();
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
// 文件读取失败,返回 null
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
123
|
/**
|
|
128
124
|
* 保存认证令牌
|
|
129
125
|
*/
|
|
130
|
-
export function saveTokens(access_token, refresh_token, expires_in) {
|
|
126
|
+
export function saveTokens(access_token, refresh_token, expires_in, env, user) {
|
|
131
127
|
const expires_at = Date.now() + expires_in * 1000;
|
|
132
|
-
|
|
128
|
+
const token = {
|
|
129
|
+
env: environmentToTokenEnv(env),
|
|
133
130
|
access_token,
|
|
134
131
|
refresh_token,
|
|
135
|
-
|
|
132
|
+
token_type: 'Bearer',
|
|
136
133
|
expires_at,
|
|
137
|
-
|
|
134
|
+
user,
|
|
135
|
+
};
|
|
136
|
+
saveOptimaToken(token);
|
|
138
137
|
}
|
|
139
138
|
/**
|
|
140
|
-
*
|
|
141
|
-
* 优先级:OPTIMA_TOKEN 环境变量 > ~/.optima/token
|
|
139
|
+
* 获取访问令牌
|
|
140
|
+
* 优先级:OPTIMA_TOKEN 环境变量 > ~/.optima/token.json
|
|
142
141
|
*/
|
|
143
142
|
export function getAccessToken() {
|
|
144
143
|
// 1. 优先从环境变量读取
|
|
145
144
|
if (process.env.OPTIMA_TOKEN) {
|
|
146
145
|
return process.env.OPTIMA_TOKEN;
|
|
147
146
|
}
|
|
148
|
-
// 2. 从
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
return tokenFromFile;
|
|
152
|
-
}
|
|
153
|
-
// 3. 从配置文件读取
|
|
154
|
-
const tokens = config.get('tokens');
|
|
155
|
-
if (!tokens)
|
|
156
|
-
return null;
|
|
157
|
-
return tokens.access_token;
|
|
147
|
+
// 2. 从 token.json 读取
|
|
148
|
+
const token = getOptimaToken();
|
|
149
|
+
return token?.access_token ?? null;
|
|
158
150
|
}
|
|
159
|
-
/**
|
|
160
|
-
* 提前刷新的缓冲时间(5 分钟)
|
|
161
|
-
* 在 token 过期前 5 分钟就开始刷新,避免请求过程中 token 过期
|
|
162
|
-
*/
|
|
163
|
-
const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
164
151
|
/**
|
|
165
152
|
* 获取 token 过期时间
|
|
166
153
|
*/
|
|
167
154
|
export function getTokenExpiresAt() {
|
|
168
|
-
const
|
|
169
|
-
return
|
|
155
|
+
const token = getOptimaToken();
|
|
156
|
+
return token?.expires_at ?? null;
|
|
170
157
|
}
|
|
171
158
|
/**
|
|
172
|
-
* 检查 token
|
|
173
|
-
* 采用提前 5 分钟刷新策略,避免以下问题:
|
|
174
|
-
* 1. 请求过程中 token 过期
|
|
175
|
-
* 2. 网络延迟导致刷新不及时
|
|
159
|
+
* 检查 token 是否过期
|
|
176
160
|
*/
|
|
177
161
|
export function isTokenExpired() {
|
|
162
|
+
// 环境变量 token 不检查过期
|
|
163
|
+
if (process.env.OPTIMA_TOKEN) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
178
166
|
const expiresAt = getTokenExpiresAt();
|
|
179
167
|
if (!expiresAt)
|
|
180
168
|
return true;
|
|
181
|
-
return Date.now() >=
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* 获取刷新令牌
|
|
185
|
-
*/
|
|
186
|
-
export function getRefreshToken() {
|
|
187
|
-
const tokens = config.get('tokens');
|
|
188
|
-
return tokens?.refresh_token ?? null;
|
|
169
|
+
return Date.now() >= expiresAt;
|
|
189
170
|
}
|
|
190
171
|
/**
|
|
191
172
|
* 检查是否已认证(不检查过期)
|
|
192
173
|
*/
|
|
193
174
|
export function isAuthenticated() {
|
|
194
|
-
// 环境变量或配置文件中有 token
|
|
195
175
|
const token = getAccessToken();
|
|
196
176
|
return token !== null;
|
|
197
177
|
}
|
|
198
178
|
/**
|
|
199
|
-
*
|
|
179
|
+
* 确保有效的访问令牌
|
|
200
180
|
* @returns 有效的访问令牌,如果无法获取则返回 null
|
|
201
|
-
* @throws AuthenticationError 当 token
|
|
181
|
+
* @throws AuthenticationError 当 token 过期时
|
|
202
182
|
*/
|
|
203
183
|
export async function ensureValidToken() {
|
|
204
|
-
// 1. 如果使用环境变量 token
|
|
184
|
+
// 1. 如果使用环境变量 token,直接返回(不检查过期)
|
|
205
185
|
if (process.env.OPTIMA_TOKEN) {
|
|
206
186
|
if (process.env.DEBUG === 'true') {
|
|
207
187
|
console.log('[Token] Using OPTIMA_TOKEN environment variable');
|
|
208
188
|
}
|
|
209
189
|
return process.env.OPTIMA_TOKEN;
|
|
210
190
|
}
|
|
211
|
-
// 2.
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
console.log('[Token] Using token from ~/.optima/token file');
|
|
216
|
-
}
|
|
217
|
-
return tokenFromFile;
|
|
218
|
-
}
|
|
219
|
-
// 3. 使用配置文件 token(支持自动刷新)
|
|
220
|
-
const tokens = config.get('tokens');
|
|
221
|
-
if (!tokens) {
|
|
222
|
-
// 没有保存的 token,需要登录
|
|
191
|
+
// 2. 从 token.json 读取
|
|
192
|
+
const token = getOptimaToken();
|
|
193
|
+
if (!token) {
|
|
194
|
+
// 没有 token,需要登录
|
|
223
195
|
return null;
|
|
224
196
|
}
|
|
225
|
-
//
|
|
226
|
-
if (
|
|
197
|
+
// 3. 检查是否过期
|
|
198
|
+
if (Date.now() >= token.expires_at) {
|
|
227
199
|
if (process.env.DEBUG === 'true') {
|
|
228
|
-
|
|
229
|
-
console.log(`[Token] Valid token, expires in ${remaining} minutes`);
|
|
200
|
+
console.log('[Token] Token expired');
|
|
230
201
|
}
|
|
231
|
-
return tokens.access_token;
|
|
232
|
-
}
|
|
233
|
-
// Token 已过期,尝试刷新
|
|
234
|
-
if (process.env.DEBUG === 'true') {
|
|
235
|
-
console.log('[Token] Token expired, attempting refresh...');
|
|
236
|
-
}
|
|
237
|
-
try {
|
|
238
|
-
// 动态导入避免循环依赖
|
|
239
|
-
const { authApi } = await import('../api/rest/auth.js');
|
|
240
|
-
const result = await authApi.refreshToken(tokens.refresh_token);
|
|
241
|
-
if (result.access_token && result.refresh_token && result.expires_in) {
|
|
242
|
-
// 保存新的 token
|
|
243
|
-
saveTokens(result.access_token, result.refresh_token, result.expires_in);
|
|
244
|
-
if (process.env.DEBUG === 'true') {
|
|
245
|
-
console.log(`[Token] Refresh successful, new token expires in ${result.expires_in / 60} minutes`);
|
|
246
|
-
}
|
|
247
|
-
return result.access_token;
|
|
248
|
-
}
|
|
249
|
-
// 刷新失败,清除配置并抛出错误
|
|
250
|
-
clearConfig();
|
|
251
202
|
const { AuthenticationError } = await import('./error.js');
|
|
252
|
-
throw new AuthenticationError('登录已过期,请重新登录: commerce auth login');
|
|
203
|
+
throw new AuthenticationError('登录已过期,请重新登录: commerce auth login 或 optima');
|
|
253
204
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// 如果已经是 AuthenticationError,直接抛出
|
|
258
|
-
if (error.name === 'AuthenticationError') {
|
|
259
|
-
throw error;
|
|
260
|
-
}
|
|
261
|
-
// 其他错误(网络问题等),包装成 AuthenticationError
|
|
262
|
-
const { AuthenticationError } = await import('./error.js');
|
|
263
|
-
const message = error.response?.data?.error_description || error.message || '未知错误';
|
|
264
|
-
throw new AuthenticationError(`Token 刷新失败: ${message}。请重新登录: commerce auth login`);
|
|
205
|
+
if (process.env.DEBUG === 'true') {
|
|
206
|
+
const remaining = Math.floor((token.expires_at - Date.now()) / 1000 / 60);
|
|
207
|
+
console.log(`[Token] Valid token, expires in ${remaining} minutes`);
|
|
265
208
|
}
|
|
209
|
+
return token.access_token;
|
|
266
210
|
}
|
|
267
211
|
/**
|
|
268
|
-
*
|
|
212
|
+
* 保存用户信息到 token.json
|
|
269
213
|
*/
|
|
270
214
|
export function saveUser(user) {
|
|
271
|
-
|
|
215
|
+
const token = getOptimaToken();
|
|
216
|
+
if (token) {
|
|
217
|
+
token.user = user;
|
|
218
|
+
saveOptimaToken(token);
|
|
219
|
+
}
|
|
272
220
|
}
|
|
273
221
|
/**
|
|
274
222
|
* 获取当前用户信息
|
|
275
223
|
*/
|
|
276
224
|
export function getUser() {
|
|
277
|
-
|
|
225
|
+
const token = getOptimaToken();
|
|
226
|
+
return token?.user ?? null;
|
|
278
227
|
}
|
|
279
228
|
/**
|
|
280
|
-
*
|
|
229
|
+
* 清除配置(登出)- 删除 token.json
|
|
281
230
|
*/
|
|
282
231
|
export function clearConfig() {
|
|
283
|
-
|
|
284
|
-
currentConfig.clear();
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* 清除指定环境的配置
|
|
288
|
-
*/
|
|
289
|
-
export function clearConfigForEnv(env) {
|
|
290
|
-
const conf = getConfigForEnv(env);
|
|
291
|
-
conf.clear();
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* 清除所有环境的配置
|
|
295
|
-
*/
|
|
296
|
-
export function clearAllConfigs() {
|
|
297
|
-
const environments = ['production', 'stage', 'development'];
|
|
298
|
-
environments.forEach(env => {
|
|
299
|
-
const conf = getConfigForEnv(env);
|
|
300
|
-
conf.clear();
|
|
301
|
-
});
|
|
302
|
-
// 同时清除当前环境标记
|
|
303
|
-
try {
|
|
304
|
-
if (existsSync(currentEnvFile)) {
|
|
305
|
-
unlinkSync(currentEnvFile);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
catch (error) {
|
|
309
|
-
// 忽略错误
|
|
310
|
-
}
|
|
232
|
+
deleteOptimaToken();
|
|
311
233
|
}
|
|
312
234
|
/**
|
|
313
235
|
* 获取配置文件路径
|
|
314
236
|
*/
|
|
315
237
|
export function getConfigPath() {
|
|
316
|
-
return
|
|
238
|
+
return TOKEN_FILE;
|
|
317
239
|
}
|
|
318
240
|
/**
|
|
319
241
|
* 获取 Commerce API URL
|
|
320
|
-
* 优先级:环境变量 >
|
|
242
|
+
* 优先级:环境变量 > 当前环境配置
|
|
321
243
|
*/
|
|
322
244
|
export function getApiUrl() {
|
|
323
|
-
|
|
245
|
+
if (process.env.OPTIMA_API_URL) {
|
|
246
|
+
return process.env.OPTIMA_API_URL;
|
|
247
|
+
}
|
|
248
|
+
const envConfig = getCurrentEnvConfig();
|
|
249
|
+
return envConfig.apiUrl;
|
|
324
250
|
}
|
|
325
251
|
/**
|
|
326
252
|
* 获取 Auth API URL
|
|
327
|
-
* 优先级:环境变量 >
|
|
253
|
+
* 优先级:环境变量 > 当前环境配置
|
|
328
254
|
*/
|
|
329
255
|
export function getAuthUrl() {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
export function setApiUrl(url) {
|
|
336
|
-
config.set('api_url', url);
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* 设置 Auth API URL
|
|
340
|
-
*/
|
|
341
|
-
export function setAuthUrl(url) {
|
|
342
|
-
config.set('auth_url', url);
|
|
256
|
+
if (process.env.OPTIMA_AUTH_URL) {
|
|
257
|
+
return process.env.OPTIMA_AUTH_URL;
|
|
258
|
+
}
|
|
259
|
+
const envConfig = getCurrentEnvConfig();
|
|
260
|
+
return envConfig.authUrl;
|
|
343
261
|
}
|
|
344
262
|
/**
|
|
345
263
|
* 获取店铺前端域名
|
|
346
|
-
* 根据当前环境返回对应的前端域名
|
|
347
|
-
* - production: optima.shop
|
|
348
|
-
* - stage: stage.optima.shop
|
|
349
|
-
* - development: optima.sh
|
|
350
264
|
*/
|
|
351
265
|
export function getStoreDomain() {
|
|
352
266
|
const env = getCurrentEnvironment();
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|