UNPKG

@segment/analytics-next

Version:

Analytics Next (aka Analytics 2.0) is the latest version of Segment’s JavaScript SDK - enabling you to send your data to any tool without having to learn, test, or use a new API every time.

352 lines 17.8 kB
import { __assign, __awaiter, __generator, __spreadArray } from "tslib"; import { Alias, Group, Identify, Page, Track } from '@segment/facade'; import { isOffline, isOnline } from '../../core/connection'; import { Context, ContextCancelation } from '../../core/context'; import { isServer } from '../../core/environment'; import { attempt } from '@segment/analytics-core'; import { isPlanEventEnabled } from '../../lib/is-plan-event-enabled'; import { mergedOptions } from '../../lib/merged-options'; import { pWhile } from '../../lib/p-while'; import { PriorityQueue } from '../../lib/priority-queue'; import { PersistedPriorityQueue } from '../../lib/priority-queue/persisted'; import { applyDestinationMiddleware, } from '../middleware'; import { buildIntegration, loadIntegration, resolveIntegrationNameFromSource, resolveVersion, unloadIntegration, } from './loader'; import { isPlainObject } from '@segment/analytics-core'; import { isDisabledIntegration as shouldSkipIntegration, isInstallableIntegration, } from './utils'; import { recordIntegrationMetric } from '../../core/stats/metric-helpers'; import { createDeferred } from '@segment/analytics-generic-utils'; function flushQueue(xt, queue) { return __awaiter(this, void 0, void 0, function () { var failedQueue; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: failedQueue = []; if (isOffline()) { return [2 /*return*/, queue]; } return [4 /*yield*/, pWhile(function () { return queue.length > 0 && isOnline(); }, function () { return __awaiter(_this, void 0, void 0, function () { var ctx, result, success; return __generator(this, function (_a) { switch (_a.label) { case 0: ctx = queue.pop(); if (!ctx) { return [2 /*return*/]; } return [4 /*yield*/, attempt(ctx, xt)]; case 1: result = _a.sent(); success = result instanceof Context; if (!success) { failedQueue.push(ctx); } return [2 /*return*/]; } }); }); }) // re-add failed tasks ]; case 1: _a.sent(); // re-add failed tasks failedQueue.map(function (failed) { return queue.pushWithBackoff(failed); }); return [2 /*return*/, queue]; } }); }); } var LegacyDestination = /** @class */ (function () { function LegacyDestination(name, version, writeKey, settings, options, integrationSource) { if (settings === void 0) { settings = {}; } var _this = this; this.options = {}; this.type = 'destination'; this.middleware = []; this.initializePromise = createDeferred(); this.flushing = false; this.name = name; this.version = version; this.settings = __assign({}, settings); this.disableAutoISOConversion = options.disableAutoISOConversion || false; this.integrationSource = integrationSource; // AJS-Renderer sets an extraneous `type` setting that clobbers // existing type defaults. We need to remove it if it's present if (this.settings['type'] && this.settings['type'] === 'browser') { delete this.settings['type']; } this.initializePromise.promise.then(function (isInitialized) { return (_this._initialized = isInitialized); }, function () { }); this.options = options; this.buffer = options.disableClientPersistence ? new PriorityQueue(4, []) : new PersistedPriorityQueue(4, "".concat(writeKey, ":dest-").concat(name)); this.scheduleFlush(); } LegacyDestination.prototype.isLoaded = function () { return !!this._ready; }; LegacyDestination.prototype.ready = function () { var _this = this; return this.initializePromise.promise.then(function () { var _a; return (_a = _this.onReady) !== null && _a !== void 0 ? _a : Promise.resolve(); }); }; LegacyDestination.prototype.load = function (ctx, analyticsInstance) { var _a; return __awaiter(this, void 0, void 0, function () { var integrationSource, _b; var _this = this; return __generator(this, function (_c) { switch (_c.label) { case 0: if (this._ready || this.onReady !== undefined) { return [2 /*return*/]; } if (!((_a = this.integrationSource) !== null && _a !== void 0)) return [3 /*break*/, 1]; _b = _a; return [3 /*break*/, 3]; case 1: return [4 /*yield*/, loadIntegration(ctx, this.name, this.version, this.options.obfuscate)]; case 2: _b = (_c.sent()); _c.label = 3; case 3: integrationSource = _b; this.integration = buildIntegration(integrationSource, this.settings, analyticsInstance); this.onReady = new Promise(function (resolve) { var onReadyFn = function () { _this._ready = true; resolve(true); }; _this.integration.once('ready', onReadyFn); }); this.integration.on('initialize', function () { _this.initializePromise.resolve(true); }); try { recordIntegrationMetric(ctx, { integrationName: this.name, methodName: 'initialize', type: 'classic', }); this.integration.initialize(); } catch (error) { recordIntegrationMetric(ctx, { integrationName: this.name, methodName: 'initialize', type: 'classic', didError: true, }); this.initializePromise.resolve(false); throw error; } return [2 /*return*/]; } }); }); }; LegacyDestination.prototype.unload = function (_ctx, _analyticsInstance) { return unloadIntegration(this.name, this.version, this.options.obfuscate); }; LegacyDestination.prototype.addMiddleware = function () { var _a; var fn = []; for (var _i = 0; _i < arguments.length; _i++) { fn[_i] = arguments[_i]; } this.middleware = (_a = this.middleware).concat.apply(_a, fn); }; LegacyDestination.prototype.shouldBuffer = function (ctx) { return ( // page events can't be buffered because of destinations that automatically add page views ctx.event.type !== 'page' && (isOffline() || this._ready !== true || this._initialized !== true)); }; LegacyDestination.prototype.send = function (ctx, clz, eventType) { var _a, _b; return __awaiter(this, void 0, void 0, function () { var plan, ev, planEvent, afterMiddleware, event, err_1; return __generator(this, function (_c) { switch (_c.label) { case 0: if (this.shouldBuffer(ctx)) { this.buffer.push(ctx); this.scheduleFlush(); return [2 /*return*/, ctx]; } plan = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.plan) === null || _b === void 0 ? void 0 : _b.track; ev = ctx.event.event; if (plan && ev && this.name !== 'Segment.io') { planEvent = plan[ev]; if (!isPlanEventEnabled(plan, planEvent)) { ctx.updateEvent('integrations', __assign(__assign({}, ctx.event.integrations), { All: false, 'Segment.io': true })); ctx.cancel(new ContextCancelation({ retry: false, reason: "Event ".concat(ev, " disabled for integration ").concat(this.name, " in tracking plan"), type: 'Dropped by plan', })); } else { ctx.updateEvent('integrations', __assign(__assign({}, ctx.event.integrations), planEvent === null || planEvent === void 0 ? void 0 : planEvent.integrations)); } if ((planEvent === null || planEvent === void 0 ? void 0 : planEvent.enabled) && (planEvent === null || planEvent === void 0 ? void 0 : planEvent.integrations[this.name]) === false) { ctx.cancel(new ContextCancelation({ retry: false, reason: "Event ".concat(ev, " disabled for integration ").concat(this.name, " in tracking plan"), type: 'Dropped by plan', })); } } return [4 /*yield*/, applyDestinationMiddleware(this.name, ctx.event, this.middleware)]; case 1: afterMiddleware = _c.sent(); if (afterMiddleware === null) { return [2 /*return*/, ctx]; } event = new clz(afterMiddleware, { traverse: !this.disableAutoISOConversion, }); recordIntegrationMetric(ctx, { integrationName: this.name, methodName: eventType, type: 'classic', }); _c.label = 2; case 2: _c.trys.push([2, 5, , 6]); if (!this.integration) return [3 /*break*/, 4]; return [4 /*yield*/, this.integration.invoke.call(this.integration, eventType, event)]; case 3: _c.sent(); _c.label = 4; case 4: return [3 /*break*/, 6]; case 5: err_1 = _c.sent(); recordIntegrationMetric(ctx, { integrationName: this.name, methodName: eventType, type: 'classic', didError: true, }); throw err_1; case 6: return [2 /*return*/, ctx]; } }); }); }; LegacyDestination.prototype.track = function (ctx) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.send(ctx, Track, 'track')]; }); }); }; LegacyDestination.prototype.page = function (ctx) { var _a; return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_b) { switch (_b.label) { case 0: if (((_a = this.integration) === null || _a === void 0 ? void 0 : _a._assumesPageview) && !this._initialized) { this.integration.initialize(); } return [4 /*yield*/, this.initializePromise.promise]; case 1: _b.sent(); return [2 /*return*/, this.send(ctx, Page, 'page')]; } }); }); }; LegacyDestination.prototype.identify = function (ctx) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.send(ctx, Identify, 'identify')]; }); }); }; LegacyDestination.prototype.alias = function (ctx) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.send(ctx, Alias, 'alias')]; }); }); }; LegacyDestination.prototype.group = function (ctx) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.send(ctx, Group, 'group')]; }); }); }; LegacyDestination.prototype.scheduleFlush = function () { var _this = this; if (this.flushing) { return; } // eslint-disable-next-line @typescript-eslint/no-misused-promises setTimeout(function () { return __awaiter(_this, void 0, void 0, function () { var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (isOffline() || this._ready !== true || this._initialized !== true) { this.scheduleFlush(); return [2 /*return*/]; } this.flushing = true; _a = this; return [4 /*yield*/, flushQueue(this, this.buffer)]; case 1: _a.buffer = _b.sent(); this.flushing = false; if (this.buffer.todo > 0) { this.scheduleFlush(); } return [2 /*return*/]; } }); }); }, Math.random() * 5000); }; return LegacyDestination; }()); export { LegacyDestination }; export function ajsDestinations(writeKey, settings, globalIntegrations, options, routingMiddleware, legacyIntegrationSources) { var _a, _b; if (globalIntegrations === void 0) { globalIntegrations = {}; } if (options === void 0) { options = {}; } if (isServer()) { return []; } if (settings.plan) { options = options !== null && options !== void 0 ? options : {}; options.plan = settings.plan; } var routingRules = (_b = (_a = settings.middlewareSettings) === null || _a === void 0 ? void 0 : _a.routingRules) !== null && _b !== void 0 ? _b : []; var remoteIntegrationsConfig = settings.integrations; var localIntegrationsConfig = options.integrations; // merged remote CDN settings with user provided options var integrationOptions = mergedOptions(settings, options !== null && options !== void 0 ? options : {}); var adhocIntegrationSources = legacyIntegrationSources === null || legacyIntegrationSources === void 0 ? void 0 : legacyIntegrationSources.reduce(function (acc, integrationSource) { var _a; return (__assign(__assign({}, acc), (_a = {}, _a[resolveIntegrationNameFromSource(integrationSource)] = integrationSource, _a))); }, {}); var installableIntegrations = new Set(__spreadArray(__spreadArray([], Object.keys(remoteIntegrationsConfig).filter(function (name) { return isInstallableIntegration(name, remoteIntegrationsConfig[name]); }), true), Object.keys(adhocIntegrationSources || {}).filter(function (name) { return isPlainObject(remoteIntegrationsConfig[name]) || isPlainObject(localIntegrationsConfig === null || localIntegrationsConfig === void 0 ? void 0 : localIntegrationsConfig[name]); }), true)); return Array.from(installableIntegrations) .filter(function (name) { return !shouldSkipIntegration(name, globalIntegrations); }) .map(function (name) { var integrationSettings = remoteIntegrationsConfig[name]; var version = resolveVersion(integrationSettings); var destination = new LegacyDestination(name, version, writeKey, integrationOptions[name], options, adhocIntegrationSources === null || adhocIntegrationSources === void 0 ? void 0 : adhocIntegrationSources[name]); var routing = routingRules.filter(function (rule) { return rule.destinationName === name; }); if (routing.length > 0 && routingMiddleware) { destination.addMiddleware(routingMiddleware); } return destination; }); } //# sourceMappingURL=index.js.map