UNPKG

@benshi.ai/js-sdk

Version:

Benshi SDK

267 lines (215 loc) 9.12 kB
import { createCheckers } from "ts-interface-checker" import { EventEmitter } from 'events'; import ECommerce from "../ECommerce"; import Navigation from '../Navigation'; import { getDeviceId } from '../../drivers/BsSystem'; import ECommercePropertiesTI from "../ECommerce/typings-ti" import BloodPropertiesTI from '../ECommerce/blood.typings-ti' import OxygenPropertiesTI from '../ECommerce/oxygen.typings-ti' import NavigationPropertiesTI from '../Navigation/typings-ti' import CommonTypesTI from '../../core/commonTypes-ti' import BsSender from "../../core/BsSender"; import BsCore from '../../core/BsCore'; import BsAppStateMonitor from "../../core/BsAppStateMonitor"; import NudgeManager from '../../core/BsNudgeManager'; import CurrencyRepository, { ICurrencyRepository } from "../../core/repositories/currency/CurrencyRepository" import CatalogRepository, { ICatalogRepository } from "../../core/repositories/catalog/CatalogRepository"; import { CTA, INudgesRepository } from "../../core/repositories/nudges/typings"; import NudgeRepositoryFactory from "../../core/repositories/nudges/NudgeFactory"; import { BsLogOptions, LogIngestorOptions } from '../../core/typings'; import ImpressionsDetector from "../../core/impressions" import { ContentBlock, IdentifyAction, NudgeAction, NudgeResponseType, UserProperties } from '../Navigation/typings'; import { offsetToISO8601 } from "../../utils"; import NotificationFactory from "../../drivers/notifications/NotificationFactory"; import { NotificationDispatcher } from "../../drivers/notifications/typings"; import BsLocalStorage from "../../drivers/storage/BsLocalStorage"; import BsNetworkQueue from "../../core/BsNetworkQueue"; import Payments from "../Payments"; import BsNetworkNodeFetch from "../../drivers/network/BsNetworkNodeFetch"; import NetworkFactory from "../../drivers/network/BsNetworkFactory"; import { NudgeManagerAction } from "../../core/BsNudgeManager.typings"; import { BsLogEvents } from "../../core/commonTypes"; export default class BsLog extends EventEmitter { private deviceId private sender private bsCore private bsNetwork private storageDriver private networkQueue private nudgeManager private notificationsEngine: NotificationDispatcher private impressionManager private nudgesRepository: INudgesRepository private currencyRepository: ICurrencyRepository private catalogRepository: ICatalogRepository private DEFAULT_BASE_URL = 'https://api.causalfoundry.ai/v1' private DEFAULT_INGEST_PATH = '/ingest/log' private DEFAULT_CURRENCY_PATH = '/ingest/currency-exchange' private DEFAULT_NUDGE_FETCH_PATH = '/nudge/sdk' private DEFAULT_CATALOG_PATH = '/ingest/catalog' private DEFAULT_FLUSH_INTERVAL = 10000 private DEFAULT_FLUSH_MAX_RETRIES = 10 private DEFAULT_CACHE_EVENTS_KEY = 'bslog' private options: BsLogOptions = { baseUrl: this.DEFAULT_BASE_URL, currencyPath: this.DEFAULT_CURRENCY_PATH, nudgeFetchPath: this.DEFAULT_NUDGE_FETCH_PATH, catalogPath: this.DEFAULT_CATALOG_PATH, activateNudgeMechanism: true, defaultBlock: ContentBlock.Core, debug: true } public constructor(key: string, options?: Partial<BsLogOptions>) { super() this.deviceId = getDeviceId() if (options) { this.options = Object.assign(this.options, options) } this.bsNetwork = NetworkFactory.getNetworkDriver(key) this.networkQueue = new BsNetworkQueue(this.bsNetwork) this.storageDriver = new BsLocalStorage() const logIngestorDefaultOptions: LogIngestorOptions = { flushInterval: this.DEFAULT_FLUSH_INTERVAL, flushMaxRetries: this.DEFAULT_FLUSH_MAX_RETRIES, ingestPath: this.DEFAULT_INGEST_PATH, cacheEventsInLocalstorage: true, cacheEventsKey: this.DEFAULT_CACHE_EVENTS_KEY, } const logIngestorOptions = {...logIngestorDefaultOptions, baseUrl: this.options.baseUrl || this.DEFAULT_BASE_URL} this.sender = new BsSender(this.bsNetwork, logIngestorOptions) this.bsCore = BsCore.createInstance( this.sender, ImpressionsDetector, this.options.debug, this.options.defaultBlock, this.deviceId) this.nudgesRepository = NudgeRepositoryFactory.getNudgeRepository( `${this.options.baseUrl}${this.options.nudgeFetchPath}`, this.bsNetwork, this.storageDriver ) this.currencyRepository = new CurrencyRepository( `${this.options.baseUrl}${this.options.currencyPath}`, this.bsNetwork ) this.catalogRepository = new CatalogRepository( `${this.options.baseUrl}${this.options.catalogPath}`, this.networkQueue, {} ) ECommerce.init(this.currencyRepository, this.catalogRepository) Navigation.init(this.catalogRepository) Payments.init(this.currencyRepository) BsAppStateMonitor(this) } /** * @ignore */ private runNudgeManager(userId: string) { if (!!this.nudgeManager) { return } if (!this.options.activateNudgeMechanism) { return } this.notificationsEngine = NotificationFactory.getNotificationEngine() this.nudgeManager = new NudgeManager( userId, this.notificationsEngine, this.nudgesRepository ) this.nudgeManager.on(NudgeManagerAction.Action, (callToActionData: CTA) => { this.emit(BsLogEvents.NudgeAction, callToActionData.type, callToActionData.cta_resource) }) this.nudgeManager.on(NudgeManagerAction.Open, (id, nudgeInfo) => { Navigation.logPushNotificationEvent({ nudge_id: id, type: NudgeResponseType.InApp, response: { action: NudgeAction.Open }, resolved_action: nudgeInfo }) }) this.nudgeManager.on(NudgeManagerAction.Discard, (id, nudgeInfo) => { Navigation.logPushNotificationEvent({ nudge_id: id, type: NudgeResponseType.InApp, response: { action: NudgeAction.Discard }, resolved_action: nudgeInfo }) }) this.nudgeManager.on(NudgeManagerAction.Block, (id, nudgeInfo) => { Navigation.logPushNotificationEvent({ nudge_id: id, type: NudgeResponseType.InApp, response: { action: NudgeAction.Block }, resolved_action: nudgeInfo }) }) } public flush() { this.sender.flush() } /** * Call this function whenever the application has information about a session event * (Register, Login, Logout) * * @param {IdentifyAction} action * @param {string} userId * @param {UserProperties} userProps */ public identify(action: IdentifyAction, userId: string, userProps: UserProperties) { const { UserInfo: IdentifyPropertiesChecker } = createCheckers( NavigationPropertiesTI, BloodPropertiesTI, ECommercePropertiesTI, OxygenPropertiesTI, CommonTypesTI) const userInfo = { action, user_props: userProps || {} } IdentifyPropertiesChecker.check(userInfo) if ((action === IdentifyAction.Login || action === IdentifyAction.Register) && (userProps.country)) { this.bsCore.login(userId) this.runNudgeManager(userId) const timezoneOffset = (new Date()).getTimezoneOffset() userProps.timezone = offsetToISO8601(timezoneOffset) this.catalogRepository.injectUser(userId, userProps) }else{ this.bsCore.login(userId) this.runNudgeManager(userId) } if (action === IdentifyAction.Logout) { this.bsCore.logout(userId) } Navigation.logIdentifyEvent({action}) } /** * When this SDK is embedded into a web application, which has been already logged * in another section, there is no need to call `identify` again, because the session * is already started. Use this function to let the SDK what is the userId so it is able * to include in the subsequent events. * * An example of an scenario where this is useful is: a native application where * some section is implemented in HTML/JS with a WebView. In this case, the session * has already started in the native part, so do not call `identify` within the JS section, * just call `setUserId` * * @param userId the string that represents unambiguously this user */ public setUserId(userId: string) { this.bsCore.login(userId) } }