UNPKG

@causalfoundry/js-sdk

Version:

Causal Foundry WEB SDK (JS/TS)

393 lines (314 loc) 12.4 kB
import {createCheckers} from "ts-interface-checker" import {EventEmitter} from 'events'; import ECommerce from "../ECommerce"; import Loyalty from "../Loyalty"; import Navigation from '../Navigation'; import PatientMgmt from "../PatientMgmt"; import { clearLocalStorageUserId, getDeviceId, getLocalStorageUserId, setLocalStorageUserId, } from '../../drivers/CfSystem'; import ECommercePropertiesTI from "../ECommerce/typings-ti" import BloodPropertiesTI from '../ECommerce/blood.typings-ti' import OxygenPropertiesTI from '../ECommerce/oxygen.typings-ti' import NavigationPropertiesTI, {IdentifyProperties} from '../Navigation/typings-ti' import CommonTypesTI from '../../core/commonTypes-ti' import CfSender from "../../core/CfSender"; import CfCore from '../../core/CfCore'; import CfAppStateMonitor from "../../core/CfAppStateMonitor"; import NudgeManager from '../../core/CfNudgeManager'; import CatalogRepository, {ICatalogRepository} from "../../core/repositories/catalog/CatalogRepository"; import {CTA, INudgesRepository} from "../../core/repositories/nudges/typings"; import NudgeRepositoryFactory from "../../core/repositories/nudges/NudgeFactory"; import {CfLogOptions, LogIngestorOptions} from '../../core/typings'; import ImpressionsDetector from "../../core/impressions" import { ContentBlock, IdentityAction, NavigationTypes, NudgeAction, SiteCatalog, UserCatalog } from '../Navigation/typings'; import NotificationFactory from "../../drivers/notifications/NotificationFactory"; import {NotificationDispatcher} from "../../drivers/notifications/typings"; import CfLocalStorage from "../../drivers/storage/CfLocalStorage"; import CfNetworkQueue from "../../core/CfNetworkQueue"; import NetworkFactory from "../../drivers/network/CfNetworkFactory"; import {NudgeManagerAction} from "../../core/CfNudgeManager.typings"; import {CfLogEvents, NudgeScreenType} from "../../core/commonTypes"; import CfExceptionHandler from "../../core/CfExceptionHandler"; import isBrowser from "is-in-browser"; import {convertParameterNodes} from "typedoc/dist/lib/converter/factories/signature"; import CallCenter from "../CallCenter"; import EmergencyMgmt from "../EmergencyMgmt"; export default class CfLog extends EventEmitter { private deviceId private sender private cfCore private cfNetwork private storageDriver private networkQueue private nudgeManager private notificationsEngine: NotificationDispatcher private nudgesRepository: INudgesRepository private catalogRepository: ICatalogRepository private DEFAULT_BASE_URL = 'https://api.causalfoundry.ai/v1' private DEFAULT_INGEST_PATH = '/ingest/log' private DEFAULT_NUDGE_FETCH_PATH = '/nudge/sdk' private DEFAULT_CATALOG_PATH = '/ingest/catalog' private DEFAULT_CDN_URL = 'https://cdn.causalfoundry.ai/' private DEFAULT_FLUSH_INTERVAL = 10000 private DEFAULT_FLUSH_MAX_RETRIES = 10 private DEFAULT_CACHE_EVENTS_KEY = 'cfLog' private options: CfLogOptions = { cdnUrl: this.DEFAULT_CDN_URL, baseUrl: this.DEFAULT_BASE_URL, allowAnonymousUsers: false, nudgeFetchPath: this.DEFAULT_NUDGE_FETCH_PATH, catalogPath: this.DEFAULT_CATALOG_PATH, activateNudgeMechanism: true, selfManagedNudges: false, defaultBlock: ContentBlock.Core, debug: true, isUsingAsInternalWrapper : false, pauseSDK: false } public constructor(key: string, options?: Partial<CfLogOptions>) { super() this.deviceId = getDeviceId() if (options) { this.options = Object.assign(this.options, options) } this.cfNetwork = NetworkFactory.getNetworkDriver(key) this.networkQueue = new CfNetworkQueue(this.cfNetwork) this.storageDriver = new CfLocalStorage() 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 updatedIngestionOptions = {...logIngestorDefaultOptions, ...options} const logIngestorOptions = {...updatedIngestionOptions, baseUrl: this.options.baseUrl || this.DEFAULT_BASE_URL} this.sender = new CfSender(this.cfNetwork, logIngestorOptions) this.cfCore = CfCore.createInstance( this.sender, ImpressionsDetector, this.options.debug, this.options.defaultBlock, this.deviceId, this.options.isUsingAsInternalWrapper) this.nudgesRepository = NudgeRepositoryFactory.getNudgeRepository( `${this.options.baseUrl}${this.options.nudgeFetchPath}`, this.cfNetwork, this.storageDriver ) this.catalogRepository = new CatalogRepository( `${this.options.baseUrl}${this.options.catalogPath}`, this.networkQueue, {}, this.options.pauseSDK ) ECommerce.init(this.catalogRepository) Loyalty.init(this.catalogRepository) Navigation.init(this.catalogRepository) PatientMgmt.init(this.catalogRepository) EmergencyMgmt.init(this.catalogRepository) CfAppStateMonitor(this) if(this.options.allowAnonymousUsers && isBrowser && this.deviceId && (getLocalStorageUserId() === '')){ this.fetchNudgesForAnonUsers(this.deviceId) } } /** * @ignore */ private runNudgeManager(userId: string) { if(this.options.pauseSDK){ return; } if (this.nudgeManager && !this.options.allowAnonymousUsers) { return }else { this.nudgeManager = null } if (!this.options.activateNudgeMechanism) { return } if (this.options.selfManagedNudges) { return } this.setupNudgeManager(userId, NudgeScreenType.None, false) } private fetchNudgesForScreen(userId: string, nudgeScreenType : NudgeScreenType) { if(this.options.pauseSDK){ return } if (this.nudgeManager) { this.nudgeManager = null } if (!this.options.activateNudgeMechanism) { // console.error("[cfLog-nudge]", "enable activateNudgeMechanism in CfLogOptions") return } if (!this.options.selfManagedNudges) { // console.error("[cfLog-nudge]", "enable selfManagedNudges in CfLogOptions") return } this.setupNudgeManager(userId, nudgeScreenType, true) } private fetchNudgesForAnonUsers(deviceId: string) { if(this.options.pauseSDK){ return } if (this.nudgeManager) { this.nudgeManager = null } this.setupNudgeManager(deviceId, NudgeScreenType.None, true) } private setupNudgeManager(userId: string, nudgeScreenType: NudgeScreenType, isOneTimeOnly: boolean){ this.notificationsEngine = NotificationFactory.getNotificationEngine() this.nudgeManager = new NudgeManager( userId, this.notificationsEngine, this.nudgesRepository, nudgeScreenType, isOneTimeOnly ) this.nudgeManager.on(NudgeManagerAction.Action, (callToActionData: CTA) => { this.emit(CfLogEvents.NudgeAction, callToActionData.type, callToActionData.cta_resource) }) this.nudgeManager.on(NudgeManagerAction.Open, (id, nudgeTime) => { Navigation.logPushNotificationEvent({ ref: id, response: NudgeAction.Open, time: nudgeTime, }) }) this.nudgeManager.on(NudgeManagerAction.Discard, (id, nudgeTime) => { Navigation.logPushNotificationEvent({ ref: id, response: NudgeAction.Discard, time: nudgeTime }) }) this.nudgeManager.on(NudgeManagerAction.Block, (id, nudgeTime) => { Navigation.logPushNotificationEvent({ ref: id, response: NudgeAction.Block, time: nudgeTime }) }) this.nudgeManager.on(NudgeManagerAction.Shown, (id, nudgeTime) => { Navigation.logPushNotificationEvent({ ref: id, response: NudgeAction.Shown, time: nudgeTime }) }) } public flush() { if(this.options.pauseSDK){ return } this.sender.flush() } /** * Call this function whenever the application has information about a session event * (Register, Login, Logout) * * @param {IdentityAction} action * @param {string} userId * @param {UserCatalog} userProps * @param {string} referralCode */ public identify(action: IdentityAction, userId: string, userProps? : UserCatalog, referralCode?: string) { if(this.options.pauseSDK){ return } if(userId == ''){ new CfExceptionHandler().throwAndLogError(NavigationTypes.Identify, 'invalid-user-id') return } const { IdentifyProperties: IdentifyPropertiesChecker } = createCheckers( NavigationPropertiesTI, BloodPropertiesTI, ECommercePropertiesTI, OxygenPropertiesTI, CommonTypesTI) const userInfo = { action: action, referral_code: referralCode } IdentifyPropertiesChecker.check(userInfo) this.cfCore.login(userId); if (action === IdentityAction.Logout) { clearLocalStorageUserId(); } else { this.runNudgeManager(userId); setLocalStorageUserId(userId); if (userProps) { this.catalogRepository.injectUser(userProps); } } Navigation.logIdentifyEvent({ action: action, referral_code: referralCode }) } public userBlockStatus(isBlocked: boolean, reason: string, remarks?: string,) { if(this.options.pauseSDK){ return } if(isBlocked == undefined){ new CfExceptionHandler().throwAndLogError(NavigationTypes.Identify, 'invalid-block-status') }else if(reason == ''){ new CfExceptionHandler().throwAndLogError(NavigationTypes.Identify, 'invalid-reason') } const userIdentifyObject = { action: isBlocked? IdentityAction.Blocked : IdentityAction.UnBlocked, referral_code: "", blocked: { reason: reason, remarks: remarks, } } Navigation.logIdentifyEvent(userIdentifyObject) } public updateUserCatalog(userCatalog: UserCatalog) { if(this.options.pauseSDK){ return } this.catalogRepository.injectUser(userCatalog) } public updateSiteCatalog(siteCatalog: SiteCatalog) { if(this.options.pauseSDK){ return } console.log("siteHeelo") this.catalogRepository.injectSite(siteCatalog) } /** * 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 a 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) { if(this.options.pauseSDK){ return } if(!userId){ new CfExceptionHandler().throwAndLogError(NavigationTypes.Identify, 'invalid-user-id') return } this.cfCore.login(userId) } }