UNPKG

@cloudbase/app

Version:
312 lines (273 loc) 9.33 kB
import { adapters, constants, utils, helpers } from '@cloudbase/utilities' import { SDKAdapterInterface, CloudbaseAdapter, IRequestConfig } from '@cloudbase/adapter-interface' import { ICloudbaseConfig, ICloudbaseUpgradedConfig, ICloudbase, ICloudbaseExtension, KV, ICloudbasePlatformInfo, EndPointKey, ICloudbaseApis, } from '@cloudbase/types' import { ICloudbaseAuth } from '@cloudbase/types/auth' import adapterForWxMp from '@cloudbase/adapter-wx_mp' import { registerComponent, registerHook } from './libs/component' import { Platform } from './libs/adapter' import { ICloudbaseComponent, ICloudbaseHook } from '@cloudbase/types/component' import { ICloudbaseCache } from '@cloudbase/types/cache' import { initCache, getCacheByEnvId, getLocalCache } from './libs/cache' import { ICloudbaseRequest } from '@cloudbase/types/request' import { initRequest, getRequestByEnvId } from './libs/request' import { getSdkName, setSdkVersion, setRegionLevelEndpoint, setSdkName, setGatewayEndPointWithEnv, type ISetEndPointWithKey, setEndPointInfo, getEndPointInfo, getSdkVersion, DEFAULT_PROTOCOL, } from './constants/common' import { i18nProxy, LANGS } from './libs/lang' import { generateApis } from './libs/callApis' export { getBaseEndPoint } from './constants/common' export { LANGS } from './libs/lang' const { useAdapters, useDefaultAdapter } = adapters const { ERRORS, COMMUNITY_SITE_URL } = constants const { printWarn } = utils const { catchErrorsDecorator } = helpers /** * @constant 默认配置 */ const DEFAULT_INIT_CONFIG: Partial<ICloudbaseConfig> = { timeout: 15000, persistence: 'local', // 持久化存储类型 } // timeout上限10分钟 const MAX_TIMEOUT = 1000 * 60 * 10 // timeout下限100ms const MIN_TIMEOUT = 100 const extensionMap: KV<ICloudbaseExtension> = {} class Cloudbase implements ICloudbase { public authInstance: ICloudbaseAuth public oauthInstance: any public requestClient: any public oauthClient: any public version: string private cloudbaseConfig: ICloudbaseConfig constructor(config?: ICloudbaseConfig) { this.cloudbaseConfig = config ? config : this.cloudbaseConfig this.authInstance = null this.oauthInstance = null this.version = getSdkVersion() } get config() { return this.cloudbaseConfig } get platform(): ICloudbasePlatformInfo { return Platform } get cache(): ICloudbaseCache { return getCacheByEnvId(this.cloudbaseConfig.env) } get localCache(): ICloudbaseCache { return getLocalCache(this.cloudbaseConfig.env) } get request(): ICloudbaseRequest { return getRequestByEnvId(this.cloudbaseConfig.env) } get apis(): ICloudbaseApis { return generateApis.call(this) } @catchErrorsDecorator({ mode: 'sync', title: 'Cloudbase 初始化失败', messages: [ '请确认以下各项:', ' 1 - 调用 cloudbase.init() 的语法或参数是否正确', ' 2 - 如果是非浏览器环境,是否配置了安全应用来源(https://docs.cloudbase.net/api-reference/webv3/adapter#%E7%AC%AC-2-%E6%AD%A5%E9%85%8D%E7%BD%AE%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E6%9D%A5%E6%BA%90)', `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`, ], }) public init(config: ICloudbaseConfig & { lang?: LANGS }): Cloudbase { if (!config.env) { throw new Error(JSON.stringify({ code: ERRORS.INVALID_PARAMS, msg: 'env must not be specified', }),) } // 初始化时若未兼容平台,则使用默认adapter if (!Platform.adapter) { this.useDefaultAdapter() } const reqConfig: IRequestConfig = { timeout: config.timeout || 5000, timeoutMsg: `[${getSdkName()}][REQUEST TIMEOUT] request had been abort since didn't finished within${ config.timeout / 1000 }s`, } this.requestClient = new Platform.adapter.reqClass(reqConfig) this.cloudbaseConfig = { ...DEFAULT_INIT_CONFIG, ...config, i18n: i18nProxy(Platform, config), } delete (this.cloudbaseConfig as any).lang // 修正timeout取值 this.cloudbaseConfig.timeout = this.formatTimeout(this.cloudbaseConfig.timeout) // 初始化cache和request const { env, persistence, debug, timeout, oauthClient, i18n } = this.cloudbaseConfig initCache({ env, persistence, debug, platformInfo: this.platform }) setRegionLevelEndpoint(env, config.region || '') setGatewayEndPointWithEnv(env, DEFAULT_PROTOCOL, config.region || '') const app = new Cloudbase(this.cloudbaseConfig) initRequest({ env, region: config.region || '', timeout, oauthClient, _fromApp: app, i18n, endPointMode: config.endPointMode, }) app.requestClient = this.requestClient ;(this as any)?.fire?.('cloudbase_init', app) this.try2InitAuth(config, app) return app } public updateConfig(config: ICloudbaseUpgradedConfig) { const { persistence, debug } = config this.cloudbaseConfig.persistence = persistence this.cloudbaseConfig.debug = debug // persistence改动影响cache initCache({ env: this.cloudbaseConfig.env, persistence, debug, platformInfo: this.platform }) } public updateLang(lang: LANGS) { if (!lang || lang === this.cloudbaseConfig.i18n?.lang) return this.cloudbaseConfig.i18n.lang = lang } public registerExtension(ext: ICloudbaseExtension) { extensionMap[ext.name] = ext } @catchErrorsDecorator({ title: '调用扩展能力失败', messages: [ '请确认以下各项:', ' 1 - 调用 invokeExtension() 的语法或参数是否正确', ' 2 - 被调用的扩展能力是否已经安装并通过 registerExtension() 注册', `如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`, ], }) public async invokeExtension(name: string, opts: any) { const ext = extensionMap[name] if (!ext) { throw new Error(JSON.stringify({ code: ERRORS.INVALID_PARAMS, msg: `extension:${name} must be registered before invoke`, }),) } return await ext.invoke(opts, this) } public useAdapters(adapters: CloudbaseAdapter | CloudbaseAdapter[], options?: any) { const { adapter, runtime } = useAdapters(adapters, options) || {} adapter && (Platform.adapter = adapter as SDKAdapterInterface) runtime && (Platform.runtime = runtime as string) } public registerHook(hook: ICloudbaseHook) { registerHook(Cloudbase, hook) } public registerComponent(component: ICloudbaseComponent) { registerComponent(Cloudbase, component) } public registerVersion(version: string) { setSdkVersion(version) this.version = version } public registerSdkName(name: string) { setSdkName(name) } /** 设置 tcb api 的 endpoint */ public registerEndPoint(url: string, protocol?: 'http' | 'https') { setEndPointInfo({ baseUrl: url, protocol, env: this.config.env, endPointKey: 'CLOUD_API' }) } /** 设置网关/tcb api的 endPoint,通过 key 指定 */ public registerEndPointWithKey(props: ISetEndPointWithKey) { setEndPointInfo({ env: this.config.env, endPointKey: props.key, baseUrl: props.url, protocol: props.protocol, }) } /** 拿网关/tcb api的 endPoint,通过 key 指定 */ public getEndPointWithKey(key: EndPointKey) { const info = getEndPointInfo(this.config.env, key) return { BASE_URL: info.baseUrl, PROTOCOL: info.protocol, } } // 解析URL参数 public parseCaptcha(url) { let queryObj: any = {} const matched = url.match(/^(data:.*?)(\?[^#\s]*)?$/) if (matched) { url = matched[1] const search = matched[2] if (search) { queryObj = utils.parseQueryString(search) } } const { token, ...restQueryObj } = queryObj if (/^data:/.test(url) && !token) { return { error: 'invalid_argument', error_description: `invalid captcha data: ${url}`, } } if (!token) { return { error: 'unimplemented', error_description: 'need to impl captcha data', } } // 解析url得到的参数 return { state: restQueryObj.state, token, // 验证码token captchaData: url, // 验证码base64图片 } } private useDefaultAdapter() { const { adapter, runtime } = useDefaultAdapter() Platform.adapter = adapter as SDKAdapterInterface Platform.runtime = runtime as string } private formatTimeout(timeout: number) { switch (true) { case timeout > MAX_TIMEOUT: printWarn(ERRORS.INVALID_PARAMS, 'timeout is greater than maximum value[10min]') return MAX_TIMEOUT case timeout < MIN_TIMEOUT: printWarn(ERRORS.INVALID_PARAMS, 'timeout is less than maximum value[100ms]') return MIN_TIMEOUT default: return timeout } } private try2InitAuth(config: ICloudbaseConfig, app) { try { if (config.accessKey) { app.auth() } } catch (error) { console.log('try2InitAuth error:', error) } } } export const cloudbase: ICloudbase = new Cloudbase() cloudbase.useAdapters(adapterForWxMp) export default cloudbase