@cloudbase/app 1.5.3-alpha.0 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/libs/cache.js +2 -20
- package/dist/cjs/libs/request.d.ts +1 -16
- package/dist/cjs/libs/request.js +17 -482
- package/dist/esm/libs/cache.js +2 -20
- package/dist/esm/libs/request.d.ts +1 -16
- package/dist/esm/libs/request.js +20 -485
- package/package.json +4 -4
- package/src/libs/cache.ts +22 -23
- package/src/libs/request.ts +10 -383
- package/dist/cjs/constants/events.d.ts +0 -7
- package/dist/cjs/constants/events.js +0 -11
- package/dist/esm/constants/events.d.ts +0 -7
- package/dist/esm/constants/events.js +0 -8
- package/src/constants/events.ts +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/app",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
4
|
"description": "cloudbase javascript sdk core",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@cloudbase/adapter-interface": "^0.4.0",
|
|
31
|
-
"@cloudbase/types": "^
|
|
32
|
-
"@cloudbase/utilities": "^
|
|
31
|
+
"@cloudbase/types": "^2.0.0-alpha.0",
|
|
32
|
+
"@cloudbase/utilities": "^2.0.0-alpha.0",
|
|
33
33
|
"cloudbase-adapter-wx_mp": "0.2.0",
|
|
34
34
|
"uuid": "^8.3.2"
|
|
35
35
|
},
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"eslint --fix"
|
|
54
54
|
]
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "9ab9ea4322a548cd981d5fe747b6dee911272a6d"
|
|
57
57
|
}
|
package/src/libs/cache.ts
CHANGED
|
@@ -2,13 +2,13 @@ import { KV } from "@cloudbase/types";
|
|
|
2
2
|
import { cache } from "@cloudbase/utilities";
|
|
3
3
|
import { ICloudbaseCache, ICacheConfig } from "@cloudbase/types/cache";
|
|
4
4
|
|
|
5
|
-
const KEY_ACCESS_TOKEN = 'access_token';
|
|
6
|
-
const KEY_ACCESS_TOKEN_EXPIRE = 'access_token_expire';
|
|
7
|
-
const KEY_REFRESH_TOKEN = 'refresh_token';
|
|
8
|
-
const KEY_ANONYMOUS_UUID = 'anonymous_uuid';
|
|
9
|
-
const KEY_LOGIN_TYPE = 'login_type';
|
|
10
5
|
const USER_INFO_KEY = 'user_info';
|
|
11
|
-
const
|
|
6
|
+
// const KEY_ACCESS_TOKEN = 'access_token';
|
|
7
|
+
// const KEY_ACCESS_TOKEN_EXPIRE = 'access_token_expire';
|
|
8
|
+
// const KEY_REFRESH_TOKEN = 'refresh_token';
|
|
9
|
+
// const KEY_ANONYMOUS_UUID = 'anonymous_uuid';
|
|
10
|
+
// const KEY_LOGIN_TYPE = 'login_type';
|
|
11
|
+
// const DEVICE_INFO = 'device_id';
|
|
12
12
|
|
|
13
13
|
const { CloudbaseCache } = cache;
|
|
14
14
|
|
|
@@ -16,32 +16,31 @@ const cacheMap: KV<ICloudbaseCache> = {};
|
|
|
16
16
|
// 本地存储
|
|
17
17
|
const localCacheMap: KV<ICloudbaseCache> = {};
|
|
18
18
|
|
|
19
|
-
export function initCache(config: ICacheConfig&{env:string}) {
|
|
20
|
-
const { env,persistence,platformInfo } = config;
|
|
19
|
+
export function initCache(config: ICacheConfig & { env: string }) {
|
|
20
|
+
const { env, persistence, platformInfo } = config;
|
|
21
21
|
|
|
22
|
-
const accessTokenKey
|
|
23
|
-
const accessTokenExpireKey = `${KEY_ACCESS_TOKEN_EXPIRE}_${env}`;
|
|
24
|
-
const refreshTokenKey = `${KEY_REFRESH_TOKEN}_${env}`;
|
|
25
|
-
const anonymousUuidKey = `${KEY_ANONYMOUS_UUID}_${env}`;
|
|
26
|
-
const loginTypeKey = `${KEY_LOGIN_TYPE}_${env}`;
|
|
27
|
-
const userInfoKey
|
|
28
|
-
const deviceIdKey
|
|
22
|
+
// const accessTokenKey = `${KEY_ACCESS_TOKEN}_${env}`;
|
|
23
|
+
// const accessTokenExpireKey = `${KEY_ACCESS_TOKEN_EXPIRE}_${env}`;
|
|
24
|
+
// const refreshTokenKey = `${KEY_REFRESH_TOKEN}_${env}`;
|
|
25
|
+
// const anonymousUuidKey = `${KEY_ANONYMOUS_UUID}_${env}`;
|
|
26
|
+
// const loginTypeKey = `${KEY_LOGIN_TYPE}_${env}`;
|
|
27
|
+
const userInfoKey = `${USER_INFO_KEY}_${env}`;
|
|
28
|
+
// const deviceIdKey = `${DEVICE_INFO}`; // 非环境级别
|
|
29
29
|
|
|
30
30
|
const keys = {
|
|
31
|
-
accessTokenKey,
|
|
32
|
-
accessTokenExpireKey,
|
|
33
|
-
refreshTokenKey,
|
|
34
|
-
anonymousUuidKey,
|
|
35
|
-
loginTypeKey,
|
|
36
31
|
userInfoKey,
|
|
37
|
-
|
|
32
|
+
// accessTokenKey,
|
|
33
|
+
// accessTokenExpireKey,
|
|
34
|
+
// refreshTokenKey,
|
|
35
|
+
// anonymousUuidKey,
|
|
36
|
+
// loginTypeKey,
|
|
37
|
+
// deviceIdKey
|
|
38
38
|
};
|
|
39
39
|
// 若指定env已存在cache则尝试更新persistence
|
|
40
|
-
cacheMap[env]?cacheMap[env].updatePersistence(persistence):(cacheMap[env] = new CloudbaseCache({
|
|
40
|
+
cacheMap[env] ? cacheMap[env].updatePersistence(persistence) : (cacheMap[env] = new CloudbaseCache({
|
|
41
41
|
...config,
|
|
42
42
|
keys,
|
|
43
43
|
platformInfo,
|
|
44
|
-
alwaysLocalKeys: ['anonymousUuidKey']
|
|
45
44
|
}));
|
|
46
45
|
localCacheMap[env] = localCacheMap[env] || new CloudbaseCache({
|
|
47
46
|
...config,
|
package/src/libs/request.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DATA_VERSION,
|
|
3
|
-
LOGINTYPE,
|
|
4
3
|
getSdkVersion,
|
|
5
4
|
getEndPoint,
|
|
6
|
-
getBaseEndPoint
|
|
7
|
-
OAUTH2_LOGINTYPE_PREFIX
|
|
5
|
+
getBaseEndPoint
|
|
8
6
|
} from '../constants/common';
|
|
9
7
|
import {
|
|
10
8
|
IRequestOptions,
|
|
@@ -13,20 +11,16 @@ import {
|
|
|
13
11
|
IUploadRequestOptions,
|
|
14
12
|
IRequestConfig
|
|
15
13
|
} from '@cloudbase/adapter-interface';
|
|
16
|
-
import { utils,
|
|
17
|
-
import { KV
|
|
14
|
+
import { utils, adapters, constants } from '@cloudbase/utilities';
|
|
15
|
+
import { KV } from '@cloudbase/types';
|
|
18
16
|
import { IGetAccessTokenResult, ICloudbaseRequestConfig, IAppendedRequestInfo, IRequestBeforeHook } from '@cloudbase/types/request';
|
|
19
17
|
import { ICloudbaseCache } from '@cloudbase/types/cache';
|
|
20
|
-
import {
|
|
21
|
-
import { getCacheByEnvId, getLocalCache } from './cache';
|
|
22
|
-
import { EVENTS } from '../constants/events';
|
|
18
|
+
import { getLocalCache } from './cache';
|
|
23
19
|
import { Platform } from './adapter';
|
|
24
|
-
const {
|
|
20
|
+
const { ERRORS } = constants;
|
|
25
21
|
const { genSeqId, isFormData, formatUrl, createSign } = utils;
|
|
26
22
|
const { RUNTIME } = adapters;
|
|
27
23
|
|
|
28
|
-
import { v4 as uuidv4 } from 'uuid'
|
|
29
|
-
|
|
30
24
|
// import FingerprintJS from '@fingerprintjs/fingerprintjs'
|
|
31
25
|
// const fpPromise = FingerprintJS.load()
|
|
32
26
|
|
|
@@ -88,12 +82,9 @@ function beforeEach(): IAppendedRequestInfo {
|
|
|
88
82
|
};
|
|
89
83
|
}
|
|
90
84
|
export interface ICloudbaseRequest {
|
|
91
|
-
fetch: (urlOrPath: string, init?: RequestInit) => Promise<Response>;
|
|
92
85
|
post: (options: IRequestOptions) => Promise<ResponseObject>;
|
|
93
86
|
upload: (options: IUploadRequestOptions) => Promise<ResponseObject>;
|
|
94
87
|
download: (options: IRequestOptions) => Promise<ResponseObject>;
|
|
95
|
-
refreshAccessToken: () => Promise<IGetAccessTokenResult>;
|
|
96
|
-
getAccessToken: () => Promise<IGetAccessTokenResult>;
|
|
97
88
|
request: (action: string, params: KV<any>, options?: KV<any>) => Promise<ResponseObject>;
|
|
98
89
|
send: (action: string, data: KV<any>) => Promise<any>;
|
|
99
90
|
}
|
|
@@ -108,19 +99,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
108
99
|
_reqClass: SDKRequestInterface;
|
|
109
100
|
// 请求失败是否抛出Error
|
|
110
101
|
private _throwWhenRequestFail = false;
|
|
111
|
-
private _cache: ICloudbaseCache;
|
|
112
102
|
// 持久化本地存储
|
|
113
103
|
private _localCache: ICloudbaseCache;
|
|
114
|
-
private _fromApp: ICloudbase
|
|
115
104
|
/**
|
|
116
105
|
* 初始化
|
|
117
106
|
* @param config
|
|
118
107
|
*/
|
|
119
108
|
constructor(config: ICloudbaseRequestConfig & { throw?: boolean }) {
|
|
120
|
-
const { _fromApp } = config;
|
|
121
109
|
|
|
122
110
|
this.config = config;
|
|
123
|
-
this._fromApp = _fromApp
|
|
124
111
|
// eslint-disable-next-line
|
|
125
112
|
this._reqClass = new Platform.adapter.reqClass(<IRequestConfig>{
|
|
126
113
|
timeout: this.config.timeout,
|
|
@@ -128,53 +115,12 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
128
115
|
restrictedMethods: ['post']
|
|
129
116
|
});
|
|
130
117
|
this._throwWhenRequestFail = config.throw || false;
|
|
131
|
-
this._cache = getCacheByEnvId(this.config.env);
|
|
132
118
|
this._localCache = getLocalCache(this.config.env);
|
|
133
119
|
bindHooks(this._reqClass, 'post', [beforeEach]);
|
|
134
120
|
bindHooks(this._reqClass, 'upload', [beforeEach]);
|
|
135
121
|
bindHooks(this._reqClass, 'download', [beforeEach]);
|
|
136
122
|
}
|
|
137
123
|
|
|
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
124
|
public async post(options: IRequestOptions): Promise<ResponseObject> {
|
|
179
125
|
const res = await this._reqClass.post(options);
|
|
180
126
|
return res;
|
|
@@ -188,62 +134,8 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
188
134
|
return res;
|
|
189
135
|
}
|
|
190
136
|
|
|
191
|
-
public
|
|
192
|
-
|
|
193
|
-
if (!this._refreshAccessTokenPromise) {
|
|
194
|
-
// 没有正在刷新,那么正常执行刷新逻辑
|
|
195
|
-
this._refreshAccessTokenPromise = this._refreshAccessToken();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
let result;
|
|
199
|
-
let err;
|
|
200
|
-
try {
|
|
201
|
-
result = await this._refreshAccessTokenPromise;
|
|
202
|
-
} catch (e) {
|
|
203
|
-
err = e;
|
|
204
|
-
}
|
|
205
|
-
this._refreshAccessTokenPromise = null;
|
|
206
|
-
this._shouldRefreshAccessTokenHook = null;
|
|
207
|
-
if (err) {
|
|
208
|
-
throw err;
|
|
209
|
-
}
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
public async refreshAccessTokenFromOauthServer(clientId: string): Promise<IGetAccessTokenResult> {
|
|
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
|
-
}
|
|
137
|
+
public getBaseEndPoint() {
|
|
138
|
+
return getBaseEndPoint()
|
|
247
139
|
}
|
|
248
140
|
|
|
249
141
|
public async getOauthAccessTokenV2(oauthClient: any): Promise<IGetAccessTokenResult> {
|
|
@@ -255,66 +147,9 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
255
147
|
}
|
|
256
148
|
}
|
|
257
149
|
|
|
258
|
-
// 获取 access token
|
|
259
|
-
public async getAccessToken(): Promise<IGetAccessTokenResult> {
|
|
260
|
-
const { loginTypeKey, accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
|
|
261
|
-
const loginType = await this._cache.getStoreAsync(loginTypeKey);
|
|
262
|
-
const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
263
|
-
if (!refreshToken) {
|
|
264
|
-
// 不该出现的状态:有 access token 却没有 refresh token
|
|
265
|
-
throw new Error(JSON.stringify({
|
|
266
|
-
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'
|
|
268
|
-
}));
|
|
269
|
-
}
|
|
270
|
-
// 如果没有access token或者过期,那么刷新
|
|
271
|
-
const accessToken = await this._cache.getStoreAsync(accessTokenKey);
|
|
272
|
-
const accessTokenExpire = Number(await this._cache.getStoreAsync(accessTokenExpireKey));
|
|
273
|
-
|
|
274
|
-
// 调用钩子函数
|
|
275
|
-
let shouldRefreshAccessToken = true;
|
|
276
|
-
if (this._shouldRefreshAccessTokenHook && !(await this._shouldRefreshAccessTokenHook(accessToken, accessTokenExpire))) {
|
|
277
|
-
shouldRefreshAccessToken = false;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if ((!accessToken || !accessTokenExpire || accessTokenExpire < Date.now()) && shouldRefreshAccessToken) {
|
|
281
|
-
if (loginType.startsWith(OAUTH2_LOGINTYPE_PREFIX)) {
|
|
282
|
-
// NOTE: 这里需要从 accessToken 解出来部分信息,用于刷新 accessToken
|
|
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
|
-
};
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
150
|
|
|
315
151
|
/* eslint-disable complexity */
|
|
316
152
|
public async request(action: string, params: KV<any>, options?: KV<any>): Promise<ResponseObject> {
|
|
317
|
-
const { oauthClient } = this.config
|
|
318
153
|
const tcbTraceKey = `x-tcb-trace_${this.config.env}`;
|
|
319
154
|
let contentType = 'application/x-www-form-urlencoded';
|
|
320
155
|
// const webDeviceId = await getTcbFingerprintId();
|
|
@@ -326,28 +161,10 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
326
161
|
...params
|
|
327
162
|
};
|
|
328
163
|
|
|
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
|
-
|
|
343
164
|
if (ACTIONS_WITHOUT_ACCESSTOKEN.indexOf(action) === -1) {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
348
|
-
if (refreshToken) {
|
|
349
|
-
tmpObj.access_token = (await this.getAccessToken()).accessToken;
|
|
350
|
-
}
|
|
165
|
+
const app = this.config._fromApp
|
|
166
|
+
const oauthClient = app.oauthInstance.oauth2client
|
|
167
|
+
tmpObj.access_token = (await this.getOauthAccessTokenV2(oauthClient)).accessToken
|
|
351
168
|
}
|
|
352
169
|
|
|
353
170
|
// 拼body和content-type
|
|
@@ -443,11 +260,6 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
443
260
|
|
|
444
261
|
public async send(action: string, data: KV<any> = {}): Promise<any> {
|
|
445
262
|
let response = await this.request(action, data, { onUploadProgress: data.onUploadProgress });
|
|
446
|
-
if (response.data.code === 'ACCESS_TOKEN_EXPIRED' && ACTIONS_WITHOUT_ACCESSTOKEN.indexOf(action) === -1) {
|
|
447
|
-
// access_token过期,重新获取
|
|
448
|
-
await this.refreshAccessToken();
|
|
449
|
-
response = await this.request(action, data, { onUploadProgress: data.onUploadProgress });
|
|
450
|
-
}
|
|
451
263
|
|
|
452
264
|
if (response.data.code && this._throwWhenRequestFail) {
|
|
453
265
|
throw new Error(JSON.stringify({
|
|
@@ -458,191 +270,6 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
458
270
|
|
|
459
271
|
return response.data;
|
|
460
272
|
}
|
|
461
|
-
|
|
462
|
-
// 调用接口刷新access token,并且返回
|
|
463
|
-
private async _refreshAccessToken(retryNum = 1): Promise<IGetAccessTokenResult> {
|
|
464
|
-
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey, loginTypeKey, anonymousUuidKey } = this._cache.keys;
|
|
465
|
-
await this._cache.removeStoreAsync(accessTokenKey);
|
|
466
|
-
await this._cache.removeStoreAsync(accessTokenExpireKey);
|
|
467
|
-
|
|
468
|
-
let refreshToken = await this._cache.getStoreAsync(refreshTokenKey);
|
|
469
|
-
if (!refreshToken) {
|
|
470
|
-
throw new Error(JSON.stringify({
|
|
471
|
-
code: ERRORS.INVALID_OPERATION,
|
|
472
|
-
msg: 'not login'
|
|
473
|
-
}));
|
|
474
|
-
}
|
|
475
|
-
const params: KV<string> = {
|
|
476
|
-
refresh_token: refreshToken
|
|
477
|
-
};
|
|
478
|
-
const response = await this.request('auth.fetchAccessTokenWithRefreshToken', params);
|
|
479
|
-
if (response.data.code) {
|
|
480
|
-
const { code } = response.data;
|
|
481
|
-
if (code === 'SIGN_PARAM_INVALID' || code === 'REFRESH_TOKEN_EXPIRED' || code === 'INVALID_REFRESH_TOKEN') {
|
|
482
|
-
// 这里处理以下逻辑:
|
|
483
|
-
// 匿名登录时,如果刷新access token报错refresh token过期,此时应该:
|
|
484
|
-
// 1. 再用 uuid 拿一次新的refresh token
|
|
485
|
-
// 2. 拿新的refresh token换access token
|
|
486
|
-
const isAnonymous = await this._cache.getStoreAsync(loginTypeKey) === LOGINTYPE.ANONYMOUS;
|
|
487
|
-
if (isAnonymous && code === 'INVALID_REFRESH_TOKEN') {
|
|
488
|
-
// 获取新的 refresh token
|
|
489
|
-
const anonymous_uuid = await this._cache.getStoreAsync(anonymousUuidKey);
|
|
490
|
-
// 此处cache为基类property
|
|
491
|
-
const refresh_token = await this._cache.getStoreAsync(refreshTokenKey);
|
|
492
|
-
const res = await this.send('auth.signInAnonymously', {
|
|
493
|
-
anonymous_uuid,
|
|
494
|
-
refresh_token
|
|
495
|
-
});
|
|
496
|
-
this._setRefreshToken(res.refresh_token);
|
|
497
|
-
if (retryNum >= 1) {
|
|
498
|
-
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
|
-
}
|
|
507
|
-
}
|
|
508
|
-
cloudbase.fire(EVENTS.LOGIN_STATE_EXPIRED);
|
|
509
|
-
await this._cache.removeStoreAsync(refreshTokenKey);
|
|
510
|
-
}
|
|
511
|
-
throw new Error(JSON.stringify({
|
|
512
|
-
code: ERRORS.NETWORK_ERROR,
|
|
513
|
-
msg: `refresh access_token failed:${response.data.code}`
|
|
514
|
-
}));
|
|
515
|
-
}
|
|
516
|
-
if (response.data.access_token) {
|
|
517
|
-
cloudbase.fire(EVENTS.ACCESS_TOKEN_REFRESHD);
|
|
518
|
-
await this._cache.setStoreAsync(accessTokenKey, response.data.access_token);
|
|
519
|
-
// 本地时间可能没有同步
|
|
520
|
-
await this._cache.setStoreAsync(accessTokenExpireKey, response.data.access_token_expire + Date.now());
|
|
521
|
-
return {
|
|
522
|
-
accessToken: response.data.access_token,
|
|
523
|
-
accessTokenExpire: response.data.access_token_expire
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
// 匿名登录refresh_token过期情况下返回refresh_token
|
|
527
|
-
// 此场景下使用新的refresh_token获取access_token
|
|
528
|
-
if (response.data.refresh_token) {
|
|
529
|
-
await this._cache.removeStoreAsync(refreshTokenKey);
|
|
530
|
-
await this._cache.setStoreAsync(refreshTokenKey, response.data.refresh_token);
|
|
531
|
-
await this._refreshAccessToken();
|
|
532
|
-
}
|
|
533
|
-
}
|
|
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
|
-
private async _setRefreshToken(refreshToken: string) {
|
|
607
|
-
const { accessTokenKey, accessTokenExpireKey, refreshTokenKey } = this._cache.keys;
|
|
608
|
-
// refresh token设置前,先清掉 access token
|
|
609
|
-
// 设置是直接拉取新 access token 覆盖,而不是 remove
|
|
610
|
-
await this._cache.removeStoreAsync(accessTokenKey);
|
|
611
|
-
await this._cache.removeStoreAsync(accessTokenExpireKey);
|
|
612
|
-
await this._cache.setStoreAsync(refreshTokenKey, refreshToken);
|
|
613
|
-
}
|
|
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
273
|
}
|
|
647
274
|
|
|
648
275
|
const requestMap: KV<CloudbaseRequest> = {};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EVENTS = void 0;
|
|
4
|
-
exports.EVENTS = {
|
|
5
|
-
LOGIN_STATE_CHANGED: 'loginStateChanged',
|
|
6
|
-
LOGIN_STATE_EXPIRED: 'loginStateExpire',
|
|
7
|
-
LOGIN_TYPE_CHANGED: 'loginTypeChanged',
|
|
8
|
-
ANONYMOUS_CONVERTED: 'anonymousConverted',
|
|
9
|
-
ACCESS_TOKEN_REFRESHD: 'refreshAccessToken'
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbnN0YW50cy9ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQWEsUUFBQSxNQUFNLEdBQUc7SUFDcEIsbUJBQW1CLEVBQUksbUJBQW1CO0lBQzFDLG1CQUFtQixFQUFJLGtCQUFrQjtJQUN6QyxrQkFBa0IsRUFBSyxrQkFBa0I7SUFDekMsbUJBQW1CLEVBQUksb0JBQW9CO0lBQzNDLHFCQUFxQixFQUFFLG9CQUFvQjtDQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IEVWRU5UUyA9IHtcbiAgTE9HSU5fU1RBVEVfQ0hBTkdFRCAgOiAnbG9naW5TdGF0ZUNoYW5nZWQnLFxuICBMT0dJTl9TVEFURV9FWFBJUkVEICA6ICdsb2dpblN0YXRlRXhwaXJlJyxcbiAgTE9HSU5fVFlQRV9DSEFOR0VEICAgOiAnbG9naW5UeXBlQ2hhbmdlZCcsXG4gIEFOT05ZTU9VU19DT05WRVJURUQgIDogJ2Fub255bW91c0NvbnZlcnRlZCcsIC8v5Yy/5ZCN6LSm5oi36KKr6L2s5q2j5ZCO6Kem5Y+RXG4gIEFDQ0VTU19UT0tFTl9SRUZSRVNIRDogJ3JlZnJlc2hBY2Nlc3NUb2tlbidcbn07XG4iXX0=
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export var EVENTS = {
|
|
2
|
-
LOGIN_STATE_CHANGED: 'loginStateChanged',
|
|
3
|
-
LOGIN_STATE_EXPIRED: 'loginStateExpire',
|
|
4
|
-
LOGIN_TYPE_CHANGED: 'loginTypeChanged',
|
|
5
|
-
ANONYMOUS_CONVERTED: 'anonymousConverted',
|
|
6
|
-
ACCESS_TOKEN_REFRESHD: 'refreshAccessToken'
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbnN0YW50cy9ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLElBQU0sTUFBTSxHQUFHO0lBQ3BCLG1CQUFtQixFQUFJLG1CQUFtQjtJQUMxQyxtQkFBbUIsRUFBSSxrQkFBa0I7SUFDekMsa0JBQWtCLEVBQUssa0JBQWtCO0lBQ3pDLG1CQUFtQixFQUFJLG9CQUFvQjtJQUMzQyxxQkFBcUIsRUFBRSxvQkFBb0I7Q0FDNUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBFVkVOVFMgPSB7XG4gIExPR0lOX1NUQVRFX0NIQU5HRUQgIDogJ2xvZ2luU3RhdGVDaGFuZ2VkJyxcbiAgTE9HSU5fU1RBVEVfRVhQSVJFRCAgOiAnbG9naW5TdGF0ZUV4cGlyZScsXG4gIExPR0lOX1RZUEVfQ0hBTkdFRCAgIDogJ2xvZ2luVHlwZUNoYW5nZWQnLFxuICBBTk9OWU1PVVNfQ09OVkVSVEVEICA6ICdhbm9ueW1vdXNDb252ZXJ0ZWQnLCAvL+WMv+WQjei0puaIt+iiq+i9rOato+WQjuinpuWPkVxuICBBQ0NFU1NfVE9LRU5fUkVGUkVTSEQ6ICdyZWZyZXNoQWNjZXNzVG9rZW4nXG59O1xuIl19
|
package/src/constants/events.ts
DELETED