UNPKG

@benshi.ai/js-sdk

Version:

Benshi SDK

182 lines (141 loc) 4.83 kB
import { Event, EventTeaser, } from '../core/typings' import { getNetworkInformation, getOperatingSystem } from '../drivers/BsSystem' import { debug } from '../logging' import BsSender from './BsSender' import { ContentBlock } from '../modules/Navigation/typings' import ImpressionsDetector from './impressions' import { ImpressionEventType } from './impressions/typings' import { toISOLocal } from '../utils' export default class BsCore { private static instance: BsCore; private deviceId: string private searchId = '' private sender: BsSender private impressionDetectorClass private impressionsDetectors: { [key: string]: ImpressionsDetector } = {} private defaultBlock private debug private currentBlock private user_id = '' private constructor( sender: BsSender, impressionDetector, debugging: boolean, defaultBlock: ContentBlock, deviceId: string ) { this.sender = sender this.impressionDetectorClass = impressionDetector this.deviceId = deviceId this.defaultBlock = defaultBlock this.debug = debug(debugging) } public static createInstance( sender: BsSender, impressionDetectorClass, debugging: boolean, defaultBlock: ContentBlock, deviceId: string) { if (!!BsCore.instance) { return BsCore.instance } BsCore.instance = new BsCore(sender, impressionDetectorClass, debugging, defaultBlock, deviceId) return BsCore.instance } public static getInstance(): BsCore { if (!BsCore.instance) { throw new Error('bslog-instance-not-created') } return BsCore.instance; } public login(userId: string) { this.user_id = userId } public logout(userId: string) { this.user_id = userId } private resolveModule(module: ContentBlock): ContentBlock { // logPageEvents are triggered automatically by the system. We do not // know whether the web application calls setCurrentBlock before or after that: const delta = 50; if (module === ContentBlock.Core) { // in this case the event could be triggered by several modules // so the SDK must decide which one must be included in the event // sent to server (i.e.: page or media events) if (this.currentBlock) { return this.currentBlock } else { return this.defaultBlock } } else { // specific module (i.e.: triggered by the ELearning module) return module } } private resolveUserId(overWrittedUserId: string, user_id: string, device_id: string): string { if (overWrittedUserId && overWrittedUserId.length !== 0) { return overWrittedUserId } return user_id || device_id } public async trackEvent( eventTeaser: EventTeaser, moduleName: ContentBlock, overWrittedUserId: string, sendNow: boolean ): Promise<void> { const event: Event = { ...eventTeaser, block: this.resolveModule(moduleName), ol: true, ts: toISOLocal(new Date()) } this.sender.add(this.resolveUserId(overWrittedUserId, this.user_id, this.deviceId), this.deviceId, event, sendNow) } public startTrackingImpressions(impressionHandler, containerClassname, itemClassname, searchId) { this.impressionsDetectors[containerClassname] = new this.impressionDetectorClass({ intersectionThreshold: 0.5 }) this.impressionsDetectors[containerClassname].on(ImpressionEventType.Impression, impressionHandler) this.impressionsDetectors[containerClassname].start(containerClassname, itemClassname, { search_id: searchId }) } public stopTrackingImpressions(containerClassname) { if (!containerClassname) { Object.values(this.impressionsDetectors).forEach(detector => detector.stop()) return } if (!this.impressionsDetectors[containerClassname]) { return } this.impressionsDetectors[containerClassname].stop() } public restartTrackingImpressions(containerClassname, searchId) { if (!containerClassname || !this.impressionsDetectors[containerClassname]) { console.error('Impossible to restart impression to unknown containerClassname') throw new Error('unknown-container') } this.impressionsDetectors[containerClassname].restart({ search_id: searchId }) } public whoami() { return this.user_id } public generateSearchId(isNewSearch: boolean) { if (isNewSearch) { this.searchId = `${this.deviceId}${this.user_id}${Date.now()}` } return this.searchId } public setCurrentBlock(block: ContentBlock) { // the reason of this delay is that the page event is triggered // 10 miliseconds after it really happens to wait for the title setTimeout(() => { this.currentBlock = block }, 15) } public setTitle(title: string) { // do nothing yet } }