UNPKG

@segment/analytics-react-native

Version:

The hassle-free way to add Segment analytics to your React-Native app.

213 lines (176 loc) 4.98 kB
import type { SegmentClient } from './analytics'; import { Timeline } from './timeline'; import { AliasEventType, EventType, GroupEventType, IdentifyEventType, PluginType, ScreenEventType, SegmentAPISettings, SegmentEvent, TrackEventType, UpdateType, } from './types'; export class Plugin { // default to utility to avoid automatic processing type: PluginType = PluginType.utility; analytics?: SegmentClient = undefined; configure(analytics: SegmentClient) { this.analytics = analytics; } update(_settings: SegmentAPISettings, _type: UpdateType) { // do nothing by default, user can override. } execute( event: SegmentEvent ): Promise<SegmentEvent | undefined> | SegmentEvent | undefined { // do nothing. return event; } shutdown() { // do nothing by default, user can override. } } export class EventPlugin extends Plugin { execute( event: SegmentEvent ): Promise<SegmentEvent | undefined> | SegmentEvent | undefined { if (event === undefined) { return event; } let result: Promise<SegmentEvent | undefined> | SegmentEvent | undefined = event; switch (result.type) { case EventType.IdentifyEvent: result = this.identify(result); break; case EventType.TrackEvent: result = this.track(result); break; case EventType.ScreenEvent: result = this.screen(result); break; case EventType.AliasEvent: result = this.alias(result); break; case EventType.GroupEvent: result = this.group(result); break; } return result; } // Default implementations that forward the event. This gives plugin // implementors the chance to interject on an event. identify( event: IdentifyEventType ): Promise<IdentifyEventType | undefined> | IdentifyEventType | undefined { return event; } track( event: TrackEventType ): Promise<TrackEventType | undefined> | TrackEventType | undefined { return event; } screen( event: ScreenEventType ): Promise<ScreenEventType | undefined> | ScreenEventType | undefined { return event; } alias( event: AliasEventType ): Promise<AliasEventType | undefined> | AliasEventType | undefined { return event; } group( event: GroupEventType ): Promise<GroupEventType | undefined> | GroupEventType | undefined { return event; } flush(): void | Promise<void> { return; } reset(): void | Promise<void> { return; } } export class DestinationPlugin extends EventPlugin { // default to destination type = PluginType.destination; key = ''; timeline = new Timeline(); private hasSettings() { return this.analytics?.settings.get()?.[this.key] !== undefined; } private isEnabled(event: SegmentEvent): boolean { let customerDisabled = false; if (event.integrations?.[this.key] === false) { customerDisabled = true; } return this.hasSettings() && !customerDisabled; } /** Adds a new plugin to the currently loaded set. - Parameter plugin: The plugin to be added. - Returns: Returns the name of the supplied plugin. */ add(plugin: Plugin) { const analytics = this.analytics; if (analytics) { plugin.configure(analytics); } this.timeline.add(plugin); return plugin; } /** Applies the supplied closure to the currently loaded set of plugins. - Parameter closure: A closure that takes an plugin to be operated on as a parameter. */ apply(closure: (plugin: Plugin) => void) { this.timeline.apply(closure); } configure(analytics: SegmentClient) { this.analytics = analytics; this.apply((plugin) => { plugin.configure(analytics); }); } /** Removes and unloads plugins with a matching name from the system. - Parameter pluginName: An plugin name. */ remove(plugin: Plugin) { this.timeline.remove(plugin); } async execute(event: SegmentEvent): Promise<SegmentEvent | undefined> { if (!this.isEnabled(event)) { return; } // Apply before and enrichment plugins const beforeResult = await this.timeline.applyPlugins({ type: PluginType.before, event, }); if (beforeResult === undefined) { return; } const enrichmentResult = await this.timeline.applyPlugins({ type: PluginType.enrichment, event: beforeResult, }); if (enrichmentResult === undefined) { return; } // Now send the event to the destination by executing the normal flow of an EventPlugin await super.execute(enrichmentResult); // apply .after plugins const afterResult = await this.timeline.applyPlugins({ type: PluginType.after, event: enrichmentResult, }); return afterResult; } } export class UtilityPlugin extends EventPlugin {} // For internal platform-specific bits export class PlatformPlugin extends Plugin {}