@cloudbase/app
Version:
cloudbase javascript sdk core
133 lines (126 loc) • 4.59 kB
text/typescript
import { ICloudbasePlatformInfo } from '@cloudbase/types'
import adapterForWxMp, { WxRequest, WxMpWebSocket, wxMpStorage, parseQueryString } from '@cloudbase/adapter-wx_mp'
import { IUploadRequestOptions, StorageType } from '@cloudbase/adapter-interface'
declare const wx: any
declare const App: any
declare const getApp: any
export const Platform: ICloudbasePlatformInfo = {}
export const getWxDefaultAdapter = () => {
WxRequest.prototype.upload = function (options: IUploadRequestOptions) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this
return new Promise((resolve) => {
const { url, file, data, headers } = options
const fs = wx.getFileSystemManager() // 读取文件 二进制内容
const task = wx.request({
url,
method: options.method,
header: {
'content-type': ' ', // 小程序 content-type 默认为 application/json, 这里一定要强制为 空, 否则签名错误
...headers,
},
data: fs.readFileSync(file), // 将二进制文件转为字符串直接赋值到 request payload, 不要以 form 的方式传输
timeout: this._timeout,
success(res: { statusCode: number; data: unknown }) {
const result = {
statusCode: res.statusCode,
data: res.data || {},
}
if (res.statusCode === 200 && data?.success_action_status) {
result.statusCode = parseInt(data.success_action_status, 10)
}
resolve(result)
},
fail(err: unknown) {
resolve(err)
},
complete(err: { errMsg: string }) {
if (!err?.errMsg) {
return
}
if (!self._timeout || self._restrictedMethods.indexOf('upload') === -1) {
return
}
const { errMsg } = err
if (errMsg === 'request:fail timeout') {
console.warn(self._timeoutMsg)
try {
task.abort()
} catch (e) {}
}
},
})
})
}
function isPlugin() {
return (
typeof App === 'undefined'
&& typeof getApp === 'undefined'
&& !wx.onAppHide
&& !wx.offAppHide
&& !wx.onAppShow
&& !wx.offAppShow
)
}
adapterForWxMp.genAdapter = function genAdapter(options) {
const adapter = {
root: { globalThis: {} },
reqClass: WxRequest,
wsClass: WxMpWebSocket,
captchaOptions: {
openURIWithCallback: (_url: string) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { EventBus } = options
let queryObj: Record<string, string> = {}
let url = _url
console.log('openURIWithCallback', _url)
const matched = _url.match(/^(data:.*?)(\?[^#\s]*)?$/)
if (matched) {
// eslint-disable-next-line prefer-destructuring
url = matched[1]
console.log('openURIWithCallback url', url)
const search = matched[2]
if (search) {
queryObj = parseQueryString(search)
}
}
console.log('openURIWithCallback queryObj', queryObj)
const { token, ...restQueryObj } = queryObj
if (/^data:/.test(url) && !token) {
// 如果是 data: 开头的 URL 且没有 token,则直接返回
return Promise.reject({
error: 'invalid_argument',
error_description: `invalie captcha data: ${_url}`,
})
}
if (!token) {
return Promise.reject({
error: 'unimplemented',
error_description: 'need to impl captcha data',
})
}
return new Promise((resolve) => {
console.log('wait for captcha...')
EventBus.$emit('CAPTCHA_DATA_CHANGE', { ...restQueryObj, token, url })
// 监听事件总线,等待验证码数据变化
EventBus.$once('RESOLVE_CAPTCHA_DATA', (res: { captcha_token: string; expires_in: number }) => {
resolve(res)
})
})
},
},
localStorage: wxMpStorage,
primaryStorage: StorageType.local,
getAppSign() {
const info = wx.getAccountInfoSync()
if (isPlugin()) {
// 插件环境返回插件appid
return info && info.plugin ? info.plugin.appId : ''
}
return info && info.miniProgram ? info.miniProgram.appId : ''
},
}
return adapter
}
return adapterForWxMp
}