@cloudbase/app
Version:
cloudbase javascript sdk core
117 lines (107 loc) • 3.45 kB
text/typescript
import { KV } from '@cloudbase/types'
import { ICloudbaseComponent, ICloudbaseHook } from '@cloudbase/types/component'
import { constants } from '@cloudbase/utilities'
const { ERRORS } = constants
const components: KV<ICloudbaseComponent> = {}
export function registerComponent(app: any, component: ICloudbaseComponent) {
const { name, namespace, entity, injectEvents, IIFE = false } = component
// 不允许重复注册或命名空间重名
if (components[name] || (namespace && app[namespace])) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_OPERATION,
msg: `Duplicate component ${name}`,
}))
}
// IIFE类型的组件以app为scope执行entity函数,不挂载到app.prototype上
if (IIFE) {
if (!entity || typeof entity !== 'function') {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: 'IIFE component\'s entity must be a function',
}))
}
entity.call(app)
}
components[name] = component
if (namespace) {
(app as any).prototype[namespace] = entity
} else {
deepExtend((app as any).prototype, entity)
}
if (injectEvents) {
const { bus, events } = injectEvents
if (!bus || !events || events.length === 0) {
return
}
const originCallback = (app as any).prototype.fire || function () {}
if (!(app as any).prototype.events) {
(app as any).prototype.events = {}
}
const originEvents: KV<any> = (app as any).prototype.events || {}
if (originEvents[name]) {
(app as any).prototype.events[name].events = [...(app as any).prototype.events[name].events, ...events]
} else {
(app as any).prototype.events[name] = { bus, events }
}
(app as any).prototype.fire = function (eventName: string, data?: any) {
originCallback(eventName, data)
const eventNames = Object.keys(this.events)
for (const name of eventNames) {
const { bus, events: eventList } = this.events[name]
if (eventList.includes(eventName)) {
bus.fire(eventName, data)
break
}
}
}
}
}
function deepExtend(target: any, source: any): KV<any> {
if (!(source instanceof Object)) {
return source
}
switch (source.constructor) {
case Date: {
const dateValue = source as Date
return new Date(dateValue.getTime())
}
case Object:
if (target === undefined) {
target = {}
}
break
case Array:
target = []
break
default:
return source
}
const sourceKeys = Object.keys(source)
for (const key of sourceKeys) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
continue
}
target[key] = deepExtend(target[key], source[key])
}
return target
}
export function registerHook(app: any, hook: ICloudbaseHook) {
const { entity, target } = hook
if (Object.prototype.hasOwnProperty.call(app, target)) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_OPERATION,
msg: `target:${target} is not exist`,
}))
}
const originMethod = app.prototype[target]
if (typeof originMethod !== 'function') {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_OPERATION,
msg: `target:${target} is not a function which is the only type supports hook`,
}))
}
app.prototype[target] = function (...args: any) {
entity.call(this, ...args)
return originMethod.call(this, ...args)
}
}