UNPKG

posthog-js

Version:

Posthog-js allows you to automatically capture usage and send events to PostHog.

492 lines • 22 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SiteApps = void 0; var core_1 = require("@posthog/core"); var globals_1 = require("@posthog/browser-common/utils/globals"); var globals_2 = require("./utils/globals"); var logger_1 = require("@posthog/browser-common/utils/logger"); var logger = (0, logger_1.createLogger)('[SiteApps]'); var APP_INIT_ERROR = 'Error while initializing PostHog app with config id '; var SiteApps = /** @class */ (function () { function SiteApps(_instance) { this._instance = _instance; this._siteAppElementPatchCount = 0; // events captured between loading posthog-js and the site app; up to 1000 events this._bufferedInvocations = []; this.apps = {}; } Object.defineProperty(SiteApps.prototype, "isEnabled", { get: function () { return !!this._instance.config.opt_in_site_apps; }, enumerable: false, configurable: true }); SiteApps.prototype._eventCollector = function (_eventName, eventPayload) { if (!eventPayload) { return; } var globals = this.globalsForEvent(eventPayload); this._bufferedInvocations.push(globals); if (this._bufferedInvocations.length > 1000) { this._bufferedInvocations = this._bufferedInvocations.slice(10); } }; Object.defineProperty(SiteApps.prototype, "siteAppLoaders", { get: function () { var _a, _b; return (_b = (_a = globals_2.assignableWindow._POSTHOG_REMOTE_CONFIG) === null || _a === void 0 ? void 0 : _a[this._instance.config.token]) === null || _b === void 0 ? void 0 : _b.siteApps; }, enumerable: false, configurable: true }); SiteApps.prototype.initialize = function () { var _this = this; if (this.isEnabled) { var stop_1 = this._instance._addCaptureHook(this._eventCollector.bind(this)); this._stopBuffering = function () { stop_1(); _this._bufferedInvocations = []; _this._stopBuffering = undefined; }; } }; SiteApps.prototype.globalsForEvent = function (event) { var e_1, _a; var _b, _c, _d, _e, _f, _g, _h; if (!event) { throw new Error('Event payload is required'); } var groups = {}; var groupIds = this._instance.get_property('$groups') || []; var groupProperties = this._instance.get_property('$stored_group_properties') || {}; try { for (var _j = __values(Object.entries(groupProperties)), _k = _j.next(); !_k.done; _k = _j.next()) { var _l = __read(_k.value, 2), type = _l[0], properties = _l[1]; groups[type] = { id: groupIds[type], type: type, properties: properties }; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_k && !_k.done && (_a = _j.return)) _a.call(_j); } finally { if (e_1) throw e_1.error; } } var $set_once = event.$set_once, $set = event.$set, _event = __rest(event, ["$set_once", "$set"]); var globals = { event: __assign(__assign({}, _event), { properties: __assign(__assign(__assign({}, event.properties), ($set ? { $set: __assign(__assign({}, ((_c = (_b = event.properties) === null || _b === void 0 ? void 0 : _b.$set) !== null && _c !== void 0 ? _c : {})), $set) } : {})), ($set_once ? { $set_once: __assign(__assign({}, ((_e = (_d = event.properties) === null || _d === void 0 ? void 0 : _d.$set_once) !== null && _e !== void 0 ? _e : {})), $set_once) } : {})), elements_chain: (_g = (_f = event.properties) === null || _f === void 0 ? void 0 : _f['$elements_chain']) !== null && _g !== void 0 ? _g : '', // TODO: // - elements_chain_href: '', // - elements_chain_texts: [] as string[], // - elements_chain_ids: [] as string[], // - elements_chain_elements: [] as string[], distinct_id: (_h = event.properties) === null || _h === void 0 ? void 0 : _h['distinct_id'] }), person: { properties: this._instance.get_property('$stored_person_properties'), }, groups: groups, }; return globals; }; SiteApps.prototype._prepareElementForSiteApp = function (element) { var _a; var tagName = (_a = element.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase(); if (tagName === 'style' && this._instance.config.prepare_external_dependency_stylesheet) { var prepared = this._instance.config.prepare_external_dependency_stylesheet(element); if (!prepared) { logger.error('prepare_external_dependency_stylesheet returned null'); return null; } return prepared; } if (tagName === 'script' && this._instance.config.prepare_external_dependency_script) { var prepared = this._instance.config.prepare_external_dependency_script(element); if (!prepared) { logger.error('prepare_external_dependency_script returned null'); return null; } return prepared; } return element; }; SiteApps.prototype._patchSiteAppElementInsertionMethods = function () { var _this = this; var _a, _b, _c, _d, _e, _f, _g, _h; if (!this._instance.config.prepare_external_dependency_stylesheet && !this._instance.config.prepare_external_dependency_script) { return function () { }; } var win = globals_1.document === null || globals_1.document === void 0 ? void 0 : globals_1.document.defaultView; var nodePrototype = (_a = win === null || win === void 0 ? void 0 : win.Node) === null || _a === void 0 ? void 0 : _a.prototype; if (!win || !nodePrototype) { return function () { }; } this._siteAppElementPatchCount++; if (this._restoreSiteAppElementPatches) { return this._releaseSiteAppElementPatches(); } var restore = []; var siteApps = this; var preparedNodes = new WeakSet(); var patch = function (prototype, method, replacement) { if (!(prototype === null || prototype === void 0 ? void 0 : prototype[method])) { return; } var original = prototype[method]; prototype[method] = replacement(original); restore.push(function () { prototype[method] = original; }); }; var prepareNode = function (node) { if (preparedNodes.has(node)) { return node; } var prepared = siteApps._prepareElementForSiteApp(node); if (prepared) { preparedNodes.add(prepared); } return prepared; }; var prepareNodes = function (nodes) { return nodes .map(function (node) { return (typeof node === 'string' ? node : prepareNode(node)); }) .filter(function (node) { return !(0, core_1.isNull)(node); }); }; patch(nodePrototype, 'appendChild', function (original) { return function (child) { var prepared = prepareNode(child); return prepared ? original.call(this, prepared) : child; }; }); patch(nodePrototype, 'insertBefore', function (original) { return function (newChild, refChild) { var prepared = prepareNode(newChild); return prepared ? original.call(this, prepared, refChild) : newChild; }; }); patch(nodePrototype, 'replaceChild', function (original) { return function (newChild, oldChild) { var prepared = prepareNode(newChild); return prepared ? original.call(this, prepared, oldChild) : oldChild; }; }); [(_b = win.Element) === null || _b === void 0 ? void 0 : _b.prototype, (_c = win.Document) === null || _c === void 0 ? void 0 : _c.prototype, (_d = win.DocumentFragment) === null || _d === void 0 ? void 0 : _d.prototype].forEach(function (prototype) { patch(prototype, 'append', function (original) { return function () { var nodes = []; for (var _i = 0; _i < arguments.length; _i++) { nodes[_i] = arguments[_i]; } return original.apply(this, prepareNodes(nodes)); }; }); patch(prototype, 'prepend', function (original) { return function () { var nodes = []; for (var _i = 0; _i < arguments.length; _i++) { nodes[_i] = arguments[_i]; } return original.apply(this, prepareNodes(nodes)); }; }); }); [(_e = win.Element) === null || _e === void 0 ? void 0 : _e.prototype, (_f = win.CharacterData) === null || _f === void 0 ? void 0 : _f.prototype, (_g = win.DocumentType) === null || _g === void 0 ? void 0 : _g.prototype].forEach(function (prototype) { patch(prototype, 'before', function (original) { return function () { var nodes = []; for (var _i = 0; _i < arguments.length; _i++) { nodes[_i] = arguments[_i]; } return original.apply(this, prepareNodes(nodes)); }; }); patch(prototype, 'after', function (original) { return function () { var nodes = []; for (var _i = 0; _i < arguments.length; _i++) { nodes[_i] = arguments[_i]; } return original.apply(this, prepareNodes(nodes)); }; }); patch(prototype, 'replaceWith', function (original) { return function () { var nodes = []; for (var _i = 0; _i < arguments.length; _i++) { nodes[_i] = arguments[_i]; } var prepared = prepareNodes(nodes); return nodes.length && !prepared.length ? undefined : original.apply(this, prepared); }; }); }); patch((_h = win.Element) === null || _h === void 0 ? void 0 : _h.prototype, 'insertAdjacentElement', function (original) { return function (position, insertedElement) { var prepared = prepareNode(insertedElement); return prepared ? original.call(this, position, prepared) : null; }; }); this._restoreSiteAppElementPatches = function () { restore.forEach(function (restore) { return restore(); }); _this._restoreSiteAppElementPatches = undefined; }; return this._releaseSiteAppElementPatches(); }; SiteApps.prototype._releaseSiteAppElementPatches = function () { var _this = this; var released = false; return function () { var _a; if (released) { return; } released = true; _this._siteAppElementPatchCount--; if (_this._siteAppElementPatchCount === 0) { (_a = _this._restoreSiteAppElementPatches) === null || _a === void 0 ? void 0 : _a.call(_this); } }; }; SiteApps.prototype._runWithPreparedSiteAppElements = function (callback, restoreSynchronously) { if (restoreSynchronously === void 0) { restoreSynchronously = true; } var restore = this._patchSiteAppElementInsertionMethods(); try { var result = callback(restore); if (restoreSynchronously) { restore(); } return result; } catch (e) { restore(); throw e; } }; SiteApps.prototype.setupSiteApp = function (loader) { var _this = this; var app = this.apps[loader.id]; var processBufferedEvents = function () { var _a; if (!app.errored && _this._bufferedInvocations.length) { logger.info("Processing ".concat(_this._bufferedInvocations.length, " events for site app with id ").concat(loader.id)); _this._bufferedInvocations.forEach(function (globals) { return _this._runWithPreparedSiteAppElements(function () { var _a; return (_a = app.processEvent) === null || _a === void 0 ? void 0 : _a.call(app, globals); }); }); app.processedBuffer = true; } if (Object.values(_this.apps).every(function (app) { return app.processedBuffer || app.errored; })) { (_a = _this._stopBuffering) === null || _a === void 0 ? void 0 : _a.call(_this); } }; var hasInitReturned = false; var onLoaded = function (success) { app.errored = !success; app.loaded = true; logger.info("Site app with id ".concat(loader.id, " ").concat(success ? 'loaded' : 'errored')); // ensure that we don't call processBufferedEvents until after init() returns and we've set up processEvent if (hasInitReturned) { processBufferedEvents(); } }; try { var processEvent = this._runWithPreparedSiteAppElements(function (restore) { return loader.init({ posthog: _this._instance, callback: function (success) { restore(); onLoaded(success); }, }); }, false).processEvent; if (processEvent) { app.processEvent = processEvent; } hasInitReturned = true; } catch (e) { logger.error(APP_INIT_ERROR + loader.id, e); onLoaded(false); } // if the app loaded synchronously, process the events now if (hasInitReturned && app.loaded) { try { processBufferedEvents(); } catch (e) { logger.error("Error while processing buffered events PostHog app with config id ".concat(loader.id), e); app.errored = true; } } }; SiteApps.prototype._setupSiteApps = function () { var e_2, _a, e_3, _b; var siteAppLoaders = this.siteAppLoaders || []; try { // do this in 2 passes, so that this.apps is populated before we call init for (var siteAppLoaders_1 = __values(siteAppLoaders), siteAppLoaders_1_1 = siteAppLoaders_1.next(); !siteAppLoaders_1_1.done; siteAppLoaders_1_1 = siteAppLoaders_1.next()) { var loader = siteAppLoaders_1_1.value; this.apps[loader.id] = { id: loader.id, loaded: false, errored: false, processedBuffer: false, }; } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (siteAppLoaders_1_1 && !siteAppLoaders_1_1.done && (_a = siteAppLoaders_1.return)) _a.call(siteAppLoaders_1); } finally { if (e_2) throw e_2.error; } } try { for (var siteAppLoaders_2 = __values(siteAppLoaders), siteAppLoaders_2_1 = siteAppLoaders_2.next(); !siteAppLoaders_2_1.done; siteAppLoaders_2_1 = siteAppLoaders_2.next()) { var loader = siteAppLoaders_2_1.value; this.setupSiteApp(loader); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (siteAppLoaders_2_1 && !siteAppLoaders_2_1.done && (_b = siteAppLoaders_2.return)) _b.call(siteAppLoaders_2); } finally { if (e_3) throw e_3.error; } } }; SiteApps.prototype._onCapturedEvent = function (event) { var e_4, _a; if (Object.keys(this.apps).length === 0) { return; } var globals = this.globalsForEvent(event); var _loop_1 = function (app) { try { this_1._runWithPreparedSiteAppElements(function () { var _a; return (_a = app.processEvent) === null || _a === void 0 ? void 0 : _a.call(app, globals); }); } catch (e) { logger.error("Error while processing event ".concat(event.event, " for site app ").concat(app.id), e); } }; var this_1 = this; try { for (var _b = __values(Object.values(this.apps)), _c = _b.next(); !_c.done; _c = _b.next()) { var app = _c.value; _loop_1(app); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_4) throw e_4.error; } } }; SiteApps.prototype.onRemoteConfig = function (result) { var e_5, _a; var _this = this; var _b, _c, _d, _e, _f; if ((_b = this.siteAppLoaders) === null || _b === void 0 ? void 0 : _b.length) { if (!this.isEnabled) { logger.error("PostHog site apps are disabled. Enable the \"opt_in_site_apps\" config to proceed."); return; } this._setupSiteApps(); // NOTE: We could improve this to only fire if we actually have listeners for the event this._instance.on('eventCaptured', function (event) { return _this._onCapturedEvent(event); }); return; } // NOTE: Below this is now only the fallback for legacy site app support. Once we have fully removed to the remote config loader we can get rid of this (_c = this._stopBuffering) === null || _c === void 0 ? void 0 : _c.call(this); // On a failed fetch there are no legacy site apps to load; buffering has // already been stopped above, same as for a response without site apps. if (!result.ok) { return; } var response = result.config; if (!((_d = response['siteApps']) === null || _d === void 0 ? void 0 : _d.length)) { return; } if (!this.isEnabled) { logger.error("PostHog site apps are disabled. Enable the \"opt_in_site_apps\" config to proceed."); return; } var _loop_2 = function (id, url) { globals_2.assignableWindow["__$$ph_site_app_".concat(id)] = this_2._instance; (_f = (_e = globals_2.assignableWindow.__PosthogExtensions__) === null || _e === void 0 ? void 0 : _e.loadSiteApp) === null || _f === void 0 ? void 0 : _f.call(_e, this_2._instance, url, function (err) { if (err) { return logger.error(APP_INIT_ERROR + id, err); } }); }; var this_2 = this; try { for (var _g = __values(response['siteApps']), _h = _g.next(); !_h.done; _h = _g.next()) { var _j = _h.value, id = _j.id, url = _j.url; _loop_2(id, url); } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_h && !_h.done && (_a = _g.return)) _a.call(_g); } finally { if (e_5) throw e_5.error; } } }; return SiteApps; }()); exports.SiteApps = SiteApps; //# sourceMappingURL=site-apps.js.map