@cloudbase/toolbox 0.7.21-beta.0 → 0.7.21-beta.1
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/lib/auth/index.d.ts +11 -1
- package/lib/auth/index.js +65 -22
- package/lib/auth/oauth.d.ts +25 -0
- package/lib/auth/oauth.js +71 -36
- package/lib/auth/web-auth.d.ts +2 -0
- package/lib/auth/web-auth.js +3 -2
- package/lib/web/web.d.ts +3 -1
- package/lib/web/web.js +4 -0
- package/package.json +1 -1
package/lib/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeviceFlowOptions } from './oauth';
|
|
1
|
+
import { DeviceFlowOptions, DeviceCodeInfo, AuthTokenByDeviceCodeOptions } from './oauth';
|
|
2
2
|
import { Credential, RequestConfig } from '../types';
|
|
3
3
|
export * from './common';
|
|
4
4
|
export * from './credential';
|
|
@@ -45,6 +45,8 @@ export interface WebAuthOptions {
|
|
|
45
45
|
onDeviceCode?: DeviceFlowOptions['onDeviceCode'];
|
|
46
46
|
/** 自定义 OAuth API 请求的 endpoint */
|
|
47
47
|
getOAuthEndpoint?: DeviceFlowOptions['getOAuthEndpoint'];
|
|
48
|
+
/** 返回即将打开的授权链接 */
|
|
49
|
+
onAuthUrl?: (url: string) => void;
|
|
48
50
|
/** 静默模式,不打印任何日志 */
|
|
49
51
|
silent?: boolean;
|
|
50
52
|
/**
|
|
@@ -70,6 +72,10 @@ export interface LoginByApiSecretOptions {
|
|
|
70
72
|
*/
|
|
71
73
|
additionalCredentialFields?: Omit<Credential, 'secretId' | 'secretKey' | 'token'>;
|
|
72
74
|
}
|
|
75
|
+
export interface StartDeviceFlowOptions extends DeviceFlowOptions {
|
|
76
|
+
noBrowser?: boolean;
|
|
77
|
+
}
|
|
78
|
+
export type CompleteDeviceFlowOptions = AuthTokenByDeviceCodeOptions;
|
|
73
79
|
export declare class AuthSupervisor {
|
|
74
80
|
static instance: AuthSupervisor;
|
|
75
81
|
/**
|
|
@@ -92,6 +98,8 @@ export declare class AuthSupervisor {
|
|
|
92
98
|
* @returns credential
|
|
93
99
|
*/
|
|
94
100
|
loginByWebAuth(options?: WebAuthOptions): Promise<Credential>;
|
|
101
|
+
startDeviceFlow(options?: StartDeviceFlowOptions): Promise<DeviceCodeInfo>;
|
|
102
|
+
completeDeviceFlow(options: CompleteDeviceFlowOptions): Promise<Credential>;
|
|
95
103
|
/**
|
|
96
104
|
* 通过 API Secret 登录,支持临时秘钥
|
|
97
105
|
* @param secretId
|
|
@@ -102,6 +110,8 @@ export declare class AuthSupervisor {
|
|
|
102
110
|
*/
|
|
103
111
|
loginByApiSecret(secretId?: string, secretKey?: string, token?: string, opts?: LoginByApiSecretOptions): Promise<Credential>;
|
|
104
112
|
logout(): Promise<void>;
|
|
113
|
+
private finalizeWebAuthCredential;
|
|
114
|
+
private updateCredentialCache;
|
|
105
115
|
private isCacheExpire;
|
|
106
116
|
}
|
|
107
117
|
/**
|
package/lib/auth/index.js
CHANGED
|
@@ -22,6 +22,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
22
22
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
26
|
+
var t = {};
|
|
27
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
28
|
+
t[p] = s[p];
|
|
29
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
30
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
31
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
32
|
+
t[p[i]] = s[p[i]];
|
|
33
|
+
}
|
|
34
|
+
return t;
|
|
35
|
+
};
|
|
25
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
37
|
exports.AuthSupevisor = exports.AuthSupervisor = void 0;
|
|
27
38
|
const web_auth_1 = require("./web-auth");
|
|
@@ -29,6 +40,7 @@ const oauth_1 = require("./oauth");
|
|
|
29
40
|
const common_1 = require("./common");
|
|
30
41
|
const credential_1 = require("./credential");
|
|
31
42
|
const error_1 = require("../error");
|
|
43
|
+
const web_1 = require("../web");
|
|
32
44
|
__exportStar(require("./common"), exports);
|
|
33
45
|
__exportStar(require("./credential"), exports);
|
|
34
46
|
__exportStar(require("./web-auth"), exports);
|
|
@@ -82,7 +94,7 @@ class AuthSupervisor {
|
|
|
82
94
|
*/
|
|
83
95
|
loginByWebAuth(options = {}) {
|
|
84
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
const { getAuthUrl, throwError, noBrowser, callbackTimeout, flow = 'device', client_id, onDeviceCode, getOAuthEndpoint, silent, custom } = options;
|
|
97
|
+
const { getAuthUrl, throwError, noBrowser, callbackTimeout, flow = 'device', client_id, onDeviceCode, getOAuthEndpoint, onAuthUrl, silent, custom } = options;
|
|
86
98
|
if (this.cacheCredential && this.needCache && !this.isCacheExpire()) {
|
|
87
99
|
return this.cacheCredential;
|
|
88
100
|
}
|
|
@@ -96,34 +108,36 @@ class AuthSupervisor {
|
|
|
96
108
|
getAuthUrl,
|
|
97
109
|
noBrowser,
|
|
98
110
|
callbackTimeout,
|
|
99
|
-
silent
|
|
111
|
+
silent,
|
|
112
|
+
onAuthUrl
|
|
100
113
|
});
|
|
101
114
|
}
|
|
102
115
|
else {
|
|
103
116
|
credential = yield (0, oauth_1.getAuthTokenByDeviceFlow)({ client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent, custom });
|
|
104
117
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
return this.finalizeWebAuthCredential(credential, throwError);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
startDeviceFlow(options = {}) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
const { noBrowser } = options, deviceFlowOptions = __rest(options, ["noBrowser"]);
|
|
124
|
+
const deviceCodeInfo = yield (0, oauth_1.getDeviceCodeByDeviceFlow)(deviceFlowOptions);
|
|
125
|
+
if (!noBrowser) {
|
|
126
|
+
yield (0, web_1.openUrl)(deviceCodeInfo.verification_uri);
|
|
114
127
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.cacheExpiredTime = accessTokenExpired
|
|
123
|
-
? Number(accessTokenExpired)
|
|
124
|
-
: Date.now() + 3600 * 1000;
|
|
128
|
+
return deviceCodeInfo;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
completeDeviceFlow(options) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
if (this.cacheCredential && this.needCache && !this.isCacheExpire()) {
|
|
134
|
+
return this.cacheCredential;
|
|
125
135
|
}
|
|
126
|
-
|
|
136
|
+
let credential = yield (0, credential_1.checkAndGetCredential)(this.requestConfig);
|
|
137
|
+
if (credential)
|
|
138
|
+
return credential;
|
|
139
|
+
credential = yield (0, oauth_1.getAuthTokenByDeviceCode)(options);
|
|
140
|
+
return this.finalizeWebAuthCredential(credential);
|
|
127
141
|
});
|
|
128
142
|
}
|
|
129
143
|
/**
|
|
@@ -200,6 +214,35 @@ class AuthSupervisor {
|
|
|
200
214
|
}
|
|
201
215
|
});
|
|
202
216
|
}
|
|
217
|
+
finalizeWebAuthCredential(credential, throwError) {
|
|
218
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
219
|
+
// eslint-disable-next-line no-param-reassign
|
|
220
|
+
credential = (0, common_1.resolveCredential)(credential);
|
|
221
|
+
try {
|
|
222
|
+
yield (0, common_1.checkAuth)(credential, this.requestConfig);
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
if (throwError || this.throwError) {
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const webCredential = (0, common_1.resolveWebCredential)(credential);
|
|
231
|
+
yield credential_1.authStore.set('credential', webCredential);
|
|
232
|
+
this.updateCredentialCache(credential);
|
|
233
|
+
return credential;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
updateCredentialCache(credential) {
|
|
237
|
+
if (!this.needCache || !credential) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
this.cacheCredential = credential;
|
|
241
|
+
const { accessTokenExpired } = credential;
|
|
242
|
+
this.cacheExpiredTime = accessTokenExpired
|
|
243
|
+
? Number(accessTokenExpired)
|
|
244
|
+
: Date.now() + 3600 * 1000;
|
|
245
|
+
}
|
|
203
246
|
isCacheExpire() {
|
|
204
247
|
const now = Date.now();
|
|
205
248
|
this.cacheExpiredTime = this.cacheExpiredTime || 0;
|
package/lib/auth/oauth.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Credential } from "../types";
|
|
2
|
+
export interface DeviceCodeInfo {
|
|
3
|
+
device_code: string;
|
|
4
|
+
user_code: string;
|
|
5
|
+
verification_uri: string;
|
|
6
|
+
expires_in: number;
|
|
7
|
+
interval: number;
|
|
8
|
+
}
|
|
2
9
|
export interface DeviceFlowOptions {
|
|
3
10
|
client_id?: string;
|
|
4
11
|
onDeviceCode?: (data: {
|
|
@@ -20,4 +27,22 @@ export interface DeviceFlowOptions {
|
|
|
20
27
|
*/
|
|
21
28
|
custom?: boolean;
|
|
22
29
|
}
|
|
30
|
+
export interface AuthTokenByDeviceCodeOptions {
|
|
31
|
+
device_code: string;
|
|
32
|
+
/** 初始轮询间隔 s,默认 5 */
|
|
33
|
+
interval?: number;
|
|
34
|
+
client_id?: string;
|
|
35
|
+
/** 自定义 OAuth API 请求的 endpoint */
|
|
36
|
+
getOAuthEndpoint?: DeviceFlowOptions['getOAuthEndpoint'];
|
|
37
|
+
/**
|
|
38
|
+
* 自定义授权流程模式
|
|
39
|
+
* 为 true 时,token 接口的返回值没有外层 { code, result, reqId } 包装,
|
|
40
|
+
* 直接就是 result 本体。
|
|
41
|
+
*/
|
|
42
|
+
custom?: DeviceFlowOptions['custom'];
|
|
43
|
+
/** 最长等待时长 ms,默认 30000 */
|
|
44
|
+
timeout?: number;
|
|
45
|
+
}
|
|
46
|
+
export declare function getDeviceCodeByDeviceFlow(options?: DeviceFlowOptions): Promise<DeviceCodeInfo>;
|
|
47
|
+
export declare function getAuthTokenByDeviceCode(options: AuthTokenByDeviceCodeOptions): Promise<Credential>;
|
|
23
48
|
export declare function getAuthTokenByDeviceFlow(options?: DeviceFlowOptions): Promise<Credential>;
|
package/lib/auth/oauth.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getAuthTokenByDeviceFlow = void 0;
|
|
12
|
+
exports.getAuthTokenByDeviceFlow = exports.getAuthTokenByDeviceCode = exports.getDeviceCodeByDeviceFlow = void 0;
|
|
13
13
|
const net_1 = require("../net");
|
|
14
14
|
const web_1 = require("../web");
|
|
15
15
|
const error_1 = require("../error");
|
|
@@ -66,6 +66,17 @@ function sleep(ms) {
|
|
|
66
66
|
setTimeout(resolve, ms);
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
+
function buildVerificationUri(deviceCodeData, options) {
|
|
70
|
+
const { custom, getAuthUrl } = options;
|
|
71
|
+
if (custom) {
|
|
72
|
+
const rawUri = deviceCodeData.verification_uri || '';
|
|
73
|
+
return getAuthUrl ? getAuthUrl(rawUri) : rawUri;
|
|
74
|
+
}
|
|
75
|
+
const defaultVerificationUri = `${web_auth_1.CLI_AUTH_BASE_URL}#/cli-auth`;
|
|
76
|
+
// from=cli 后续考虑改用 client_id,因为 toolbox 作为公共依赖,可能被不同 client 所引用
|
|
77
|
+
const rawVerificationUri = `${defaultVerificationUri}?user_code=${deviceCodeData.user_code}&flow=device&from=cli`;
|
|
78
|
+
return getAuthUrl ? getAuthUrl(rawVerificationUri) : rawVerificationUri;
|
|
79
|
+
}
|
|
69
80
|
/**
|
|
70
81
|
* 将接口原始返回值归一化为裸数据。
|
|
71
82
|
* - 标准模式:从 { code, result, reqId } 中解包,校验 code
|
|
@@ -101,43 +112,24 @@ function unwrapTokenResponse(raw, custom) {
|
|
|
101
112
|
}
|
|
102
113
|
return { data: resp.result, reqId: resp.reqId };
|
|
103
114
|
}
|
|
104
|
-
function
|
|
115
|
+
function getDeviceCodeByDeviceFlow(options = {}) {
|
|
105
116
|
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
-
const { client_id,
|
|
117
|
+
const { client_id, getOAuthEndpoint, getAuthUrl, custom } = options;
|
|
107
118
|
const endpoint = yield resolveOAuthEndpoint(getOAuthEndpoint);
|
|
108
|
-
// ---- 获取 device code ----
|
|
109
119
|
const deviceCodeRaw = yield fetchDeviceCode({ client_id, endpoint });
|
|
110
120
|
const { data: deviceCodeData } = unwrapDeviceCodeResponse(deviceCodeRaw, !!custom);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 标准模式由客户端拼接 verification_uri
|
|
121
|
-
const defaultVerificationUri = `${web_auth_1.CLI_AUTH_BASE_URL}#/cli-auth`;
|
|
122
|
-
// from=cli 后续考虑改用 client_id,因为 toolbox 作为公共依赖,可能被不同 client 所引用
|
|
123
|
-
const rawVerificationUri = `${defaultVerificationUri}?user_code=${user_code}&from=cli&flow=device`;
|
|
124
|
-
verification_uri = getAuthUrl ? getAuthUrl(rawVerificationUri) : rawVerificationUri;
|
|
125
|
-
}
|
|
126
|
-
if (!silent) {
|
|
127
|
-
console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
|
|
128
|
-
console.log(`\n${verification_uri}`);
|
|
129
|
-
console.log(`\n用户码: ${user_code}\n`);
|
|
130
|
-
}
|
|
131
|
-
// 尝试自动打开授权页面
|
|
132
|
-
yield (0, web_1.openUrl)(verification_uri);
|
|
133
|
-
if (onDeviceCode) {
|
|
134
|
-
onDeviceCode({ user_code, verification_uri, device_code, expires_in });
|
|
135
|
-
}
|
|
136
|
-
// ---- 轮询 token ----
|
|
121
|
+
const verification_uri = buildVerificationUri(deviceCodeData, { custom, getAuthUrl });
|
|
122
|
+
return Object.assign(Object.assign({}, deviceCodeData), { verification_uri });
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
exports.getDeviceCodeByDeviceFlow = getDeviceCodeByDeviceFlow;
|
|
126
|
+
function getAuthTokenByDeviceCode(options) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
const { device_code, interval = 5, client_id, getOAuthEndpoint, custom, timeout = 30000 } = options;
|
|
129
|
+
const endpoint = yield resolveOAuthEndpoint(getOAuthEndpoint);
|
|
137
130
|
let pollInterval = interval;
|
|
138
|
-
const deadline = Date.now() +
|
|
139
|
-
while (Date.now() < deadline) {
|
|
140
|
-
yield sleep(pollInterval * 1000);
|
|
131
|
+
const deadline = timeout > 0 ? Date.now() + timeout : 0;
|
|
132
|
+
while (!deadline || Date.now() < deadline) {
|
|
141
133
|
let tokenData;
|
|
142
134
|
let reqId;
|
|
143
135
|
try {
|
|
@@ -149,14 +141,23 @@ function getAuthTokenByDeviceFlow(options = {}) {
|
|
|
149
141
|
throw e;
|
|
150
142
|
throw new error_1.CloudBaseError('Device Flow 轮询请求失败', { original: e });
|
|
151
143
|
}
|
|
152
|
-
// 服务端返回业务错误(携带 error 字段)
|
|
153
144
|
if (tokenData && 'error' in tokenData) {
|
|
154
145
|
const { error, error_description } = tokenData;
|
|
155
146
|
if (error === POLL_ERROR_CODES.AUTHORIZATION_PENDING) {
|
|
147
|
+
const nextWaitMs = pollInterval * 1000;
|
|
148
|
+
if (deadline && Date.now() + nextWaitMs >= deadline) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
yield sleep(nextWaitMs);
|
|
156
152
|
continue;
|
|
157
153
|
}
|
|
158
154
|
if (error === POLL_ERROR_CODES.SLOW_DOWN) {
|
|
159
155
|
pollInterval += 5;
|
|
156
|
+
const nextWaitMs = pollInterval * 1000;
|
|
157
|
+
if (deadline && Date.now() + nextWaitMs >= deadline) {
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
yield sleep(nextWaitMs);
|
|
160
161
|
continue;
|
|
161
162
|
}
|
|
162
163
|
if (error === POLL_ERROR_CODES.EXPIRED_TOKEN) {
|
|
@@ -170,13 +171,47 @@ function getAuthTokenByDeviceFlow(options = {}) {
|
|
|
170
171
|
requestId: reqId,
|
|
171
172
|
});
|
|
172
173
|
}
|
|
173
|
-
// 成功拿到 Credential
|
|
174
174
|
if (tokenData) {
|
|
175
175
|
return tokenData;
|
|
176
176
|
}
|
|
177
177
|
throw new error_1.CloudBaseError('Device Flow 授权失败:返回数据异常', { requestId: reqId });
|
|
178
178
|
}
|
|
179
|
-
throw new error_1.CloudBaseError('
|
|
179
|
+
throw new error_1.CloudBaseError('授权尚未完成,请确认已完成授权后重试', {
|
|
180
|
+
code: POLL_ERROR_CODES.AUTHORIZATION_PENDING,
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
exports.getAuthTokenByDeviceCode = getAuthTokenByDeviceCode;
|
|
185
|
+
function getAuthTokenByDeviceFlow(options = {}) {
|
|
186
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
const { client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent, custom } = options;
|
|
188
|
+
const { device_code, user_code, verification_uri, expires_in, interval } = yield getDeviceCodeByDeviceFlow({ client_id, getOAuthEndpoint, getAuthUrl, custom });
|
|
189
|
+
if (!silent) {
|
|
190
|
+
console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
|
|
191
|
+
console.log(`\n${verification_uri}`);
|
|
192
|
+
console.log(`\n用户码: ${user_code}\n`);
|
|
193
|
+
}
|
|
194
|
+
// 尝试自动打开授权页面
|
|
195
|
+
yield (0, web_1.openUrl)(verification_uri);
|
|
196
|
+
if (onDeviceCode) {
|
|
197
|
+
onDeviceCode({ user_code, verification_uri, device_code, expires_in });
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
return yield getAuthTokenByDeviceCode({
|
|
201
|
+
device_code,
|
|
202
|
+
interval,
|
|
203
|
+
client_id,
|
|
204
|
+
getOAuthEndpoint,
|
|
205
|
+
custom,
|
|
206
|
+
timeout: expires_in * 1000
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
if (e instanceof error_1.CloudBaseError && e.code === POLL_ERROR_CODES.AUTHORIZATION_PENDING) {
|
|
211
|
+
throw new error_1.CloudBaseError('授权超时,用户未在有效期内完成授权,请重试');
|
|
212
|
+
}
|
|
213
|
+
throw e;
|
|
214
|
+
}
|
|
180
215
|
});
|
|
181
216
|
}
|
|
182
217
|
exports.getAuthTokenByDeviceFlow = getAuthTokenByDeviceFlow;
|
package/lib/auth/web-auth.d.ts
CHANGED
package/lib/auth/web-auth.js
CHANGED
|
@@ -18,7 +18,7 @@ exports.CLI_AUTH_BASE_URL = 'https://tcb.cloud.tencent.com/dev';
|
|
|
18
18
|
// 打开云开发控制台,获取授权
|
|
19
19
|
function getAuthTokenFromWeb(options = {}) {
|
|
20
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
const { getAuthUrl, noBrowser, callbackTimeout, silent } = options;
|
|
21
|
+
const { getAuthUrl, noBrowser, callbackTimeout, silent, onAuthUrl } = options;
|
|
22
22
|
const mac = yield (0, system_1.getMacAddress)();
|
|
23
23
|
const os = (0, system_1.getOSInfo)();
|
|
24
24
|
const macHash = (0, coding_1.md5Encoding)(mac);
|
|
@@ -45,7 +45,8 @@ function getAuthTokenFromWeb(options = {}) {
|
|
|
45
45
|
}, 'login', {
|
|
46
46
|
noBrowser,
|
|
47
47
|
callbackTimeout,
|
|
48
|
-
silent
|
|
48
|
+
silent,
|
|
49
|
+
onUrl: onAuthUrl
|
|
49
50
|
});
|
|
50
51
|
const credential = (0, common_1.resolveCredential)(query);
|
|
51
52
|
return credential;
|
package/lib/web/web.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export type CheckFn = (query: IQuery) => Promise<void>;
|
|
|
6
6
|
export interface GetDataFromWebOptions {
|
|
7
7
|
noBrowser?: boolean;
|
|
8
8
|
callbackTimeout?: number;
|
|
9
|
-
/**
|
|
9
|
+
/** 静默模式,不打印任何日志 */
|
|
10
10
|
silent?: boolean;
|
|
11
|
+
/** 返回即将打开的授权链接 */
|
|
12
|
+
onUrl?: (url: string) => void;
|
|
11
13
|
}
|
|
12
14
|
export declare function isTruthyFlag(value?: string): boolean;
|
|
13
15
|
export declare function openUrl(url: string): Promise<boolean>;
|
package/lib/web/web.js
CHANGED
|
@@ -124,10 +124,14 @@ function getDataFromWeb(getUrl, type, options = {}) {
|
|
|
124
124
|
const noBrowser = (_a = options.noBrowser) !== null && _a !== void 0 ? _a : isTruthyFlag(process.env.TCB_NO_BROWSER);
|
|
125
125
|
const callbackTimeout = (_b = options.callbackTimeout) !== null && _b !== void 0 ? _b : 180000;
|
|
126
126
|
const silent = (_c = options.silent) !== null && _c !== void 0 ? _c : false;
|
|
127
|
+
const onUrl = options.onUrl;
|
|
127
128
|
if (!Number.isFinite(callbackTimeout) || callbackTimeout <= 0) {
|
|
128
129
|
throw new error_1.CloudBaseError('callbackTimeout must be a positive number');
|
|
129
130
|
}
|
|
130
131
|
const url = getUrl(port);
|
|
132
|
+
if (onUrl) {
|
|
133
|
+
onUrl(url);
|
|
134
|
+
}
|
|
131
135
|
if (!silent) {
|
|
132
136
|
console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
|
|
133
137
|
console.log(`\n${url}\n`);
|