@optima-chat/ads-cli 0.5.0 → 0.7.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/LICENSE +21 -0
- package/dist/commands/account/check.d.ts.map +1 -1
- package/dist/commands/account/check.js +16 -163
- package/dist/commands/account/check.js.map +1 -1
- package/dist/commands/account/create.d.ts.map +1 -1
- package/dist/commands/account/create.js +0 -40
- package/dist/commands/account/create.js.map +1 -1
- package/dist/commands/account/index.d.ts.map +1 -1
- package/dist/commands/account/index.js +2 -2
- package/dist/commands/account/index.js.map +1 -1
- package/dist/commands/account/link.d.ts +6 -0
- package/dist/commands/account/link.d.ts.map +1 -0
- package/dist/commands/account/link.js +57 -0
- package/dist/commands/account/link.js.map +1 -0
- package/dist/commands/ad/create.js +2 -2
- package/dist/commands/ad/create.js.map +1 -1
- package/dist/commands/ad/delete.js +2 -2
- package/dist/commands/ad/delete.js.map +1 -1
- package/dist/commands/ad/info.js +2 -2
- package/dist/commands/ad/info.js.map +1 -1
- package/dist/commands/ad/list.js +2 -2
- package/dist/commands/ad/list.js.map +1 -1
- package/dist/commands/ad/update.d.ts +1 -1
- package/dist/commands/ad/update.js +3 -3
- package/dist/commands/ad/update.js.map +1 -1
- package/dist/commands/ad-group/create.d.ts.map +1 -1
- package/dist/commands/ad-group/create.js +10 -16
- package/dist/commands/ad-group/create.js.map +1 -1
- package/dist/commands/ad-group/delete.js +2 -2
- package/dist/commands/ad-group/delete.js.map +1 -1
- package/dist/commands/ad-group/info.js +2 -2
- package/dist/commands/ad-group/info.js.map +1 -1
- package/dist/commands/ad-group/list.d.ts.map +1 -1
- package/dist/commands/ad-group/list.js +4 -3
- package/dist/commands/ad-group/list.js.map +1 -1
- package/dist/commands/ad-group/update.js +2 -2
- package/dist/commands/ad-group/update.js.map +1 -1
- package/dist/commands/auth/login.d.ts +2 -4
- package/dist/commands/auth/login.d.ts.map +1 -1
- package/dist/commands/auth/login.js +68 -135
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.d.ts +2 -0
- package/dist/commands/auth/logout.d.ts.map +1 -1
- package/dist/commands/auth/logout.js +19 -17
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/status.d.ts +2 -0
- package/dist/commands/auth/status.d.ts.map +1 -1
- package/dist/commands/auth/status.js +36 -21
- package/dist/commands/auth/status.js.map +1 -1
- package/dist/commands/campaign/create.d.ts.map +1 -1
- package/dist/commands/campaign/create.js +9 -15
- package/dist/commands/campaign/create.js.map +1 -1
- package/dist/commands/campaign/delete.js +2 -2
- package/dist/commands/campaign/delete.js.map +1 -1
- package/dist/commands/campaign/info.js +2 -2
- package/dist/commands/campaign/info.js.map +1 -1
- package/dist/commands/campaign/list.js +2 -2
- package/dist/commands/campaign/list.js.map +1 -1
- package/dist/commands/campaign/update.js +2 -2
- package/dist/commands/campaign/update.js.map +1 -1
- package/dist/commands/keyword/add.d.ts.map +1 -1
- package/dist/commands/keyword/add.js +7 -6
- package/dist/commands/keyword/add.js.map +1 -1
- package/dist/commands/keyword/delete.js +2 -2
- package/dist/commands/keyword/delete.js.map +1 -1
- package/dist/commands/keyword/list.d.ts.map +1 -1
- package/dist/commands/keyword/list.js +4 -3
- package/dist/commands/keyword/list.js.map +1 -1
- package/dist/commands/keyword/update.js +2 -2
- package/dist/commands/keyword/update.js.map +1 -1
- package/dist/commands/query.js +2 -2
- package/dist/commands/query.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/lib/api-client.d.ts +2 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +7 -9
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/auth-types.d.ts +74 -0
- package/dist/lib/auth-types.d.ts.map +1 -0
- package/dist/lib/auth-types.js +24 -0
- package/dist/lib/auth-types.js.map +1 -0
- package/dist/lib/device-flow.d.ts +11 -0
- package/dist/lib/device-flow.d.ts.map +1 -0
- package/dist/lib/device-flow.js +111 -0
- package/dist/lib/device-flow.js.map +1 -0
- package/dist/lib/token-store.d.ts +43 -32
- package/dist/lib/token-store.d.ts.map +1 -1
- package/dist/lib/token-store.js +183 -81
- package/dist/lib/token-store.js.map +1 -1
- package/package.json +9 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Types - 认证相关类型定义
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 环境类型
|
|
6
|
+
*/
|
|
7
|
+
export type Environment = 'ci' | 'stage' | 'prod';
|
|
8
|
+
/**
|
|
9
|
+
* 环境配置
|
|
10
|
+
*/
|
|
11
|
+
export declare const ENV_CONFIG: Record<Environment, {
|
|
12
|
+
authUrl: string;
|
|
13
|
+
clientId: string;
|
|
14
|
+
adsApiUrl: string;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Device Code 响应
|
|
18
|
+
*/
|
|
19
|
+
export interface DeviceCodeResponse {
|
|
20
|
+
device_code: string;
|
|
21
|
+
user_code: string;
|
|
22
|
+
verification_uri: string;
|
|
23
|
+
verification_uri_complete?: string;
|
|
24
|
+
expires_in: number;
|
|
25
|
+
interval: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Token 响应
|
|
29
|
+
*/
|
|
30
|
+
export interface TokenResponse {
|
|
31
|
+
access_token: string;
|
|
32
|
+
refresh_token?: string;
|
|
33
|
+
token_type: string;
|
|
34
|
+
expires_in: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 存储的 Token 数据
|
|
38
|
+
*/
|
|
39
|
+
export interface TokenData {
|
|
40
|
+
env: Environment;
|
|
41
|
+
access_token: string;
|
|
42
|
+
refresh_token?: string;
|
|
43
|
+
token_type: string;
|
|
44
|
+
expires_at: number;
|
|
45
|
+
user?: UserInfo;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 用户信息
|
|
49
|
+
*/
|
|
50
|
+
export interface UserInfo {
|
|
51
|
+
id: string;
|
|
52
|
+
email: string;
|
|
53
|
+
name?: string;
|
|
54
|
+
avatar?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Device Flow 回调
|
|
58
|
+
*/
|
|
59
|
+
export interface DeviceFlowCallbacks {
|
|
60
|
+
onCodeReceived: (code: string, uri: string) => void;
|
|
61
|
+
onPolling?: () => void;
|
|
62
|
+
onSuccess: (user: UserInfo) => void;
|
|
63
|
+
onError: (error: string) => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 认证状态
|
|
67
|
+
*/
|
|
68
|
+
export interface AuthStatus {
|
|
69
|
+
loggedIn: boolean;
|
|
70
|
+
env?: Environment;
|
|
71
|
+
user?: UserInfo;
|
|
72
|
+
expiresAt?: number;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=auth-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-types.d.ts","sourceRoot":"","sources":["../../src/lib/auth-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAC7B,WAAW,EACX;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAiBzD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,WAAW,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Types - 认证相关类型定义
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 环境配置
|
|
6
|
+
*/
|
|
7
|
+
export const ENV_CONFIG = {
|
|
8
|
+
ci: {
|
|
9
|
+
authUrl: 'https://auth.optima.chat',
|
|
10
|
+
clientId: 'google-ads-cli-dev',
|
|
11
|
+
adsApiUrl: 'https://ads-api.optima.onl', // CI 环境用 prod API
|
|
12
|
+
},
|
|
13
|
+
stage: {
|
|
14
|
+
authUrl: 'https://auth.stage.optima.onl',
|
|
15
|
+
clientId: 'google-ads-cli-stage',
|
|
16
|
+
adsApiUrl: 'https://ads-api.stage.optima.onl',
|
|
17
|
+
},
|
|
18
|
+
prod: {
|
|
19
|
+
authUrl: 'https://auth.optima.onl',
|
|
20
|
+
clientId: 'google-ads-cli-prod',
|
|
21
|
+
adsApiUrl: 'https://ads-api.optima.onl',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=auth-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-types.js","sourceRoot":"","sources":["../../src/lib/auth-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAGnB;IACF,EAAE,EAAE;QACF,OAAO,EAAE,0BAA0B;QACnC,QAAQ,EAAE,oBAAoB;QAC9B,SAAS,EAAE,4BAA4B,EAAE,kBAAkB;KAC5D;IACD,KAAK,EAAE;QACL,OAAO,EAAE,+BAA+B;QACxC,QAAQ,EAAE,sBAAsB;QAChC,SAAS,EAAE,kCAAkC;KAC9C;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,yBAAyB;QAClC,QAAQ,EAAE,qBAAqB;QAC/B,SAAS,EAAE,4BAA4B;KACxC;CACF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Flow - OAuth2 设备授权流程
|
|
3
|
+
*
|
|
4
|
+
* 参考 optima-agent 实现,使用 Device Flow 进行登录
|
|
5
|
+
*/
|
|
6
|
+
import type { DeviceFlowCallbacks, Environment } from './auth-types.js';
|
|
7
|
+
/**
|
|
8
|
+
* 启动 Device Flow 登录
|
|
9
|
+
*/
|
|
10
|
+
export declare function startDeviceFlow(env: Environment, callbacks: DeviceFlowCallbacks, signal?: AbortSignal): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=device-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/lib/device-flow.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAGV,mBAAmB,EACnB,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAazB;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,mBAAmB,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAsHf"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Flow - OAuth2 设备授权流程
|
|
3
|
+
*
|
|
4
|
+
* 参考 optima-agent 实现,使用 Device Flow 进行登录
|
|
5
|
+
*/
|
|
6
|
+
import { ENV_CONFIG } from './auth-types.js';
|
|
7
|
+
import { saveToken, fetchUserInfo } from './token-store.js';
|
|
8
|
+
function sleep(ms) {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 启动 Device Flow 登录
|
|
13
|
+
*/
|
|
14
|
+
export async function startDeviceFlow(env, callbacks, signal) {
|
|
15
|
+
const { authUrl, clientId } = ENV_CONFIG[env];
|
|
16
|
+
// 1. 请求 device code
|
|
17
|
+
const codeRes = await fetch(`${authUrl}/api/v1/oauth/device/authorize`, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
body: JSON.stringify({ client_id: clientId }),
|
|
21
|
+
signal,
|
|
22
|
+
});
|
|
23
|
+
if (!codeRes.ok) {
|
|
24
|
+
const errorText = await codeRes.text();
|
|
25
|
+
throw new Error(`Failed to get device code: ${codeRes.status} ${errorText}`);
|
|
26
|
+
}
|
|
27
|
+
const codeData = (await codeRes.json());
|
|
28
|
+
// 2. 通知 UI 显示 code(优先使用带 code 的完整 URL)
|
|
29
|
+
const verificationUrl = codeData.verification_uri_complete || codeData.verification_uri;
|
|
30
|
+
callbacks.onCodeReceived(codeData.user_code, verificationUrl);
|
|
31
|
+
// 3. 轮询获取 token
|
|
32
|
+
const pollInterval = (codeData.interval || 5) * 1000;
|
|
33
|
+
const expiresAt = Date.now() + codeData.expires_in * 1000;
|
|
34
|
+
while (Date.now() < expiresAt) {
|
|
35
|
+
if (signal?.aborted) {
|
|
36
|
+
throw new Error('Login cancelled');
|
|
37
|
+
}
|
|
38
|
+
callbacks.onPolling?.();
|
|
39
|
+
await sleep(pollInterval);
|
|
40
|
+
if (signal?.aborted) {
|
|
41
|
+
throw new Error('Login cancelled');
|
|
42
|
+
}
|
|
43
|
+
const tokenRes = await fetch(`${authUrl}/api/v1/oauth/device/token`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
46
|
+
body: new URLSearchParams({
|
|
47
|
+
device_code: codeData.device_code,
|
|
48
|
+
client_id: clientId,
|
|
49
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
50
|
+
}),
|
|
51
|
+
signal,
|
|
52
|
+
});
|
|
53
|
+
// 解析响应
|
|
54
|
+
let responseBody;
|
|
55
|
+
try {
|
|
56
|
+
responseBody = await tokenRes.text();
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
responseBody = '';
|
|
60
|
+
}
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
let data;
|
|
63
|
+
try {
|
|
64
|
+
data = JSON.parse(responseBody);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
callbacks.onError(`Invalid response: ${responseBody}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// 成功获取 token(有 access_token 且无 error)
|
|
71
|
+
if (data.access_token && !data.error) {
|
|
72
|
+
const tokenData = data;
|
|
73
|
+
// 获取用户信息
|
|
74
|
+
let userInfo;
|
|
75
|
+
try {
|
|
76
|
+
userInfo = await fetchUserInfo(tokenData.access_token, env);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// 用户信息获取失败不影响登录
|
|
80
|
+
}
|
|
81
|
+
// 保存 token
|
|
82
|
+
saveToken(tokenData, env, userInfo);
|
|
83
|
+
callbacks.onSuccess(userInfo || { id: '', email: '' });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// 处理错误响应
|
|
87
|
+
const error = data;
|
|
88
|
+
// authorization_pending 是正常状态,继续轮询
|
|
89
|
+
if (error.error === 'authorization_pending') {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (error.error === 'slow_down') {
|
|
93
|
+
await sleep(5000); // 额外等待
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (error.error === 'expired_token') {
|
|
97
|
+
callbacks.onError('登录超时,请重试');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (error.error === 'access_denied') {
|
|
101
|
+
callbacks.onError('登录被拒绝');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// 其他错误,显示详情
|
|
105
|
+
const errorMsg = error.error_description || error.error || `HTTP ${tokenRes.status}`;
|
|
106
|
+
callbacks.onError(errorMsg);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
callbacks.onError('登录超时');
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=device-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-flow.js","sourceRoot":"","sources":["../../src/lib/device-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Token Store - Optima JWT Token 存储和管理
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. ~/.optima/token.json 文件
|
|
4
|
+
* Token 存储位置:~/.optima/token.json
|
|
5
|
+
* 与 optima-agent 兼容
|
|
7
6
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
import type { TokenData, TokenResponse, UserInfo, AuthStatus, Environment } from './auth-types.js';
|
|
8
|
+
/**
|
|
9
|
+
* 确保 ~/.optima 目录存在
|
|
10
|
+
*/
|
|
11
|
+
export declare function ensureOptimaDir(): void;
|
|
12
|
+
/**
|
|
13
|
+
* 保存 Token
|
|
14
|
+
*/
|
|
15
|
+
export declare function saveToken(response: TokenResponse, env: Environment, user?: UserInfo): void;
|
|
16
|
+
/**
|
|
17
|
+
* 读取 Token(按优先级)
|
|
18
|
+
*/
|
|
19
|
+
export declare function getToken(): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* 读取完整 Token 数据
|
|
22
|
+
*/
|
|
23
|
+
export declare function getTokenData(): TokenData | null;
|
|
24
|
+
/**
|
|
25
|
+
* 清除 Token
|
|
26
|
+
*/
|
|
27
|
+
export declare function clearToken(): void;
|
|
28
|
+
/**
|
|
29
|
+
* 检查 Token 是否过期
|
|
30
|
+
*/
|
|
31
|
+
export declare function isTokenExpired(data?: TokenData | null): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 获取用户信息
|
|
34
|
+
*/
|
|
35
|
+
export declare function fetchUserInfo(accessToken: string, env: Environment): Promise<UserInfo>;
|
|
29
36
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @deprecated 使用 TokenStore 类替代
|
|
37
|
+
* 获取认证状态
|
|
32
38
|
*/
|
|
33
|
-
export declare function
|
|
39
|
+
export declare function getAuthStatus(): Promise<AuthStatus>;
|
|
34
40
|
/**
|
|
35
|
-
*
|
|
36
|
-
* @deprecated 使用 TokenStore 类替代
|
|
41
|
+
* 刷新 Token
|
|
37
42
|
*/
|
|
38
|
-
export declare function
|
|
43
|
+
export declare function refreshToken(): Promise<boolean>;
|
|
39
44
|
/**
|
|
40
|
-
*
|
|
45
|
+
* 获取当前环境的 Ads API URL
|
|
41
46
|
*/
|
|
42
|
-
export declare function
|
|
47
|
+
export declare function getAdsApiUrl(): string;
|
|
48
|
+
export declare class TokenStore {
|
|
49
|
+
getToken(): Promise<string | null>;
|
|
50
|
+
hasToken(): Promise<boolean>;
|
|
51
|
+
saveToken(accessToken: string, refreshToken?: string): Promise<void>;
|
|
52
|
+
clearToken(): Promise<void>;
|
|
53
|
+
}
|
|
43
54
|
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/lib/token-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/lib/token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,QAAQ,EACR,UAAU,EACV,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAMzB;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,WAAW,EAChB,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAaN;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAaxC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAqB/C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAM/D;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,QAAQ,CAAC,CAYnB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAuCzD;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CA6BrD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAIrC;AAID,qBAAa,UAAU;IACf,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIlC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAI5B,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC"}
|
package/dist/lib/token-store.js
CHANGED
|
@@ -1,103 +1,205 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Token Store - Optima JWT Token 存储和管理
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. ~/.optima/token.json 文件
|
|
4
|
+
* Token 存储位置:~/.optima/token.json
|
|
5
|
+
* 与 optima-agent 兼容
|
|
7
6
|
*/
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { ENV_CONFIG } from './auth-types.js';
|
|
11
|
+
const OPTIMA_DIR = join(homedir(), '.optima');
|
|
12
|
+
const TOKEN_FILE = join(OPTIMA_DIR, 'token.json');
|
|
13
|
+
/**
|
|
14
|
+
* 确保 ~/.optima 目录存在
|
|
15
|
+
*/
|
|
16
|
+
export function ensureOptimaDir() {
|
|
17
|
+
if (!existsSync(OPTIMA_DIR)) {
|
|
18
|
+
mkdirSync(OPTIMA_DIR, { recursive: true, mode: 0o700 });
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 保存 Token
|
|
23
|
+
*/
|
|
24
|
+
export function saveToken(response, env, user) {
|
|
25
|
+
ensureOptimaDir();
|
|
26
|
+
const tokenData = {
|
|
27
|
+
env,
|
|
28
|
+
access_token: response.access_token,
|
|
29
|
+
refresh_token: response.refresh_token,
|
|
30
|
+
token_type: response.token_type,
|
|
31
|
+
expires_at: Date.now() + response.expires_in * 1000,
|
|
32
|
+
user,
|
|
33
|
+
};
|
|
34
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(tokenData, null, 2), { mode: 0o600 });
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 读取 Token(按优先级)
|
|
38
|
+
*/
|
|
39
|
+
export function getToken() {
|
|
40
|
+
// 1. 环境变量
|
|
41
|
+
if (process.env.OPTIMA_TOKEN) {
|
|
42
|
+
return process.env.OPTIMA_TOKEN;
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const token = await this.getToken();
|
|
46
|
-
return !!token;
|
|
44
|
+
// 2. token.json 文件
|
|
45
|
+
const data = getTokenData();
|
|
46
|
+
if (data) {
|
|
47
|
+
return data.access_token;
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 读取完整 Token 数据
|
|
53
|
+
*/
|
|
54
|
+
export function getTokenData() {
|
|
55
|
+
if (!existsSync(TOKEN_FILE)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const content = readFileSync(TOKEN_FILE, 'utf-8');
|
|
60
|
+
const data = JSON.parse(content);
|
|
61
|
+
// 兼容两种格式
|
|
62
|
+
return {
|
|
63
|
+
env: data.env || 'prod',
|
|
64
|
+
access_token: data.access_token || data.accessToken,
|
|
65
|
+
refresh_token: data.refresh_token || data.refreshToken,
|
|
66
|
+
token_type: data.token_type || 'Bearer',
|
|
67
|
+
expires_at: data.expires_at || data.expiresAt || 0,
|
|
68
|
+
user: data.user,
|
|
60
69
|
};
|
|
61
|
-
fs.writeFileSync(this.tokenFilePath, JSON.stringify(token, null, 2));
|
|
62
70
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*/
|
|
66
|
-
async clearToken() {
|
|
67
|
-
if (fs.existsSync(this.tokenFilePath)) {
|
|
68
|
-
fs.unlinkSync(this.tokenFilePath);
|
|
69
|
-
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
/**
|
|
73
|
-
*
|
|
74
|
-
* @deprecated 使用 TokenStore 类替代
|
|
76
|
+
* 清除 Token
|
|
75
77
|
*/
|
|
76
|
-
export function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return null;
|
|
78
|
+
export function clearToken() {
|
|
79
|
+
if (existsSync(TOKEN_FILE)) {
|
|
80
|
+
unlinkSync(TOKEN_FILE);
|
|
80
81
|
}
|
|
81
|
-
return {
|
|
82
|
-
access_token: '',
|
|
83
|
-
refresh_token: refreshToken,
|
|
84
|
-
expires_at: 0,
|
|
85
|
-
scope: 'https://www.googleapis.com/auth/adwords',
|
|
86
|
-
token_type: 'Bearer',
|
|
87
|
-
};
|
|
88
82
|
}
|
|
89
83
|
/**
|
|
90
|
-
*
|
|
91
|
-
* @deprecated 使用 TokenStore 类替代
|
|
84
|
+
* 检查 Token 是否过期
|
|
92
85
|
*/
|
|
93
|
-
export function
|
|
94
|
-
|
|
86
|
+
export function isTokenExpired(data) {
|
|
87
|
+
const tokenData = data ?? getTokenData();
|
|
88
|
+
if (!tokenData)
|
|
89
|
+
return true;
|
|
90
|
+
// 提前 5 分钟视为过期
|
|
91
|
+
return Date.now() > tokenData.expires_at - 5 * 60 * 1000;
|
|
95
92
|
}
|
|
96
93
|
/**
|
|
97
|
-
*
|
|
94
|
+
* 获取用户信息
|
|
98
95
|
*/
|
|
99
|
-
export function
|
|
100
|
-
const
|
|
101
|
-
|
|
96
|
+
export async function fetchUserInfo(accessToken, env) {
|
|
97
|
+
const { authUrl } = ENV_CONFIG[env];
|
|
98
|
+
const res = await fetch(`${authUrl}/api/v1/users/me`, {
|
|
99
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
100
|
+
});
|
|
101
|
+
if (!res.ok) {
|
|
102
|
+
throw new Error('Failed to fetch user info');
|
|
103
|
+
}
|
|
104
|
+
return (await res.json());
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 获取认证状态
|
|
108
|
+
*/
|
|
109
|
+
export async function getAuthStatus() {
|
|
110
|
+
const data = getTokenData();
|
|
111
|
+
if (!data) {
|
|
112
|
+
return { loggedIn: false };
|
|
113
|
+
}
|
|
114
|
+
if (isTokenExpired(data)) {
|
|
115
|
+
return { loggedIn: false };
|
|
116
|
+
}
|
|
117
|
+
// 如果有缓存的用户信息,直接使用
|
|
118
|
+
if (data.user) {
|
|
119
|
+
return {
|
|
120
|
+
loggedIn: true,
|
|
121
|
+
env: data.env,
|
|
122
|
+
user: data.user,
|
|
123
|
+
expiresAt: data.expires_at,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// 否则从服务端获取
|
|
127
|
+
try {
|
|
128
|
+
const user = await fetchUserInfo(data.access_token, data.env);
|
|
129
|
+
// 更新缓存
|
|
130
|
+
const updatedData = { ...data, user };
|
|
131
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(updatedData, null, 2), {
|
|
132
|
+
mode: 0o600,
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
loggedIn: true,
|
|
136
|
+
env: data.env,
|
|
137
|
+
user,
|
|
138
|
+
expiresAt: data.expires_at,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return { loggedIn: false };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 刷新 Token
|
|
147
|
+
*/
|
|
148
|
+
export async function refreshToken() {
|
|
149
|
+
const data = getTokenData();
|
|
150
|
+
if (!data?.refresh_token) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const { authUrl, clientId } = ENV_CONFIG[data.env];
|
|
154
|
+
try {
|
|
155
|
+
const res = await fetch(`${authUrl}/api/v1/oauth/token`, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
158
|
+
body: new URLSearchParams({
|
|
159
|
+
grant_type: 'refresh_token',
|
|
160
|
+
refresh_token: data.refresh_token,
|
|
161
|
+
client_id: clientId,
|
|
162
|
+
}),
|
|
163
|
+
});
|
|
164
|
+
if (!res.ok) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
const tokenResponse = (await res.json());
|
|
168
|
+
saveToken(tokenResponse, data.env, data.user);
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 获取当前环境的 Ads API URL
|
|
177
|
+
*/
|
|
178
|
+
export function getAdsApiUrl() {
|
|
179
|
+
const data = getTokenData();
|
|
180
|
+
const env = data?.env || 'prod';
|
|
181
|
+
return process.env.ADS_BACKEND_URL || ENV_CONFIG[env].adsApiUrl;
|
|
182
|
+
}
|
|
183
|
+
// ============ TokenStore class for backward compatibility ============
|
|
184
|
+
export class TokenStore {
|
|
185
|
+
async getToken() {
|
|
186
|
+
return getToken();
|
|
187
|
+
}
|
|
188
|
+
async hasToken() {
|
|
189
|
+
return !!getToken();
|
|
190
|
+
}
|
|
191
|
+
async saveToken(accessToken, refreshToken) {
|
|
192
|
+
const data = getTokenData();
|
|
193
|
+
const env = data?.env || 'prod';
|
|
194
|
+
saveToken({
|
|
195
|
+
access_token: accessToken,
|
|
196
|
+
refresh_token: refreshToken,
|
|
197
|
+
token_type: 'Bearer',
|
|
198
|
+
expires_in: 24 * 60 * 60, // 24 hours
|
|
199
|
+
}, env);
|
|
200
|
+
}
|
|
201
|
+
async clearToken() {
|
|
202
|
+
clearToken();
|
|
203
|
+
}
|
|
102
204
|
}
|
|
103
205
|
//# sourceMappingURL=token-store.js.map
|