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