import type { Storage } from '../../storage' ; import type { UserInfoState } from '../../store/userInfo' ; import type { Context , DeepPartial , IntegrationSettings , SegmentAPIIntegrations , SegmentEvent , } from '../../types' ; type Data = { isReady : boolean ; events : SegmentEvent [ ] ; context ? : DeepPartial < Context > ; settings : SegmentAPIIntegrations ; userInfo : UserInfoState ; } ; const INITIAL_VALUES = { isReady : true , events : [ ] , context : undefined , settings : { } , userInfo : { anonymousId : 'anonymousId' , userId : undefined , traits : undefined , } , } ; export class MockSegmentStore implements Storage { private data : Data ; private initialData : Data ; reset = ( ) => { this . data = JSON . parse ( JSON . stringify ( this . initialData ) ) ; } ; constructor ( initialData ? ) { this . data = { ... INITIAL_VALUES , ... initialData } ; this . initialData = { ... INITIAL_VALUES , ... initialData } ; } private createCallbackManager = < V , R = void > ( ) => { type Callback = ( value : V ) => R ; const callbacks = [ ] ; const deregister = ( callback ) => { callbacks . splice ( callbacks . indexOf ( callback ) , 1 ) ; } ; const register = ( callback ) => { callbacks . push ( callback ) ; return ( ) => { deregister ( callback ) ; } ; } ; const run = ( value ) => { callbacks . forEach ( ( callback ) => callback ( value ) ) ; } ; return { register , deregister , run } ; } ; private callbacks = { context : this . createCallbackManager < DeepPartial < Context > | undefined > ( ) , settings : this . createCallbackManager < SegmentAPIIntegrations > ( ) , events : this . createCallbackManager < SegmentEvent [ ] > ( ) , userInfo : this . createCallbackManager < UserInfoState > ( ) , } ; readonly isReady = { get : ( ) => { return this . data . isReady ; } , onChange : ( _callback ) => { return ( ) => { } ; } , } ; readonly context = { get : ( ) => ( { ... this . data . context } ) , onChange : ( callback ) => this . callbacks . context . register ( callback ) , set : ( value ) => { this . data . context = { ... value } ; this . callbacks . context . run ( value ) ; } , } ; readonly settings = { get : ( ) => this . data . settings , onChange : ( callback ) => this . callbacks . settings . register ( callback ) , set : ( value ) => { this . data . settings = value ; this . callbacks . settings . run ( value ) ; } , add : ( key , value ) => { this . data . settings [ key ] = value ; this . callbacks . settings . run ( this . data . settings ) ; } , } ; readonly events = { get : ( ) => this . data . events , onChange : ( callback ) => this . callbacks . events . register ( callback ) , add : ( event ) => { const eventsToAdd = Array . isArray ( event ) ? event : [ event ] ; this . data . events . push ( ... eventsToAdd ) ; this . callbacks . events . run ( this . data . events ) ; } , remove : ( event ) => { const eventsToRemove = Array . isArray ( event ) ? event : [ event ] ; const setToRemove = new Set ( eventsToRemove ) ; this . data . events = this . data . events . filter ( ( callback ) => ! setToRemove . has ( callback ) ) ; this . callbacks . events . run ( this . data . events ) ; } , } ; readonly userInfo = { get : ( ) => this . data . userInfo , onChange : ( callback ) => this . callbacks . userInfo . register ( callback ) , set : ( value ) => { this . data . userInfo = value ; this . callbacks . userInfo . run ( value ) ; } , } ; }