import { BaseGather, GoogleGather, GoogleGatherOptions, MixpanelGather, MixpanelGatherOptions } from './gathers' import { EventMeta, PageMeta, ScreenMeta, ConfigMeta, UserMeta, ParamsMeta } from './gathers' import { warn, isObject, mergeDeep } from './utils' export * from './gathers' export * from './utils' declare const process: { env: { NODE_ENV: string } client: boolean } export interface MixgatherOptions { debug?: boolean appName?: string // Gathers google?: GoogleGatherOptions mixpanel?: MixpanelGatherOptions } export interface MixgaterState { currentPageTitle: string } export class Mixgather { public isInited = false public options: MixgatherOptions = {} public state: MixgaterState = { currentPageTitle: '' } private gathers: BaseGather[] = [] constructor(options?: MixgatherOptions) { const defaultOptions = { debug: process.env.NODE_ENV !== 'production', appName: process.client && document.title } mergeDeep(this.options, defaultOptions, options) } public enableDebug() { this.options.debug = true } private debug(text: string, ...params: any) { if (!this.options.debug) { return } console.log(`[mixgather] ${text}`, ...params) } public async init(options: MixgatherOptions) { if (this.isInited) { return warn( 'mixgather: had been inited before, please register gather by manual' ) } mergeDeep(this.options, options) if (!this.options) { return warn('mixgather: options was undefined') } const { google, mixpanel } = options if (google && google.id) { this.registerGather(GoogleGather, google) } if (mixpanel && mixpanel.token) { this.registerGather(MixpanelGather, mixpanel) } try { await Promise.all(this.gathers.map((gather) => gather.init())) } catch (error) { console.error(error) } this.debug('Inited') this.isInited = true } public setProperty(configMeta: ConfigMeta): ConfigMeta { this.gathers.map((gather) => gather.config(configMeta)) return configMeta } public setUser(userMeta: UserMeta): UserMeta { this.gathers.map((gather) => gather.setUser && gather.setUser(userMeta)) return userMeta } public setCurrentPage(title: string) { this.state.currentPageTitle = title } public page( path: string = location.pathname, params?: ParamsMeta | string ): PageMeta { let pageMeta: PageMeta = { path } if (typeof path !== 'string') { pageMeta = { ...(path as PageMeta) } } if (isObject(params)) { Object.assign(pageMeta, params) } if (!pageMeta.title) { if (typeof params === 'string') { pageMeta.title = params } else { pageMeta.title = document.title } } this.gathers.map((gather) => gather.page(pageMeta)) this.setCurrentPage(pageMeta.title) this.screen(this.state.currentPageTitle) this.debug('Sent Page:', pageMeta.path, pageMeta) return pageMeta } public event(action: string, params?: ParamsMeta): EventMeta { let eventMeta: EventMeta = { action } if (typeof action !== 'string') { eventMeta = { ...(action as EventMeta) } } Object.assign(eventMeta, params) if (!eventMeta.page) { eventMeta.page = this.state.currentPageTitle } this.gathers.map((gather) => gather.event(eventMeta)) this.debug('Sent Event:', eventMeta.action, eventMeta) return eventMeta } public screen(screenName: string, appName?: string): ScreenMeta { let screenMeta: ScreenMeta = { name: screenName } if (typeof screenName !== 'string') { screenMeta = { ...(screenName as ScreenMeta), app: appName || this.options.appName } } this.gathers.map((gather) => gather.screen(screenMeta)) return screenMeta } public registerGather( Gather: new (...args: any[]) => T, options: any ) { this.gathers.push(new Gather(options)) } public getGather(name: new (...args: any[]) => T): T { return this.gathers.find((t) => t instanceof name) as T } } export default new Mixgather()