@cloudbase/app 1.5.2-alpha.0 → 1.8.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/.eslintrc.js +12 -0
- package/dist/cjs/constants/common.d.ts +1 -7
- package/dist/cjs/constants/common.js +5 -11
- package/dist/cjs/constants/events.js +2 -2
- package/dist/cjs/index.js +26 -26
- package/dist/cjs/libs/adapter.d.ts +1 -1
- package/dist/cjs/libs/adapter.js +1 -1
- package/dist/cjs/libs/cache.d.ts +1 -1
- package/dist/cjs/libs/cache.js +9 -14
- package/dist/cjs/libs/component.js +16 -14
- package/dist/cjs/libs/request.d.ts +0 -7
- package/dist/cjs/libs/request.js +61 -298
- package/dist/esm/constants/common.d.ts +1 -7
- package/dist/esm/constants/common.js +4 -10
- package/dist/esm/constants/events.js +2 -2
- package/dist/esm/index.js +15 -15
- package/dist/esm/libs/adapter.d.ts +1 -1
- package/dist/esm/libs/adapter.js +1 -1
- package/dist/esm/libs/cache.d.ts +1 -1
- package/dist/esm/libs/cache.js +10 -15
- package/dist/esm/libs/component.js +16 -14
- package/dist/esm/libs/request.d.ts +0 -7
- package/dist/esm/libs/request.js +61 -298
- package/package.json +5 -16
- package/src/constants/common.ts +13 -20
- package/src/constants/events.ts +5 -5
- package/src/global.d.ts +1 -1
- package/src/index.ts +20 -19
- package/src/libs/adapter.ts +2 -2
- package/src/libs/cache.ts +8 -11
- package/src/libs/component.ts +42 -40
- package/src/libs/request.ts +53 -256
- package/.eslintrc +0 -29
package/src/libs/request.ts
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
/* eslint-disable no-plusplus */
|
|
2
|
+
/* eslint-disable no-prototype-builtins */
|
|
3
|
+
/* eslint-disable no-restricted-syntax */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
1
5
|
import {
|
|
2
6
|
DATA_VERSION,
|
|
3
7
|
LOGINTYPE,
|
|
4
8
|
getSdkVersion,
|
|
5
9
|
getEndPoint,
|
|
6
|
-
OAUTH2_LOGINTYPE_PREFIX
|
|
7
10
|
} from '../constants/common';
|
|
8
11
|
import {
|
|
9
12
|
IRequestOptions,
|
|
10
13
|
SDKRequestInterface,
|
|
11
14
|
ResponseObject,
|
|
12
15
|
IUploadRequestOptions,
|
|
13
|
-
IRequestConfig
|
|
16
|
+
IRequestConfig,
|
|
14
17
|
} from '@cloudbase/adapter-interface';
|
|
15
|
-
import { utils,
|
|
18
|
+
import { utils, adapters, constants } from '@cloudbase/utilities';
|
|
16
19
|
import { KV } from '@cloudbase/types';
|
|
17
20
|
import { IGetAccessTokenResult, ICloudbaseRequestConfig, IAppendedRequestInfo, IRequestBeforeHook } from '@cloudbase/types/request';
|
|
18
21
|
import { ICloudbaseCache } from '@cloudbase/types/cache';
|
|
@@ -20,15 +23,11 @@ import { cloudbase } from '..';
|
|
|
20
23
|
import { getCacheByEnvId, getLocalCache } from './cache';
|
|
21
24
|
import { EVENTS } from '../constants/events';
|
|
22
25
|
import { Platform } from './adapter';
|
|
23
|
-
|
|
26
|
+
|
|
27
|
+
const { ERRORS } = constants;
|
|
24
28
|
const { genSeqId, isFormData, formatUrl, createSign } = utils;
|
|
25
29
|
const { RUNTIME } = adapters;
|
|
26
30
|
|
|
27
|
-
import { v4 as uuidv4 } from 'uuid'
|
|
28
|
-
|
|
29
|
-
// import FingerprintJS from '@fingerprintjs/fingerprintjs'
|
|
30
|
-
// const fpPromise = FingerprintJS.load()
|
|
31
|
-
|
|
32
31
|
// 下面几种 action 不需要 access token
|
|
33
32
|
const ACTIONS_WITHOUT_ACCESSTOKEN = [
|
|
34
33
|
'auth.getJwt',
|
|
@@ -41,7 +40,7 @@ const ACTIONS_WITHOUT_ACCESSTOKEN = [
|
|
|
41
40
|
'auth.activateEndUserMail',
|
|
42
41
|
'auth.sendPasswordResetEmail',
|
|
43
42
|
'auth.resetPasswordWithToken',
|
|
44
|
-
'auth.isUsernameRegistered'
|
|
43
|
+
'auth.isUsernameRegistered',
|
|
45
44
|
];
|
|
46
45
|
|
|
47
46
|
function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestBeforeHook[]) {
|
|
@@ -49,7 +48,7 @@ function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestB
|
|
|
49
48
|
instance[name] = function (options: IRequestOptions) {
|
|
50
49
|
const data = {};
|
|
51
50
|
const headers = {};
|
|
52
|
-
hooks.forEach(hook => {
|
|
51
|
+
hooks.forEach((hook) => {
|
|
53
52
|
const { data: appendedData, headers: appendedHeaders } = hook.call(instance, options);
|
|
54
53
|
Object.assign(data, appendedData);
|
|
55
54
|
Object.assign(headers, appendedHeaders);
|
|
@@ -64,12 +63,12 @@ function bindHooks(instance: SDKRequestInterface, name: string, hooks: IRequestB
|
|
|
64
63
|
}
|
|
65
64
|
options.data = {
|
|
66
65
|
...originData,
|
|
67
|
-
...data
|
|
66
|
+
...data,
|
|
68
67
|
};
|
|
69
68
|
})();
|
|
70
69
|
options.headers = {
|
|
71
70
|
...(options.headers || {}),
|
|
72
|
-
...headers
|
|
71
|
+
...headers,
|
|
73
72
|
};
|
|
74
73
|
return (originMethod as Function).call(instance, options);
|
|
75
74
|
};
|
|
@@ -78,16 +77,15 @@ function beforeEach(): IAppendedRequestInfo {
|
|
|
78
77
|
const seqId = genSeqId();
|
|
79
78
|
return {
|
|
80
79
|
data: {
|
|
81
|
-
seqId
|
|
80
|
+
seqId,
|
|
82
81
|
},
|
|
83
82
|
headers: {
|
|
84
83
|
'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
|
|
85
|
-
'x-seqid': seqId
|
|
86
|
-
}
|
|
84
|
+
'x-seqid': seqId,
|
|
85
|
+
},
|
|
87
86
|
};
|
|
88
87
|
}
|
|
89
88
|
export interface ICloudbaseRequest {
|
|
90
|
-
fetch: (urlOrPath: string, init?: RequestInit) => Promise<Response>;
|
|
91
89
|
post: (options: IRequestOptions) => Promise<ResponseObject>;
|
|
92
90
|
upload: (options: IUploadRequestOptions) => Promise<ResponseObject>;
|
|
93
91
|
download: (options: IRequestOptions) => Promise<ResponseObject>;
|
|
@@ -102,8 +100,8 @@ export interface ICloudbaseRequest {
|
|
|
102
100
|
*/
|
|
103
101
|
export class CloudbaseRequest implements ICloudbaseRequest {
|
|
104
102
|
config: ICloudbaseRequestConfig;
|
|
105
|
-
_shouldRefreshAccessTokenHook: Function
|
|
106
|
-
_refreshAccessTokenPromise: Promise<IGetAccessTokenResult> | null
|
|
103
|
+
_shouldRefreshAccessTokenHook: Function;
|
|
104
|
+
_refreshAccessTokenPromise: Promise<IGetAccessTokenResult> | null;
|
|
107
105
|
_reqClass: SDKRequestInterface;
|
|
108
106
|
// 请求失败是否抛出Error
|
|
109
107
|
private _throwWhenRequestFail = false;
|
|
@@ -120,7 +118,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
120
118
|
this._reqClass = new Platform.adapter.reqClass(<IRequestConfig>{
|
|
121
119
|
timeout: this.config.timeout,
|
|
122
120
|
timeoutMsg: `[@cloudbase/js-sdk] 请求在${this.config.timeout / 1000}s内未完成,已中断`,
|
|
123
|
-
restrictedMethods: ['post']
|
|
121
|
+
restrictedMethods: ['post'],
|
|
124
122
|
});
|
|
125
123
|
this._throwWhenRequestFail = config.throw || false;
|
|
126
124
|
this._cache = getCacheByEnvId(this.config.env);
|
|
@@ -129,49 +127,6 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
129
127
|
bindHooks(this._reqClass, 'upload', [beforeEach]);
|
|
130
128
|
bindHooks(this._reqClass, 'download', [beforeEach]);
|
|
131
129
|
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 套一层 fetch,方便处理请求地址
|
|
135
|
-
* @param {string} urlOrPath
|
|
136
|
-
* @param {RequestInit} init
|
|
137
|
-
* @returns
|
|
138
|
-
*/
|
|
139
|
-
public async fetch(urlOrPath: string, init?: RequestInit): Promise<Response> {
|
|
140
|
-
const deviceId = await this.getDeviceId();
|
|
141
|
-
|
|
142
|
-
const headers = {
|
|
143
|
-
'X-Project-Id': this.config.env,
|
|
144
|
-
'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
|
|
145
|
-
'X-Request-Id': genSeqId(),
|
|
146
|
-
'X-Request-Timestamp': Date.now(),
|
|
147
|
-
'X-Device-Id': deviceId
|
|
148
|
-
}
|
|
149
|
-
// 非web平台使用凭证检验有效性
|
|
150
|
-
if (Platform.runtime !== RUNTIME.WEB) {
|
|
151
|
-
const { appSign, appSecret } = this.config
|
|
152
|
-
const timestamp = Date.now()
|
|
153
|
-
const { appAccessKey, appAccessKeyId } = appSecret
|
|
154
|
-
const sign = createSign({
|
|
155
|
-
// data: init.body,
|
|
156
|
-
data: {},
|
|
157
|
-
timestamp,
|
|
158
|
-
appAccessKeyId,
|
|
159
|
-
appSign
|
|
160
|
-
}, appAccessKey)
|
|
161
|
-
|
|
162
|
-
headers['X-TCB-App-Source'] = `timestamp=${timestamp};appAccessKeyId=${appAccessKeyId};appSign=${appSign};sign=${sign}`
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
init.headers = Object.assign({}, init.headers, headers)
|
|
166
|
-
|
|
167
|
-
const { PROTOCOL, BASE_URL } = getEndPoint()
|
|
168
|
-
const webEndpoint = `${PROTOCOL}${BASE_URL}`
|
|
169
|
-
const url = urlOrPath.startsWith('http')
|
|
170
|
-
? urlOrPath
|
|
171
|
-
: `${new URL(webEndpoint).origin}${urlOrPath}`
|
|
172
|
-
return await fetch(url, init)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
130
|
public async post(options: IRequestOptions): Promise<ResponseObject> {
|
|
176
131
|
const res = await this._reqClass.post(options);
|
|
177
132
|
return res;
|
|
@@ -207,51 +162,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
207
162
|
return result;
|
|
208
163
|
}
|
|
209
164
|
|
|
210
|
-
|
|
211
|
-
// 可能会同时调用多次刷新 access token,这里把它们合并成一个
|
|
212
|
-
if (!this._refreshAccessTokenPromise) {
|
|
213
|
-
// 没有正在刷新,那么正常执行刷新逻辑
|
|
214
|
-
this._refreshAccessTokenPromise = this._refreshAccessTokenFromOauthServer(clientId);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
let result;
|
|
218
|
-
let err;
|
|
219
|
-
try {
|
|
220
|
-
result = await this._refreshAccessTokenPromise;
|
|
221
|
-
} catch (e) {
|
|
222
|
-
err = e;
|
|
223
|
-
}
|
|
224
|
-
this._refreshAccessTokenPromise = null;
|
|
225
|
-
this._shouldRefreshAccessTokenHook = null;
|
|
226
|
-
if (err) {
|
|
227
|
-
throw err;
|
|
228
|
-
}
|
|
229
|
-
return result;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// 获取 OAuth accesstoken
|
|
233
|
-
public async getOauthAccessToken(): Promise<IGetAccessTokenResult> {
|
|
234
|
-
const { oauthClient } = this.config
|
|
235
|
-
if (oauthClient) {
|
|
236
|
-
const validAccessToken = await oauthClient.getAccessToken()
|
|
237
|
-
const credentials = await oauthClient._getCredentials()
|
|
238
|
-
return {
|
|
239
|
-
accessToken: validAccessToken,
|
|
240
|
-
accessTokenExpire: new Date(credentials.expires_at).getTime()
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// 获取 access token
|
|
165
|
+
// 获取access token
|
|
246
166
|
public async getAccessToken(): Promise<IGetAccessTokenResult> {
|
|
247
|
-
const {
|
|
248
|
-
const loginType = await this._cache.getStoreAsync(loginTypeKey);
|
|
167
|
+
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
|
|
249
168
|
const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
250
169
|
if (!refreshToken) {
|
|
251
170
|
// 不该出现的状态:有 access token 却没有 refresh token
|
|
252
171
|
throw new Error(JSON.stringify({
|
|
253
172
|
code: ERRORS.OPERATION_FAIL,
|
|
254
|
-
msg: 'refresh token is not exist, your local data might be messed up, please retry after clear localStorage or sessionStorage'
|
|
173
|
+
msg: 'refresh token is not exist, your local data might be messed up, please retry after clear localStorage or sessionStorage',
|
|
255
174
|
}));
|
|
256
175
|
}
|
|
257
176
|
// 如果没有access token或者过期,那么刷新
|
|
@@ -265,43 +184,18 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
265
184
|
}
|
|
266
185
|
|
|
267
186
|
if ((!accessToken || !accessTokenExpire || accessTokenExpire < Date.now()) && shouldRefreshAccessToken) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// 所以过期的 accessToken 不能删除,而是用新 accessToken 覆盖
|
|
271
|
-
if (accessToken) {
|
|
272
|
-
let header = null
|
|
273
|
-
let payload = null
|
|
274
|
-
try {
|
|
275
|
-
header = jwt.decode(accessToken, { header: true })
|
|
276
|
-
payload = jwt.decode(accessToken)
|
|
277
|
-
}
|
|
278
|
-
catch (e) {
|
|
279
|
-
throw new Error(`[DECODE_ACCESS_TOKEN_ERROR] ${e.message}, accesstoken: ${accessToken}`)
|
|
280
|
-
}
|
|
281
|
-
if (header?.kid && payload?.project_id) {
|
|
282
|
-
return await this.refreshAccessTokenFromOauthServer(payload?.project_id)
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
// 这里用 env 试一下
|
|
287
|
-
return await this.refreshAccessTokenFromOauthServer(this.config.env)
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
return await this.refreshAccessToken();
|
|
292
|
-
}
|
|
293
|
-
} else {
|
|
294
|
-
// 返回本地的access token
|
|
295
|
-
return {
|
|
296
|
-
accessToken,
|
|
297
|
-
accessTokenExpire
|
|
298
|
-
};
|
|
187
|
+
// 返回新的access tolen
|
|
188
|
+
return await this.refreshAccessToken();
|
|
299
189
|
}
|
|
190
|
+
// 返回本地的access token
|
|
191
|
+
return {
|
|
192
|
+
accessToken,
|
|
193
|
+
accessTokenExpire,
|
|
194
|
+
};
|
|
300
195
|
}
|
|
301
196
|
|
|
302
197
|
/* eslint-disable complexity */
|
|
303
198
|
public async request(action: string, params: KV<any>, options?: KV<any>): Promise<ResponseObject> {
|
|
304
|
-
const { oauthClient } = this.config
|
|
305
199
|
const tcbTraceKey = `x-tcb-trace_${this.config.env}`;
|
|
306
200
|
let contentType = 'application/x-www-form-urlencoded';
|
|
307
201
|
// const webDeviceId = await getTcbFingerprintId();
|
|
@@ -310,13 +204,9 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
310
204
|
// webDeviceId,
|
|
311
205
|
dataVersion: DATA_VERSION,
|
|
312
206
|
env: this.config.env,
|
|
313
|
-
...params
|
|
207
|
+
...params,
|
|
314
208
|
};
|
|
315
209
|
|
|
316
|
-
// 若识别到注册了 Oauth 模块,则使用oauth getAccessToken
|
|
317
|
-
if (oauthClient) {
|
|
318
|
-
tmpObj.access_token = (await this.getOauthAccessToken()).accessToken
|
|
319
|
-
}
|
|
320
210
|
|
|
321
211
|
if (ACTIONS_WITHOUT_ACCESSTOKEN.indexOf(action) === -1) {
|
|
322
212
|
const { refreshTokenKey } = this._cache.keys;
|
|
@@ -332,7 +222,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
332
222
|
let payload;
|
|
333
223
|
if (action === 'storage.uploadFile') {
|
|
334
224
|
payload = new FormData();
|
|
335
|
-
for (
|
|
225
|
+
for (const key in payload) {
|
|
336
226
|
if (payload.hasOwnProperty(key) && payload[key] !== undefined) {
|
|
337
227
|
payload.append(key, tmpObj[key]);
|
|
338
228
|
}
|
|
@@ -341,19 +231,19 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
341
231
|
} else {
|
|
342
232
|
contentType = 'application/json;charset=UTF-8';
|
|
343
233
|
payload = {};
|
|
344
|
-
for (
|
|
234
|
+
for (const key in tmpObj) {
|
|
345
235
|
if (tmpObj[key] !== undefined) {
|
|
346
236
|
payload[key] = tmpObj[key];
|
|
347
237
|
}
|
|
348
238
|
}
|
|
349
239
|
}
|
|
350
|
-
|
|
240
|
+
const opts: any = {
|
|
351
241
|
headers: {
|
|
352
|
-
'content-type': contentType
|
|
353
|
-
}
|
|
242
|
+
'content-type': contentType,
|
|
243
|
+
},
|
|
354
244
|
};
|
|
355
|
-
if (options?.
|
|
356
|
-
opts.onUploadProgress = options
|
|
245
|
+
if (options?.onUploadProgress) {
|
|
246
|
+
opts.onUploadProgress = options.onUploadProgress;
|
|
357
247
|
}
|
|
358
248
|
|
|
359
249
|
if (this.config.region) {
|
|
@@ -373,7 +263,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
373
263
|
data: {}, // 校验签名流程实际未用到,可设空
|
|
374
264
|
timestamp,
|
|
375
265
|
appAccessKeyId,
|
|
376
|
-
appSign
|
|
266
|
+
appSign,
|
|
377
267
|
}, appAccessKey);
|
|
378
268
|
|
|
379
269
|
opts.headers['X-TCB-App-Source'] = `timestamp=${timestamp};appAccessKeyId=${appAccessKeyId};appSign=${appSign};sign=${sign}`;
|
|
@@ -384,13 +274,13 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
384
274
|
// 请求链接支持添加动态 query 参数,方便用户调试定位请求
|
|
385
275
|
const { parse, inQuery, search } = params;
|
|
386
276
|
let formatQuery: Record<string, any> = {
|
|
387
|
-
env: this.config.env
|
|
277
|
+
env: this.config.env,
|
|
388
278
|
};
|
|
389
279
|
// 尝试解析响应数据为 JSON
|
|
390
280
|
parse && (formatQuery.parse = true);
|
|
391
281
|
inQuery && (formatQuery = {
|
|
392
282
|
...inQuery,
|
|
393
|
-
...formatQuery
|
|
283
|
+
...formatQuery,
|
|
394
284
|
});
|
|
395
285
|
const { BASE_URL, PROTOCOL } = getEndPoint();
|
|
396
286
|
// 生成请求 url
|
|
@@ -403,7 +293,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
403
293
|
const res: ResponseObject = await this.post({
|
|
404
294
|
url: newUrl,
|
|
405
295
|
data: payload,
|
|
406
|
-
...opts
|
|
296
|
+
...opts,
|
|
407
297
|
});
|
|
408
298
|
|
|
409
299
|
// 保存 trace header
|
|
@@ -430,7 +320,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
430
320
|
if (response.data.code && this._throwWhenRequestFail) {
|
|
431
321
|
throw new Error(JSON.stringify({
|
|
432
322
|
code: ERRORS.OPERATION_FAIL,
|
|
433
|
-
msg: `[${response.data.code}] ${response.data.message}
|
|
323
|
+
msg: `[${response.data.code}] ${response.data.message}`,
|
|
434
324
|
}));
|
|
435
325
|
}
|
|
436
326
|
|
|
@@ -443,15 +333,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
443
333
|
await this._cache.removeStoreAsync(accessTokenKey);
|
|
444
334
|
await this._cache.removeStoreAsync(accessTokenExpireKey);
|
|
445
335
|
|
|
446
|
-
|
|
336
|
+
const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
447
337
|
if (!refreshToken) {
|
|
448
338
|
throw new Error(JSON.stringify({
|
|
449
339
|
code: ERRORS.INVALID_OPERATION,
|
|
450
|
-
msg: 'not login'
|
|
340
|
+
msg: 'not login',
|
|
451
341
|
}));
|
|
452
342
|
}
|
|
453
343
|
const params: KV<string> = {
|
|
454
|
-
refresh_token: refreshToken
|
|
344
|
+
refresh_token: refreshToken,
|
|
455
345
|
};
|
|
456
346
|
const response = await this.request('auth.fetchAccessTokenWithRefreshToken', params);
|
|
457
347
|
if (response.data.code) {
|
|
@@ -469,26 +359,23 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
469
359
|
const refresh_token = await this._cache.getStoreAsync(refreshTokenKey);
|
|
470
360
|
const res = await this.send('auth.signInAnonymously', {
|
|
471
361
|
anonymous_uuid,
|
|
472
|
-
refresh_token
|
|
362
|
+
refresh_token,
|
|
473
363
|
});
|
|
474
364
|
this._setRefreshToken(res.refresh_token);
|
|
475
365
|
if (retryNum >= 1) {
|
|
476
366
|
return this._refreshAccessToken(--retryNum);
|
|
477
|
-
} else {
|
|
478
|
-
throw new Error(
|
|
479
|
-
JSON.stringify({
|
|
480
|
-
code: ERRORS.OPERATION_FAIL,
|
|
481
|
-
message: '重试获取 refresh token 失败'
|
|
482
|
-
})
|
|
483
|
-
)
|
|
484
367
|
}
|
|
368
|
+
throw new Error(JSON.stringify({
|
|
369
|
+
code: ERRORS.OPERATION_FAIL,
|
|
370
|
+
message: '重试获取 refresh token 失败',
|
|
371
|
+
}));
|
|
485
372
|
}
|
|
486
373
|
cloudbase.fire(EVENTS.LOGIN_STATE_EXPIRED);
|
|
487
374
|
await this._cache.removeStoreAsync(refreshTokenKey);
|
|
488
375
|
}
|
|
489
376
|
throw new Error(JSON.stringify({
|
|
490
377
|
code: ERRORS.NETWORK_ERROR,
|
|
491
|
-
msg: `refresh access_token failed:${response.data.code}
|
|
378
|
+
msg: `refresh access_token failed:${response.data.code}`,
|
|
492
379
|
}));
|
|
493
380
|
}
|
|
494
381
|
if (response.data.access_token) {
|
|
@@ -498,7 +385,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
498
385
|
await this._cache.setStoreAsync(accessTokenExpireKey, response.data.access_token_expire + Date.now());
|
|
499
386
|
return {
|
|
500
387
|
accessToken: response.data.access_token,
|
|
501
|
-
accessTokenExpire: response.data.access_token_expire
|
|
388
|
+
accessTokenExpire: response.data.access_token_expire,
|
|
502
389
|
};
|
|
503
390
|
}
|
|
504
391
|
// 匿名登录refresh_token过期情况下返回refresh_token
|
|
@@ -509,103 +396,13 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
509
396
|
await this._refreshAccessToken();
|
|
510
397
|
}
|
|
511
398
|
}
|
|
512
|
-
|
|
513
|
-
private async _fetchAccessTokenFromOauthServer(refreshToken: string, clientId: string) {
|
|
514
|
-
const resp = await this.fetch('/auth/v1/token', {
|
|
515
|
-
method: 'POST',
|
|
516
|
-
headers: {
|
|
517
|
-
'Accept': 'application/json',
|
|
518
|
-
'Content-Type': 'application/json'
|
|
519
|
-
},
|
|
520
|
-
body: JSON.stringify({
|
|
521
|
-
grant_type: 'refresh_token',
|
|
522
|
-
client_id: clientId,
|
|
523
|
-
refresh_token: refreshToken
|
|
524
|
-
})
|
|
525
|
-
})
|
|
526
|
-
// Resp:
|
|
527
|
-
// {
|
|
528
|
-
// "token_type": "Bearer",
|
|
529
|
-
// "access_token": "",
|
|
530
|
-
// "refresh_token":"",
|
|
531
|
-
// "expires_in": 259200,
|
|
532
|
-
// "sub": ""
|
|
533
|
-
// }
|
|
534
|
-
// 以下代码重复
|
|
535
|
-
const seqIdFromHeader = resp.headers.get('SeqId') || resp.headers.get('RequestId')
|
|
536
|
-
if (resp.status >= 400 && resp.status < 500) {
|
|
537
|
-
const body: any = await resp.json()
|
|
538
|
-
const seqId = body.request_id || seqIdFromHeader
|
|
539
|
-
throw new Error(`[${getSdkName()}/${getSdkVersion()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
|
|
540
|
-
}
|
|
541
|
-
else if (resp.status >= 500) {
|
|
542
|
-
const body: any = await resp.json()
|
|
543
|
-
const seqId = body.request_id || seqIdFromHeader
|
|
544
|
-
throw new Error(`[${getSdkName()}/${getSdkVersion()}][OAuth2AuthProvider][status:${resp.status}][${body.error}(${body.error_code})] ${body.error_description} (${seqId})`)
|
|
545
|
-
}
|
|
546
|
-
return resp.json()
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// 调用接口刷新access token,并且返回
|
|
550
|
-
private async _refreshAccessTokenFromOauthServer(clientId: string): Promise<IGetAccessTokenResult> {
|
|
551
|
-
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
|
|
552
|
-
const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
553
|
-
if (!refreshToken) {
|
|
554
|
-
throw new Error(JSON.stringify({
|
|
555
|
-
code: ERRORS.INVALID_OPERATION,
|
|
556
|
-
msg: 'not login'
|
|
557
|
-
}));
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
const token = await this._fetchAccessTokenFromOauthServer(refreshToken, clientId);
|
|
561
|
-
const { refresh_token: newRefreshToken, access_token: accessToken, expires_in: accessTokenExpire } = token
|
|
562
|
-
|
|
563
|
-
// 错误处理
|
|
564
|
-
if (!accessToken || !accessTokenExpire) {
|
|
565
|
-
throw new Error(JSON.stringify({
|
|
566
|
-
code: ERRORS.NETWORK_ERROR,
|
|
567
|
-
msg: 'refresh access_token failed'
|
|
568
|
-
}));
|
|
569
|
-
}
|
|
570
|
-
if (accessToken && accessTokenExpire) {
|
|
571
|
-
if (newRefreshToken === refreshToken) {
|
|
572
|
-
await this._cache.setStoreAsync(refreshTokenKey, newRefreshToken);
|
|
573
|
-
}
|
|
574
|
-
await this._cache.setStoreAsync(accessTokenKey, accessToken);
|
|
575
|
-
await this._cache.setStoreAsync(accessTokenExpireKey, accessTokenExpire * 1000 + Date.now());
|
|
576
|
-
cloudbase.fire(EVENTS.ACCESS_TOKEN_REFRESHD);
|
|
577
|
-
return {
|
|
578
|
-
accessToken: accessToken,
|
|
579
|
-
accessTokenExpire: accessTokenExpire
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
|
|
584
399
|
private async _setRefreshToken(refreshToken: string) {
|
|
585
400
|
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
|
|
586
401
|
// refresh token设置前,先清掉 access token
|
|
587
|
-
// 设置是直接拉取新 access token 覆盖,而不是 remove
|
|
588
402
|
await this._cache.removeStoreAsync(accessTokenKey);
|
|
589
403
|
await this._cache.removeStoreAsync(accessTokenExpireKey);
|
|
590
404
|
await this._cache.setStoreAsync(refreshTokenKey, refreshToken);
|
|
591
405
|
}
|
|
592
|
-
|
|
593
|
-
private async getDeviceId(): Promise<string> {
|
|
594
|
-
const { deviceIdKey } = this._cache.keys
|
|
595
|
-
const deviceId = await this._cache.getStoreAsync(deviceIdKey)
|
|
596
|
-
|
|
597
|
-
if (!deviceId) {
|
|
598
|
-
// const fp = await fpPromise
|
|
599
|
-
// const result = await fp.get()
|
|
600
|
-
// const deviceId = result.visitorId
|
|
601
|
-
const newDeviceId = uuidv4()
|
|
602
|
-
this._cache.setStoreAsync(deviceIdKey, newDeviceId)
|
|
603
|
-
return newDeviceId
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
return deviceId
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
406
|
}
|
|
610
407
|
|
|
611
408
|
const requestMap: KV<CloudbaseRequest> = {};
|
|
@@ -613,10 +410,10 @@ const requestMap: KV<CloudbaseRequest> = {};
|
|
|
613
410
|
export function initRequest(config: ICloudbaseRequestConfig) {
|
|
614
411
|
requestMap[config.env] = new CloudbaseRequest({
|
|
615
412
|
...config,
|
|
616
|
-
throw: true
|
|
413
|
+
throw: true,
|
|
617
414
|
});
|
|
618
415
|
}
|
|
619
416
|
|
|
620
417
|
export function getRequestByEnvId(env: string): CloudbaseRequest {
|
|
621
418
|
return requestMap[env];
|
|
622
|
-
}
|
|
419
|
+
}
|
package/.eslintrc
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"eslint-config-alloy/typescript"
|
|
4
|
-
],
|
|
5
|
-
"rules": {
|
|
6
|
-
"indent": [
|
|
7
|
-
"error",
|
|
8
|
-
2,
|
|
9
|
-
{
|
|
10
|
-
"SwitchCase": 1,
|
|
11
|
-
"flatTernaryExpressions": true
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"guard-for-in": 0,
|
|
15
|
-
"no-param-reassign": 0,
|
|
16
|
-
"no-undefined": 0,
|
|
17
|
-
"@typescript-eslint/explicit-member-accessibility": 0,
|
|
18
|
-
"@typescript-eslint/consistent-type-assertions": 0,
|
|
19
|
-
"@typescript-eslint/no-loss-of-precision": 0,
|
|
20
|
-
"@typescript-eslint/no-duplicate-imports": 0
|
|
21
|
-
},
|
|
22
|
-
"parserOptions": {
|
|
23
|
-
"ecmaVersion": 6,
|
|
24
|
-
"sourceType": "module",
|
|
25
|
-
"ecmaFeatures": {
|
|
26
|
-
"modules": true
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|