@segment/analytics-react-native
Version:
The hassle-free way to add Segment analytics to your React-Native app.
260 lines (247 loc) • 7.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Plugin = exports.PlatformPlugin = exports.EventPlugin = exports.DestinationPlugin = void 0;
Object.defineProperty(exports, "PluginType", {
enumerable: true,
get: function () {
return _types.PluginType;
}
});
exports.WaitingPlugin = exports.UtilityPlugin = void 0;
var _timeline = require("./timeline");
var _types = require("./types");
class Plugin {
// default to utility to avoid automatic processing
type = _types.PluginType.utility;
analytics = undefined;
configure(analytics) {
this.analytics = analytics;
}
update(_settings, _type) {
// do nothing by default, user can override.
}
execute(event) {
// do nothing.
return event;
}
shutdown() {
// do nothing by default, user can override.
}
}
exports.Plugin = Plugin;
class EventPlugin extends Plugin {
execute(event) {
if (event === undefined) {
return event;
}
let result = event;
switch (result.type) {
case _types.EventType.IdentifyEvent:
result = this.identify(result);
break;
case _types.EventType.TrackEvent:
result = this.track(result);
break;
case _types.EventType.ScreenEvent:
result = this.screen(result);
break;
case _types.EventType.AliasEvent:
result = this.alias(result);
break;
case _types.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) {
return event;
}
track(event) {
return event;
}
screen(event) {
return event;
}
alias(event) {
return event;
}
group(event) {
return event;
}
flush() {
return;
}
reset() {
return;
}
}
exports.EventPlugin = EventPlugin;
class DestinationPlugin extends EventPlugin {
// default to destination
type = _types.PluginType.destination;
key = '';
timeline = new _timeline.Timeline();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
hasSettings() {
return this.analytics?.settings.get()?.[this.key] !== undefined;
}
isEnabled(event) {
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) {
const analytics = this.analytics;
if (analytics) {
plugin.configure(analytics);
}
if (analytics && plugin instanceof WaitingPlugin) {
analytics.pauseEventProcessingForPlugin(plugin);
}
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) {
this.timeline.apply(closure);
}
configure(analytics) {
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) {
this.timeline.remove(plugin);
}
async execute(event) {
if (!this.isEnabled(event)) {
return;
}
// Apply before and enrichment plugins
const beforeResult = await this.timeline.applyPlugins({
type: _types.PluginType.before,
event
});
if (beforeResult === undefined) {
return;
}
const enrichmentResult = await this.timeline.applyPlugins({
type: _types.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: _types.PluginType.after,
event: enrichmentResult
});
return afterResult;
}
}
exports.DestinationPlugin = DestinationPlugin;
class UtilityPlugin extends EventPlugin {}
// For internal platform-specific bits
exports.UtilityPlugin = UtilityPlugin;
class PlatformPlugin extends Plugin {}
exports.PlatformPlugin = PlatformPlugin;
/**
* WaitingPlugin - A base class for plugins that need to pause event processing
* until an asynchronous operation completes.
*
* When a WaitingPlugin is added to the Analytics client, it automatically pauses
* event processing. Events are buffered in memory until the plugin calls resume().
* If resume() is not called within 30 seconds, event processing automatically resumes.
*
* @example
* ```typescript
* class IDFAPlugin extends WaitingPlugin {
* type = PluginType.enrichment;
*
* configure(analytics: SegmentClient) {
* super.configure(analytics);
* // Request IDFA permission
* requestTrackingPermission().then((status) => {
* if (status === 'authorized') {
* // Add IDFA to context
* }
* this.resume(); // Resume event processing
* });
* }
*
* track(event: SegmentEvent) {
* // Enrich event with IDFA if available
* return event;
* }
* }
* ```
*
* Common use cases:
* - Waiting for user permissions (IDFA, location, notifications)
* - Initializing native SDKs that provide enrichment data
* - Loading remote configuration required for event processing
* - Waiting for authentication state before sending events
*
* @remarks
* Multiple WaitingPlugins can be active simultaneously. Event processing
* only resumes when ALL waiting plugins have called resume() or timed out.
*
* WaitingPlugins can be added at any plugin type (before, enrichment, destination).
* They can also be added to DestinationPlugins to pause only that destination's
* event processing.
*/
class WaitingPlugin extends Plugin {
constructor() {
super();
}
/**
* Configure the plugin with the Analytics client.
* Automatically pauses event processing when called.
* Override this method to perform async initialization, then call resume().
*
* @param analytics - The Analytics client instance
*/
configure(analytics) {
super.configure(analytics);
}
/**
* Manually pause event processing.
* Generally not needed as adding a WaitingPlugin automatically pauses processing.
*/
pause() {
this.analytics?.pauseEventProcessingForPlugin(this);
}
/**
* Resume event processing for this plugin.
* Call this method when your async operation completes.
* If all WaitingPlugins have resumed, buffered events will be processed.
*/
async resume() {
await this.analytics?.resumeEventProcessingForPlugin(this);
}
}
exports.WaitingPlugin = WaitingPlugin;
//# sourceMappingURL=plugin.js.map