@cloudbase/app 3.0.0 → 3.0.2
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/constants/common.d.ts +7 -5
- package/dist/cjs/constants/common.js +21 -12
- package/dist/cjs/index.d.ts +59 -1
- package/dist/cjs/index.js +24 -55
- package/dist/cjs/libs/adapter.d.ts +1 -0
- package/dist/cjs/libs/adapter.js +160 -2
- package/dist/cjs/libs/request.d.ts +24 -6
- package/dist/cjs/libs/request.js +116 -43
- package/dist/esm/constants/common.d.ts +7 -5
- package/dist/esm/constants/common.js +18 -9
- package/dist/esm/index.d.ts +59 -1
- package/dist/esm/index.js +26 -54
- package/dist/esm/libs/adapter.d.ts +1 -0
- package/dist/esm/libs/adapter.js +135 -1
- package/dist/esm/libs/request.d.ts +24 -6
- package/dist/esm/libs/request.js +116 -43
- package/dist/miniprogram/index.js +1 -1
- package/package.json +5 -5
- package/src/constants/common.ts +29 -13
- package/src/index.d.ts +4 -3
- package/src/index.ts +39 -41
- package/src/libs/adapter.ts +129 -0
- package/src/libs/request.ts +143 -35
- package/dist/cjs/libs/callApis.d.ts +0 -9
- package/dist/cjs/libs/callApis.js +0 -114
- package/dist/esm/libs/callApis.d.ts +0 -9
- package/dist/esm/libs/callApis.js +0 -108
- package/src/libs/callApis.ts +0 -67
package/src/constants/common.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { EndPointKey } from '@cloudbase/types'
|
|
1
2
|
import { constants } from '@cloudbase/utilities'
|
|
2
3
|
|
|
4
|
+
const ZONE_CHINA = ['ap-shanghai', 'ap-guangzhou', 'ap-shenzhen-fsi', 'ap-shanghai-fsi', 'ap-nanjing', 'ap-beijing', 'ap-chengdu', 'ap-chongqing', 'ap-hongkong']
|
|
5
|
+
|
|
3
6
|
// @ts-ignore
|
|
4
7
|
const { setSdkName: setUtilitiesSdkName, setProtocol: setUtilitiesProtocol } = constants
|
|
5
8
|
/**
|
|
@@ -23,15 +26,16 @@ export function getSdkName() {
|
|
|
23
26
|
}
|
|
24
27
|
export const DATA_VERSION = '2020-01-10'
|
|
25
28
|
|
|
26
|
-
export type EndPointKey = 'CLOUD_API' | 'GATEWAY'
|
|
27
|
-
|
|
28
29
|
interface EndPointInfo {
|
|
29
30
|
env: string
|
|
30
31
|
endPointKey: EndPointKey
|
|
31
32
|
region?: string
|
|
32
33
|
baseUrl?: string
|
|
33
|
-
protocol?:
|
|
34
|
+
protocol?: Protocol
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
type Protocol = 'http' | 'https' | 'http:' | 'https:'
|
|
38
|
+
|
|
35
39
|
/**
|
|
36
40
|
* 所有 endPoint 信息
|
|
37
41
|
* 避免直接操作该数组
|
|
@@ -42,18 +46,25 @@ const END_POINT_INFO_ARR: Array<EndPointInfo> = []
|
|
|
42
46
|
/** 用来查找 endPoint 的字段 */
|
|
43
47
|
const END_POINT_INFO_SEARCH_KEYS = ['env', 'endPointKey', 'region']
|
|
44
48
|
|
|
45
|
-
const DEFAULT_PROTOCOL = 'https:'
|
|
49
|
+
export const DEFAULT_PROTOCOL: 'http:' | 'https:' = 'https:'
|
|
46
50
|
|
|
47
51
|
function findMatchedInfo(info: EndPointInfo) {
|
|
52
|
+
// eslint-disable-next-line max-len, eqeqeq
|
|
48
53
|
return END_POINT_INFO_ARR.find(targetInfo => END_POINT_INFO_SEARCH_KEYS.filter(searchKey => info[searchKey] != null).every(searchKey => targetInfo[searchKey] === info[searchKey],),)
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
export function setEndPointInfo(newInfo: EndPointInfo) {
|
|
57
|
+
if (newInfo.protocol && !/:$/.test(newInfo.protocol)) {
|
|
58
|
+
newInfo.protocol = `${newInfo.protocol}:` as Protocol
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
const endPointInfo = findMatchedInfo(newInfo)
|
|
53
62
|
if (endPointInfo) {
|
|
63
|
+
// eslint-disable-next-line eqeqeq
|
|
54
64
|
if (newInfo.baseUrl != null) {
|
|
55
65
|
endPointInfo.baseUrl = newInfo.baseUrl
|
|
56
66
|
}
|
|
67
|
+
// eslint-disable-next-line eqeqeq
|
|
57
68
|
if (newInfo.protocol != null) {
|
|
58
69
|
endPointInfo.protocol = newInfo.protocol
|
|
59
70
|
}
|
|
@@ -63,7 +74,7 @@ export function setEndPointInfo(newInfo: EndPointInfo) {
|
|
|
63
74
|
|
|
64
75
|
// 保持旧代码逻辑
|
|
65
76
|
if (newInfo.endPointKey === 'CLOUD_API') {
|
|
66
|
-
setUtilitiesProtocol((newInfo.protocol ?? DEFAULT_PROTOCOL) as 'http' | 'https')
|
|
77
|
+
setUtilitiesProtocol((newInfo.protocol ?? DEFAULT_PROTOCOL) as 'http:' | 'https:')
|
|
67
78
|
}
|
|
68
79
|
}
|
|
69
80
|
|
|
@@ -77,18 +88,23 @@ export interface ISetEndPointWithKey {
|
|
|
77
88
|
protocol?: 'http' | 'https'
|
|
78
89
|
}
|
|
79
90
|
|
|
80
|
-
export function setGatewayEndPointWithEnv(env: string, protocol?:
|
|
81
|
-
|
|
91
|
+
export function setGatewayEndPointWithEnv(env: string, protocol?: Protocol, region = 'ap-shanghai') {
|
|
92
|
+
region = region || 'ap-shanghai'
|
|
93
|
+
let baseUrl = `//${env}.api.tcloudbasegateway.com/v1`
|
|
94
|
+
|
|
95
|
+
if (!ZONE_CHINA.includes(region)) {
|
|
96
|
+
baseUrl = `//${env}.api.intl.tcloudbasegateway.com/v1`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
setEndPointInfo({ endPointKey: 'GATEWAY', env, baseUrl, protocol })
|
|
82
100
|
}
|
|
83
|
-
export function setRegionLevelEndpoint(env: string, region: string, protocol?:
|
|
84
|
-
const baseUrl = region
|
|
85
|
-
? `//${env}.${region}.tcb-api.tencentcloudapi.com/web`
|
|
86
|
-
: `//${env}.ap-shanghai.tcb-api.tencentcloudapi.com/web`
|
|
101
|
+
export function setRegionLevelEndpoint(env: string, region: string, protocol?: Protocol) {
|
|
102
|
+
const baseUrl = `//${env}.${region || 'ap-shanghai'}.tcb-api.tencentcloudapi.com/web`
|
|
87
103
|
setEndPointInfo({ env, region, baseUrl, protocol, endPointKey: 'CLOUD_API' })
|
|
88
104
|
}
|
|
89
105
|
|
|
90
|
-
export function getBaseEndPoint(env: string) {
|
|
91
|
-
const info = getEndPointInfo(env, 'CLOUD_API')
|
|
106
|
+
export function getBaseEndPoint(env: string, endPointKey: EndPointKey = 'CLOUD_API') {
|
|
107
|
+
const info = getEndPointInfo(env, endPointKey || 'CLOUD_API')
|
|
92
108
|
|
|
93
109
|
const { protocol: PROTOCOL, baseUrl: BASE_URL } = info
|
|
94
110
|
const webEndpoint = `${PROTOCOL}${BASE_URL}`
|
package/src/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import cloudbase from '@cloudbase/app';
|
|
2
2
|
import { ICloudbase } from '@cloudbase/types';
|
|
3
3
|
declare global {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
interface Window {
|
|
5
|
+
cloudbase: ICloudbase;
|
|
6
|
+
}
|
|
7
7
|
}
|
|
8
|
+
// @ts-ignore
|
|
8
9
|
export = cloudbase;
|
|
9
10
|
export default cloudbase;
|
package/src/index.ts
CHANGED
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
ICloudbaseExtension,
|
|
8
8
|
KV,
|
|
9
9
|
ICloudbasePlatformInfo,
|
|
10
|
+
EndPointKey,
|
|
11
|
+
ICloudbaseApis,
|
|
10
12
|
} from '@cloudbase/types'
|
|
11
13
|
import { ICloudbaseAuth } from '@cloudbase/types/auth'
|
|
12
|
-
import adapterForWxMp from '@cloudbase/adapter-wx_mp'
|
|
13
14
|
import { registerComponent, registerHook } from './libs/component'
|
|
14
|
-
import { Platform } from './libs/adapter'
|
|
15
|
+
import { getWxDefaultAdapter, Platform } from './libs/adapter'
|
|
15
16
|
import { ICloudbaseComponent, ICloudbaseHook } from '@cloudbase/types/component'
|
|
16
17
|
import { ICloudbaseCache } from '@cloudbase/types/cache'
|
|
17
18
|
import { initCache, getCacheByEnvId, getLocalCache } from './libs/cache'
|
|
@@ -23,14 +24,13 @@ import {
|
|
|
23
24
|
setRegionLevelEndpoint,
|
|
24
25
|
setSdkName,
|
|
25
26
|
setGatewayEndPointWithEnv,
|
|
26
|
-
type EndPointKey,
|
|
27
27
|
type ISetEndPointWithKey,
|
|
28
28
|
setEndPointInfo,
|
|
29
29
|
getEndPointInfo,
|
|
30
30
|
getSdkVersion,
|
|
31
|
+
DEFAULT_PROTOCOL,
|
|
31
32
|
} from './constants/common'
|
|
32
33
|
import { i18nProxy, LANGS } from './libs/lang'
|
|
33
|
-
import { generateApis, generateCallApis } from './libs/callApis'
|
|
34
34
|
export { getBaseEndPoint } from './constants/common'
|
|
35
35
|
export { LANGS } from './libs/lang'
|
|
36
36
|
const { useAdapters, useDefaultAdapter } = adapters
|
|
@@ -43,7 +43,7 @@ const { catchErrorsDecorator } = helpers
|
|
|
43
43
|
*/
|
|
44
44
|
const DEFAULT_INIT_CONFIG: Partial<ICloudbaseConfig> = {
|
|
45
45
|
timeout: 15000,
|
|
46
|
-
persistence: 'local',
|
|
46
|
+
persistence: 'local', // 持久化存储类型
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// timeout上限10分钟
|
|
@@ -59,6 +59,8 @@ class Cloudbase implements ICloudbase {
|
|
|
59
59
|
public requestClient: any
|
|
60
60
|
public oauthClient: any
|
|
61
61
|
public version: string
|
|
62
|
+
public auth: ICloudbase['auth'] & ICloudbaseAuth
|
|
63
|
+
public apis: ICloudbaseApis
|
|
62
64
|
private cloudbaseConfig: ICloudbaseConfig
|
|
63
65
|
|
|
64
66
|
constructor(config?: ICloudbaseConfig) {
|
|
@@ -88,10 +90,6 @@ class Cloudbase implements ICloudbase {
|
|
|
88
90
|
return getRequestByEnvId(this.cloudbaseConfig.env)
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
get apis(): { [key: string]: typeof generateCallApis } {
|
|
92
|
-
return generateApis.call(this)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
93
|
@catchErrorsDecorator({
|
|
96
94
|
mode: 'sync',
|
|
97
95
|
title: 'Cloudbase 初始化失败',
|
|
@@ -109,6 +107,8 @@ class Cloudbase implements ICloudbase {
|
|
|
109
107
|
msg: 'env must not be specified',
|
|
110
108
|
}),)
|
|
111
109
|
}
|
|
110
|
+
config.endPointMode = config.endPointMode || 'GATEWAY'
|
|
111
|
+
|
|
112
112
|
// 初始化时若未兼容平台,则使用默认adapter
|
|
113
113
|
if (!Platform.adapter) {
|
|
114
114
|
this.useDefaultAdapter()
|
|
@@ -137,12 +137,23 @@ class Cloudbase implements ICloudbase {
|
|
|
137
137
|
initCache({ env, persistence, debug, platformInfo: this.platform })
|
|
138
138
|
|
|
139
139
|
setRegionLevelEndpoint(env, config.region || '')
|
|
140
|
-
setGatewayEndPointWithEnv(env)
|
|
140
|
+
setGatewayEndPointWithEnv(env, DEFAULT_PROTOCOL, config.region || '')
|
|
141
141
|
|
|
142
142
|
const app = new Cloudbase(this.cloudbaseConfig)
|
|
143
|
-
initRequest({
|
|
143
|
+
initRequest({
|
|
144
|
+
env,
|
|
145
|
+
region: config.region || '',
|
|
146
|
+
timeout,
|
|
147
|
+
oauthClient,
|
|
148
|
+
_fromApp: app,
|
|
149
|
+
i18n,
|
|
150
|
+
endPointMode: config.endPointMode,
|
|
151
|
+
})
|
|
144
152
|
app.requestClient = this.requestClient
|
|
145
153
|
;(this as any)?.fire?.('cloudbase_init', app)
|
|
154
|
+
|
|
155
|
+
this.try2InitAuth(app)
|
|
156
|
+
|
|
146
157
|
return app
|
|
147
158
|
}
|
|
148
159
|
|
|
@@ -233,38 +244,11 @@ class Cloudbase implements ICloudbase {
|
|
|
233
244
|
|
|
234
245
|
// 解析URL参数
|
|
235
246
|
public parseCaptcha(url) {
|
|
236
|
-
|
|
237
|
-
const matched = url.match(/^(data:.*?)(\?[^#\s]*)?$/)
|
|
238
|
-
if (matched) {
|
|
239
|
-
url = matched[1]
|
|
240
|
-
const search = matched[2]
|
|
241
|
-
if (search) {
|
|
242
|
-
queryObj = utils.parseQueryString(search)
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const { token, ...restQueryObj } = queryObj
|
|
246
|
-
if (/^data:/.test(url) && !token) {
|
|
247
|
-
return {
|
|
248
|
-
error: 'invalid_argument',
|
|
249
|
-
error_description: `invalid captcha data: ${url}`,
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (!token) {
|
|
253
|
-
return {
|
|
254
|
-
error: 'unimplemented',
|
|
255
|
-
error_description: 'need to impl captcha data',
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
// 解析url得到的参数
|
|
259
|
-
return {
|
|
260
|
-
state: restQueryObj.state,
|
|
261
|
-
token, // 验证码token
|
|
262
|
-
captchaData: url, // 验证码base64图片
|
|
263
|
-
}
|
|
247
|
+
return utils.parseCaptcha(url)
|
|
264
248
|
}
|
|
265
249
|
|
|
266
250
|
private useDefaultAdapter() {
|
|
267
|
-
const { adapter, runtime } = useDefaultAdapter()
|
|
251
|
+
const { adapter, runtime } = useDefaultAdapter.bind(this)()
|
|
268
252
|
Platform.adapter = adapter as SDKAdapterInterface
|
|
269
253
|
Platform.runtime = runtime as string
|
|
270
254
|
}
|
|
@@ -281,9 +265,23 @@ class Cloudbase implements ICloudbase {
|
|
|
281
265
|
return timeout
|
|
282
266
|
}
|
|
283
267
|
}
|
|
268
|
+
|
|
269
|
+
private try2InitAuth(app) {
|
|
270
|
+
try {
|
|
271
|
+
app.auth()
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.log('try2InitAuth error:', error)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
284
276
|
}
|
|
285
277
|
|
|
278
|
+
// 类型导出
|
|
279
|
+
export type { Cloudbase }
|
|
280
|
+
|
|
281
|
+
// 值导出
|
|
286
282
|
export const cloudbase: ICloudbase = new Cloudbase()
|
|
287
|
-
cloudbase.useAdapters(adapterForWxMp)
|
|
288
283
|
|
|
284
|
+
cloudbase.useAdapters(getWxDefaultAdapter())
|
|
285
|
+
|
|
286
|
+
// 默认导出实例
|
|
289
287
|
export default cloudbase
|
package/src/libs/adapter.ts
CHANGED
|
@@ -1,3 +1,132 @@
|
|
|
1
1
|
import { ICloudbasePlatformInfo } from '@cloudbase/types'
|
|
2
|
+
import adapterForWxMp, { WxRequest, WxMpWebSocket, wxMpStorage, parseQueryString } from '@cloudbase/adapter-wx_mp'
|
|
3
|
+
import { IUploadRequestOptions, StorageType } from '@cloudbase/adapter-interface'
|
|
4
|
+
|
|
5
|
+
declare const wx: any
|
|
6
|
+
declare const App: any
|
|
7
|
+
declare const getApp: any
|
|
2
8
|
|
|
3
9
|
export const Platform: ICloudbasePlatformInfo = {}
|
|
10
|
+
|
|
11
|
+
export const getWxDefaultAdapter = () => {
|
|
12
|
+
WxRequest.prototype.upload = function (options: IUploadRequestOptions) {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
14
|
+
const self = this
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const { url, file, data, headers } = options
|
|
17
|
+
const fs = wx.getFileSystemManager() // 读取文件 二进制内容
|
|
18
|
+
const task = wx.request({
|
|
19
|
+
url,
|
|
20
|
+
method: options.method,
|
|
21
|
+
header: {
|
|
22
|
+
'content-type': ' ', // 小程序 content-type 默认为 application/json, 这里一定要强制为 空, 否则签名错误
|
|
23
|
+
...headers,
|
|
24
|
+
},
|
|
25
|
+
data: fs.readFileSync(file), // 将二进制文件转为字符串直接赋值到 request payload, 不要以 form 的方式传输
|
|
26
|
+
timeout: this._timeout,
|
|
27
|
+
success(res: { statusCode: number; data: unknown }) {
|
|
28
|
+
const result = {
|
|
29
|
+
statusCode: res.statusCode,
|
|
30
|
+
data: res.data || {},
|
|
31
|
+
}
|
|
32
|
+
if (res.statusCode === 200 && data?.success_action_status) {
|
|
33
|
+
result.statusCode = parseInt(data.success_action_status, 10)
|
|
34
|
+
}
|
|
35
|
+
resolve(result)
|
|
36
|
+
},
|
|
37
|
+
fail(err: unknown) {
|
|
38
|
+
resolve(err)
|
|
39
|
+
},
|
|
40
|
+
complete(err: { errMsg: string }) {
|
|
41
|
+
if (!err?.errMsg) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if (!self._timeout || self._restrictedMethods.indexOf('upload') === -1) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const { errMsg } = err
|
|
48
|
+
if (errMsg === 'request:fail timeout') {
|
|
49
|
+
console.warn(self._timeoutMsg)
|
|
50
|
+
try {
|
|
51
|
+
task.abort()
|
|
52
|
+
} catch (e) {}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isPlugin() {
|
|
60
|
+
return (
|
|
61
|
+
typeof App === 'undefined'
|
|
62
|
+
&& typeof getApp === 'undefined'
|
|
63
|
+
&& !wx.onAppHide
|
|
64
|
+
&& !wx.offAppHide
|
|
65
|
+
&& !wx.onAppShow
|
|
66
|
+
&& !wx.offAppShow
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
adapterForWxMp.genAdapter = function genAdapter(options) {
|
|
70
|
+
const adapter = {
|
|
71
|
+
root: { globalThis: {} },
|
|
72
|
+
reqClass: WxRequest,
|
|
73
|
+
wsClass: WxMpWebSocket,
|
|
74
|
+
captchaOptions: {
|
|
75
|
+
openURIWithCallback: (_url: string) => {
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
77
|
+
const { EventBus } = options
|
|
78
|
+
let queryObj: Record<string, string> = {}
|
|
79
|
+
let url = _url
|
|
80
|
+
console.log('openURIWithCallback', _url)
|
|
81
|
+
const matched = _url.match(/^(data:.*?)(\?[^#\s]*)?$/)
|
|
82
|
+
if (matched) {
|
|
83
|
+
// eslint-disable-next-line prefer-destructuring
|
|
84
|
+
url = matched[1]
|
|
85
|
+
console.log('openURIWithCallback url', url)
|
|
86
|
+
const search = matched[2]
|
|
87
|
+
if (search) {
|
|
88
|
+
queryObj = parseQueryString(search)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log('openURIWithCallback queryObj', queryObj)
|
|
92
|
+
const { token, ...restQueryObj } = queryObj
|
|
93
|
+
if (/^data:/.test(url) && !token) {
|
|
94
|
+
// 如果是 data: 开头的 URL 且没有 token,则直接返回
|
|
95
|
+
return Promise.reject({
|
|
96
|
+
error: 'invalid_argument',
|
|
97
|
+
error_description: `invalie captcha data: ${_url}`,
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
if (!token) {
|
|
101
|
+
return Promise.reject({
|
|
102
|
+
error: 'unimplemented',
|
|
103
|
+
error_description: 'need to impl captcha data',
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
console.log('wait for captcha...')
|
|
108
|
+
EventBus.$emit('CAPTCHA_DATA_CHANGE', { ...restQueryObj, token, url })
|
|
109
|
+
|
|
110
|
+
// 监听事件总线,等待验证码数据变化
|
|
111
|
+
EventBus.$once('RESOLVE_CAPTCHA_DATA', (res: { captcha_token: string; expires_in: number }) => {
|
|
112
|
+
resolve(res)
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
localStorage: wxMpStorage,
|
|
118
|
+
primaryStorage: StorageType.local,
|
|
119
|
+
getAppSign() {
|
|
120
|
+
const info = wx.getAccountInfoSync()
|
|
121
|
+
if (isPlugin()) {
|
|
122
|
+
// 插件环境返回插件appid
|
|
123
|
+
return info && info.plugin ? info.plugin.appId : ''
|
|
124
|
+
}
|
|
125
|
+
return info && info.miniProgram ? info.miniProgram.appId : ''
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
return adapter
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return adapterForWxMp
|
|
132
|
+
}
|
package/src/libs/request.ts
CHANGED
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
IFetchOptions,
|
|
9
9
|
} from '@cloudbase/adapter-interface'
|
|
10
10
|
import { utils, constants, langEvent } from '@cloudbase/utilities'
|
|
11
|
-
import { KV } from '@cloudbase/types'
|
|
11
|
+
import { EndPointKey, KV } from '@cloudbase/types'
|
|
12
|
+
import { ICustomReqOpts } from '@cloudbase/types/functions'
|
|
12
13
|
import {
|
|
13
14
|
IGetAccessTokenResult,
|
|
14
15
|
ICloudbaseRequestConfig,
|
|
@@ -79,6 +80,14 @@ function beforeEach(): IAppendedRequestInfo {
|
|
|
79
80
|
},
|
|
80
81
|
}
|
|
81
82
|
}
|
|
83
|
+
export interface IGateWayOptions {
|
|
84
|
+
name?: string
|
|
85
|
+
data?: any
|
|
86
|
+
path?: string
|
|
87
|
+
method: string
|
|
88
|
+
header?: {}
|
|
89
|
+
url?: string
|
|
90
|
+
}
|
|
82
91
|
export interface ICloudbaseRequest {
|
|
83
92
|
post: (options: IRequestOptions) => Promise<ResponseObject>
|
|
84
93
|
upload: (options: IUploadRequestOptions) => Promise<ResponseObject>
|
|
@@ -112,21 +121,47 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
112
121
|
this.reqClass = new Platform.adapter.reqClass(reqConfig)
|
|
113
122
|
this.throwWhenRequestFail = config.throw || false
|
|
114
123
|
this.localCache = getLocalCache(this.config.env)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
|
|
125
|
+
if (this.config.endPointMode !== 'GATEWAY') {
|
|
126
|
+
bindHooks(this.reqClass, 'post', [beforeEach])
|
|
127
|
+
bindHooks(this.reqClass, 'upload', [beforeEach])
|
|
128
|
+
bindHooks(this.reqClass, 'download', [beforeEach])
|
|
129
|
+
}
|
|
118
130
|
|
|
119
131
|
langEvent.bus.on(langEvent.LANG_CHANGE_EVENT, (params) => {
|
|
120
132
|
this.config.i18n = params.data?.i18n || this.config.i18n
|
|
121
133
|
})
|
|
122
134
|
}
|
|
123
135
|
|
|
136
|
+
public async getAccessToken(token = null) {
|
|
137
|
+
// eslint-disable-next-line eqeqeq
|
|
138
|
+
if (token != null) {
|
|
139
|
+
return token
|
|
140
|
+
}
|
|
141
|
+
const app = this.config._fromApp
|
|
142
|
+
|
|
143
|
+
if (!app.oauthInstance) {
|
|
144
|
+
throw new Error('you can\'t request without auth')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const { oauthInstance } = app
|
|
148
|
+
const oauthClient = oauthInstance.oauth2client
|
|
149
|
+
return (await this.getOauthAccessTokenV2(oauthClient)).accessToken
|
|
150
|
+
}
|
|
151
|
+
|
|
124
152
|
public getDefaultHeaders() {
|
|
125
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
[this.config.i18n?.LANG_HEADER_KEY]: this.config.i18n?.lang,
|
|
155
|
+
'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
|
|
156
|
+
}
|
|
126
157
|
}
|
|
127
158
|
|
|
128
|
-
public async post(options: IRequestOptions): Promise<ResponseObject> {
|
|
129
|
-
const res = await this.reqClass.post({
|
|
159
|
+
public async post(options: IRequestOptions, customReqOpts?: ICustomReqOpts): Promise<ResponseObject> {
|
|
160
|
+
const res = await this.reqClass.post({
|
|
161
|
+
...options,
|
|
162
|
+
headers: { ...options.headers, ...this.getDefaultHeaders() },
|
|
163
|
+
customReqOpts,
|
|
164
|
+
})
|
|
130
165
|
return res
|
|
131
166
|
}
|
|
132
167
|
public async upload(options: IUploadRequestOptions): Promise<ResponseObject> {
|
|
@@ -134,12 +169,15 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
134
169
|
return res
|
|
135
170
|
}
|
|
136
171
|
public async download(options: IRequestOptions): Promise<ResponseObject> {
|
|
137
|
-
const res = await this.reqClass.download({
|
|
172
|
+
const res = await this.reqClass.download({
|
|
173
|
+
...options,
|
|
174
|
+
headers: { ...options.headers, ...this.getDefaultHeaders() },
|
|
175
|
+
})
|
|
138
176
|
return res
|
|
139
177
|
}
|
|
140
178
|
|
|
141
|
-
public getBaseEndPoint() {
|
|
142
|
-
return getBaseEndPoint(this.config.env)
|
|
179
|
+
public getBaseEndPoint(endPointKey: EndPointKey = 'CLOUD_API') {
|
|
180
|
+
return getBaseEndPoint(this.config.env, endPointKey)
|
|
143
181
|
}
|
|
144
182
|
|
|
145
183
|
public async getOauthAccessTokenV2(oauthClient: any): Promise<IGetAccessTokenResult> {
|
|
@@ -162,7 +200,9 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
162
200
|
inQuery?: KV<any>
|
|
163
201
|
search?: string
|
|
164
202
|
defaultQuery?: KV<any>
|
|
203
|
+
headers?: KV<string>
|
|
165
204
|
},
|
|
205
|
+
customReqOpts?: ICustomReqOpts,
|
|
166
206
|
): Promise<ResponseObject> {
|
|
167
207
|
const tcbTraceKey = `x-tcb-trace_${this.config.env}`
|
|
168
208
|
let contentType = 'application/x-www-form-urlencoded'
|
|
@@ -209,6 +249,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
209
249
|
headers: {
|
|
210
250
|
'content-type': contentType,
|
|
211
251
|
...this.getDefaultHeaders(),
|
|
252
|
+
...options?.headers,
|
|
212
253
|
},
|
|
213
254
|
}
|
|
214
255
|
if (options?.onUploadProgress) {
|
|
@@ -243,13 +284,25 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
243
284
|
...formatQuery,
|
|
244
285
|
})
|
|
245
286
|
|
|
246
|
-
const
|
|
287
|
+
const endPointMode = this.config.endPointMode || 'CLOUD_API'
|
|
288
|
+
|
|
289
|
+
const url = getEndPointInfo(this.config.env, endPointMode)
|
|
290
|
+
let BASE_URL = url.baseUrl
|
|
291
|
+
const PROTOCOL = url.protocol
|
|
292
|
+
|
|
293
|
+
if (endPointMode === 'GATEWAY') {
|
|
294
|
+
if (/^((database)\.)|(auth\.wsWebSign)/.test(action)) {
|
|
295
|
+
const url = getEndPointInfo(this.config.env, 'CLOUD_API')
|
|
296
|
+
BASE_URL = `${url.baseUrl.match(/\/\/([^/?#]*)/)[0]}/web`
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
247
300
|
// 生成请求 url
|
|
248
301
|
let newUrl
|
|
249
302
|
if (options.pathname) {
|
|
250
303
|
newUrl = formatUrl(
|
|
251
304
|
PROTOCOL,
|
|
252
|
-
`${getBaseEndPoint(this.config.env)?.replace(/^https?:/, '')}/${options.pathname}`,
|
|
305
|
+
`${getBaseEndPoint(this.config.env, endPointMode)?.replace(/^https?:/, '')}/${options.pathname}`,
|
|
253
306
|
formatQuery,
|
|
254
307
|
)
|
|
255
308
|
} else {
|
|
@@ -260,11 +313,14 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
260
313
|
newUrl += search
|
|
261
314
|
}
|
|
262
315
|
|
|
263
|
-
const res: ResponseObject = await this.post(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
316
|
+
const res: ResponseObject = await this.post(
|
|
317
|
+
{
|
|
318
|
+
url: newUrl,
|
|
319
|
+
data: payload,
|
|
320
|
+
...opts,
|
|
321
|
+
},
|
|
322
|
+
customReqOpts,
|
|
323
|
+
)
|
|
268
324
|
|
|
269
325
|
// 保存 trace header
|
|
270
326
|
const resTraceHeader = res.header?.['x-tcb-trace']
|
|
@@ -279,22 +335,8 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
279
335
|
return res
|
|
280
336
|
}
|
|
281
337
|
|
|
282
|
-
public async fetch(options: IFetchOptions & { token?: string }): Promise<ResponseObject> {
|
|
338
|
+
public async fetch(options: IFetchOptions & { token?: string; customReqOpts?: ICustomReqOpts },): Promise<ResponseObject> {
|
|
283
339
|
const { token, headers = {}, ...restOptions } = options
|
|
284
|
-
const getAccessToken = async () => {
|
|
285
|
-
if (token != null) {
|
|
286
|
-
return token
|
|
287
|
-
}
|
|
288
|
-
const app = this.config._fromApp
|
|
289
|
-
|
|
290
|
-
if (!app.oauthInstance) {
|
|
291
|
-
throw new Error('you can\'t request without auth')
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const { oauthInstance } = app
|
|
295
|
-
const oauthClient = oauthInstance.oauth2client
|
|
296
|
-
return (await this.getOauthAccessTokenV2(oauthClient)).accessToken
|
|
297
|
-
}
|
|
298
340
|
|
|
299
341
|
const doFetch = async () => this.reqClass.fetch({
|
|
300
342
|
headers: {
|
|
@@ -302,7 +344,7 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
302
344
|
// 'X-Request-Id': `${utils.generateRequestId()}`,
|
|
303
345
|
// 'X-Request-Timestamp': `${Date.now()}`,
|
|
304
346
|
'X-SDK-Version': `@cloudbase/js-sdk/${getSdkVersion()}`,
|
|
305
|
-
Authorization: `Bearer ${await getAccessToken()}`,
|
|
347
|
+
Authorization: `Bearer ${await this.getAccessToken(token)}`,
|
|
306
348
|
...this.getDefaultHeaders(),
|
|
307
349
|
...headers,
|
|
308
350
|
},
|
|
@@ -327,8 +369,18 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
327
369
|
}
|
|
328
370
|
}
|
|
329
371
|
|
|
330
|
-
public async send(
|
|
331
|
-
|
|
372
|
+
public async send(
|
|
373
|
+
action: string,
|
|
374
|
+
data: KV<any> = {},
|
|
375
|
+
options: KV<any> = {},
|
|
376
|
+
customReqOpts?: ICustomReqOpts,
|
|
377
|
+
): Promise<any> {
|
|
378
|
+
const response = await this.request(
|
|
379
|
+
action,
|
|
380
|
+
data,
|
|
381
|
+
{ ...options, onUploadProgress: data.onUploadProgress },
|
|
382
|
+
customReqOpts,
|
|
383
|
+
)
|
|
332
384
|
|
|
333
385
|
if (response.data.code && this.throwWhenRequestFail) {
|
|
334
386
|
throw new Error(JSON.stringify({
|
|
@@ -339,6 +391,62 @@ export class CloudbaseRequest implements ICloudbaseRequest {
|
|
|
339
391
|
|
|
340
392
|
return response.data
|
|
341
393
|
}
|
|
394
|
+
|
|
395
|
+
public async gateWay(options: IGateWayOptions, customReqOpts?: ICustomReqOpts) {
|
|
396
|
+
const { url, name, data, path = '', method, header = {} } = options
|
|
397
|
+
|
|
398
|
+
if ((!name || !path) && !url) {
|
|
399
|
+
throw new Error(JSON.stringify({
|
|
400
|
+
code: ERRORS.INVALID_PARAMS,
|
|
401
|
+
msg: '[gateWay] invalid function name or path or url',
|
|
402
|
+
}),)
|
|
403
|
+
}
|
|
404
|
+
let jsonData
|
|
405
|
+
try {
|
|
406
|
+
jsonData = data ? JSON.stringify(data) : ''
|
|
407
|
+
} catch (e) {
|
|
408
|
+
throw new Error(JSON.stringify({
|
|
409
|
+
code: ERRORS.INVALID_PARAMS,
|
|
410
|
+
msg: '[gateWay] invalid data',
|
|
411
|
+
}),)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const requestId = utils.generateRequestId()
|
|
415
|
+
const { baseUrl, protocol } = getEndPointInfo(this.config.env, 'GATEWAY')
|
|
416
|
+
let endpoint = `${protocol}${baseUrl}${url || `/${path}/${name}`}`
|
|
417
|
+
|
|
418
|
+
const isGetAndHead = ['GET', 'HEAD'].includes(method?.toUpperCase?.())
|
|
419
|
+
|
|
420
|
+
if (isGetAndHead) {
|
|
421
|
+
try {
|
|
422
|
+
let dataParse = {}
|
|
423
|
+
try {
|
|
424
|
+
dataParse = JSON.parse(data as any)
|
|
425
|
+
} catch (error) {
|
|
426
|
+
dataParse = data || {}
|
|
427
|
+
}
|
|
428
|
+
endpoint = `${endpoint}${endpoint.includes('?') ? '&' : '?'}${Object.keys(dataParse)
|
|
429
|
+
.map(key => `${key}=${dataParse[key]}`)
|
|
430
|
+
.join('&')}`
|
|
431
|
+
} catch (error) {
|
|
432
|
+
//
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const response = await this.fetch({
|
|
437
|
+
method: method || 'POST',
|
|
438
|
+
headers: {
|
|
439
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
440
|
+
'X-Request-Id': requestId,
|
|
441
|
+
...header,
|
|
442
|
+
},
|
|
443
|
+
...(isGetAndHead ? {} : { body: jsonData }),
|
|
444
|
+
url: endpoint,
|
|
445
|
+
customReqOpts,
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
return { requestId, ...response, data: await response.data }
|
|
449
|
+
}
|
|
342
450
|
}
|
|
343
451
|
|
|
344
452
|
const requestMap: KV<CloudbaseRequest> = {}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ICallApiOptions, KV } from '@cloudbase/types';
|
|
2
|
-
import { ResponseObject } from '@cloudbase/adapter-interface';
|
|
3
|
-
export declare function callApi(callApiOptions: ICallApiOptions, opts: KV<any>): Promise<ResponseObject['data']>;
|
|
4
|
-
export declare function generateCallApis(apiName: string): {
|
|
5
|
-
[apiName: string]: typeof callApi;
|
|
6
|
-
};
|
|
7
|
-
export declare function generateApis(): {
|
|
8
|
-
[apiName: string]: typeof generateCallApis;
|
|
9
|
-
};
|