UNPKG

@amplitude/analytics-core

Version:
279 lines 12.5 kB
import { __awaiter, __generator, __values } from "tslib"; import { IdentifyOperation, SpecialEventType, } from './types/event/event'; import { OrderedIdentifyOperations } from './identify'; import { CLIENT_NOT_INITIALIZED, OPT_OUT_MESSAGE } from './types/messages'; import { Timeline } from './timeline'; import { createGroupEvent, createGroupIdentifyEvent, createIdentifyEvent, createRevenueEvent, createTrackEvent, } from './utils/event-builder'; import { buildResult } from './utils/result-builder'; import { returnWrapper } from './utils/return-wrapper'; var AmplitudeCore = /** @class */ (function () { function AmplitudeCore(name) { if (name === void 0) { name = '$default'; } this.initializing = false; this.isReady = false; this.q = []; this.dispatchQ = []; this.logEvent = this.track.bind(this); this.timeline = new Timeline(this); this.name = name; } AmplitudeCore.prototype._init = function (config) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: this.config = config; this.timeline.reset(this); return [4 /*yield*/, this.runQueuedFunctions('q')]; case 1: _a.sent(); this.isReady = true; return [2 /*return*/]; } }); }); }; AmplitudeCore.prototype.runQueuedFunctions = function (queueName) { return __awaiter(this, void 0, void 0, function () { var queuedFunctions, queuedFunctions_1, queuedFunctions_1_1, queuedFunction, val, e_1_1; var e_1, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: queuedFunctions = this[queueName]; this[queueName] = []; _b.label = 1; case 1: _b.trys.push([1, 8, 9, 10]); queuedFunctions_1 = __values(queuedFunctions), queuedFunctions_1_1 = queuedFunctions_1.next(); _b.label = 2; case 2: if (!!queuedFunctions_1_1.done) return [3 /*break*/, 7]; queuedFunction = queuedFunctions_1_1.value; val = queuedFunction(); if (!(val && 'promise' in val)) return [3 /*break*/, 4]; return [4 /*yield*/, val.promise]; case 3: _b.sent(); return [3 /*break*/, 6]; case 4: return [4 /*yield*/, val]; case 5: _b.sent(); _b.label = 6; case 6: queuedFunctions_1_1 = queuedFunctions_1.next(); return [3 /*break*/, 2]; case 7: return [3 /*break*/, 10]; case 8: e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 10]; case 9: try { if (queuedFunctions_1_1 && !queuedFunctions_1_1.done && (_a = queuedFunctions_1.return)) _a.call(queuedFunctions_1); } finally { if (e_1) throw e_1.error; } return [7 /*endfinally*/]; case 10: if (!this[queueName].length) return [3 /*break*/, 12]; return [4 /*yield*/, this.runQueuedFunctions(queueName)]; case 11: _b.sent(); _b.label = 12; case 12: return [2 /*return*/]; } }); }); }; AmplitudeCore.prototype.track = function (eventInput, eventProperties, eventOptions) { var event = createTrackEvent(eventInput, eventProperties, eventOptions); return returnWrapper(this.dispatch(event)); }; AmplitudeCore.prototype.identify = function (identify, eventOptions) { var event = createIdentifyEvent(identify, eventOptions); return returnWrapper(this.dispatch(event)); }; AmplitudeCore.prototype.groupIdentify = function (groupType, groupName, identify, eventOptions) { var event = createGroupIdentifyEvent(groupType, groupName, identify, eventOptions); return returnWrapper(this.dispatch(event)); }; AmplitudeCore.prototype.setGroup = function (groupType, groupName, eventOptions) { var event = createGroupEvent(groupType, groupName, eventOptions); return returnWrapper(this.dispatch(event)); }; AmplitudeCore.prototype.revenue = function (revenue, eventOptions) { var event = createRevenueEvent(revenue, eventOptions); return returnWrapper(this.dispatch(event)); }; AmplitudeCore.prototype.add = function (plugin) { if (!this.isReady) { this.q.push(this._addPlugin.bind(this, plugin)); return returnWrapper(); } return this._addPlugin(plugin); }; AmplitudeCore.prototype._addPlugin = function (plugin) { return returnWrapper(this.timeline.register(plugin, this.config)); }; AmplitudeCore.prototype.remove = function (pluginName) { if (!this.isReady) { this.q.push(this._removePlugin.bind(this, pluginName)); return returnWrapper(); } return this._removePlugin(pluginName); }; AmplitudeCore.prototype._removePlugin = function (pluginName) { return returnWrapper(this.timeline.deregister(pluginName, this.config)); }; AmplitudeCore.prototype.dispatchWithCallback = function (event, callback) { if (!this.isReady) { return callback(buildResult(event, 0, CLIENT_NOT_INITIALIZED)); } void this.process(event).then(callback); }; AmplitudeCore.prototype.dispatch = function (event) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { if (!this.isReady) { return [2 /*return*/, new Promise(function (resolve) { _this.dispatchQ.push(_this.dispatchWithCallback.bind(_this, event, resolve)); })]; } return [2 /*return*/, this.process(event)]; }); }); }; /** * * This method applies identify operations to user properties and * returns a single object representing the final user property state. * * This is a best-effort api that only supports $set, $clearAll, and $unset. * Other operations are not supported and are ignored. * * * @param userProperties The `event.userProperties` object from an Identify event. * @returns A key-value object user properties without operations. * * @example * Input: * { * $set: { plan: 'premium' }, * custom_flag: true * } * * Output: * { * plan: 'premium', * custom_flag: true * } */ AmplitudeCore.prototype.getOperationAppliedUserProperties = function (userProperties) { var updatedProperties = {}; if (userProperties === undefined) { return updatedProperties; } // Keep non-operation keys for later merge var nonOpProperties = {}; Object.keys(userProperties).forEach(function (key) { if (!Object.values(IdentifyOperation).includes(key)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment nonOpProperties[key] = userProperties[key]; } }); OrderedIdentifyOperations.forEach(function (operation) { // Skip when key is an operation. if (!Object.keys(userProperties).includes(operation)) return; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment var opProperties = userProperties[operation]; switch (operation) { case IdentifyOperation.CLEAR_ALL: // Due to operation order, the following line will never execute. /* istanbul ignore next */ Object.keys(updatedProperties).forEach(function (prop) { delete updatedProperties[prop]; }); break; case IdentifyOperation.UNSET: Object.keys(opProperties).forEach(function (prop) { delete updatedProperties[prop]; }); break; case IdentifyOperation.SET: Object.assign(updatedProperties, opProperties); break; } }); // Merge non-operation properties. // Custom properties should not be affected by operations. // https://github.com/amplitude/nova/blob/343f678ded83c032e83b189796b3c2be161b48f5/src/main/java/com/amplitude/userproperty/model/ModifyUserPropertiesIdent.java#L79-L83 Object.assign(updatedProperties, nonOpProperties); return updatedProperties; }; AmplitudeCore.prototype.process = function (event) { return __awaiter(this, void 0, void 0, function () { var userProperties, result, e_2, message, result; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); // skip event processing if opt out if (this.config.optOut) { return [2 /*return*/, buildResult(event, 0, OPT_OUT_MESSAGE)]; } if (event.event_type === SpecialEventType.IDENTIFY) { userProperties = this.getOperationAppliedUserProperties(event.user_properties); this.timeline.onIdentityChanged({ userProperties: userProperties }); } return [4 /*yield*/, this.timeline.push(event)]; case 1: result = _a.sent(); result.code === 200 ? this.config.loggerProvider.log(result.message) : result.code === 100 ? this.config.loggerProvider.warn(result.message) : this.config.loggerProvider.error(result.message); return [2 /*return*/, result]; case 2: e_2 = _a.sent(); message = String(e_2); this.config.loggerProvider.error(message); result = buildResult(event, 0, message); return [2 /*return*/, result]; case 3: return [2 /*return*/]; } }); }); }; AmplitudeCore.prototype.setOptOut = function (optOut) { if (!this.isReady) { this.q.push(this._setOptOut.bind(this, Boolean(optOut))); return; } this._setOptOut(optOut); }; AmplitudeCore.prototype._setOptOut = function (optOut) { if (this.config.optOut !== optOut) { this.timeline.onOptOutChanged(optOut); this.config.optOut = Boolean(optOut); } }; AmplitudeCore.prototype.flush = function () { return returnWrapper(this.timeline.flush()); }; AmplitudeCore.prototype.plugin = function (name) { var plugin = this.timeline.plugins.find(function (plugin) { return plugin.name === name; }); if (plugin === undefined) { this.config.loggerProvider.debug("Cannot find plugin with name ".concat(name)); return undefined; } return plugin; }; return AmplitudeCore; }()); export { AmplitudeCore }; //# sourceMappingURL=core-client.js.map