UNPKG

clean-insights-sdk

Version:

A privacy-preserving measurement framework.

164 lines (163 loc) 7.63 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Campaign = void 0; var dayjs_1 = __importDefault(require("dayjs")); var duration_1 = __importDefault(require("dayjs/plugin/duration")); var isSameOrBefore_1 = __importDefault(require("dayjs/plugin/isSameOrBefore")); dayjs_1.default.extend(duration_1.default); dayjs_1.default.extend(isSameOrBefore_1.default); var EventAggregationRule_1 = require("./EventAggregationRule"); var Campaign = /** @class */ (function () { /** * @param {dayjs.Dayjs|CampaignData} start * The start of the campaign. (inclusive) * * @param {dayjs.Dayjs=} end * The end of the campaign. (inclusive) OPTIONAL if provided via an object as first argument. * * @param {number=} aggregationPeriodLength * The length of the aggregation period in number of days. At the end of a period, * the aggregated data will be sent to the analytics server. * OPTIONAL if provided via an object as first argument. * * @param {number=} numberOfPeriods=1 * The number of periods you want to measure in a row. Therefore the total * length in days you measure one user is `aggregationPeriodLength * numberOfPeriods` * beginning with the first day of the next period after the user consented. * * @param {boolean=} onlyRecordOnce=false * Will result in recording only the first time a visit or event happened * per period. Useful for yes/no questions. * * @param {EventAggregationRule=} eventAggregationRule=.Sum * The rule how to aggregate the value of an event (if any given) * with subsequent calls. * * @param {boolean=} strengthenAnonymity=false * When set to true, measurements only ever start at the next full period. * This ensures, that anonymity guaranties aren't accidentally reduced because the * first period is very short. */ function Campaign(start, end, aggregationPeriodLength, numberOfPeriods, onlyRecordOnce, eventAggregationRule, strengthenAnonymity) { if ('isValid' in start) { // Just checks for an arbitrary Day.js function, because instanceof test throws. if (!end || !aggregationPeriodLength) { throw TypeError('You either need to provide all non-optional arguments in their place or in an object as the first argument.'); } this.start = start; this.end = end; this.aggregationPeriodLength = aggregationPeriodLength; this.numberOfPeriods = typeof numberOfPeriods === 'number' ? numberOfPeriods : 1; this.onlyRecordOnce = onlyRecordOnce || false; this.eventAggregationRule = eventAggregationRule || EventAggregationRule_1.EventAggregationRule.Sum; this.strengthenAnonymity = strengthenAnonymity || false; } else { this.start = (0, dayjs_1.default)(start.start); this.end = (0, dayjs_1.default)(start.end); this.aggregationPeriodLength = start.aggregationPeriodLength; this.numberOfPeriods = typeof start.numberOfPeriods === 'number' ? start.numberOfPeriods : 1; this.onlyRecordOnce = start.onlyRecordOnce || false; this.eventAggregationRule = start.eventAggregationRule === "avg" ? EventAggregationRule_1.EventAggregationRule.Avg : EventAggregationRule_1.EventAggregationRule.Sum; this.strengthenAnonymity = start.strengthenAnonymity || false; } } Object.defineProperty(Campaign.prototype, "aggregationPeriod", { get: function () { return dayjs_1.default.duration(this.aggregationPeriodLength, 'days'); }, enumerable: false, configurable: true }); Object.defineProperty(Campaign.prototype, "currentMeasurementPeriod", { /** * Returns the current measurement period, aka. the period where NOW is in. * * If NOW is outside any possible period, because the campaign hasn't started, * yet, or already ended, will return `null`. * * The first period is defined as `aggregationPeriodLength` number of days after * the `start` of the campaign. * * @returns {?{start: dayjs.Dayjs, end: dayjs.Dayjs}} */ get: function () { if (this.numberOfPeriods <= 0) { return null; } var now = (0, dayjs_1.default)(); var periodEnd = this.start; do { periodEnd = periodEnd.add(this.aggregationPeriod); } while (periodEnd.isSameOrBefore(now)); var periodStart = periodEnd.subtract(this.aggregationPeriod).isAfter(this.start) ? periodEnd.subtract(this.aggregationPeriod) : this.start; if (periodEnd.isAfter(this.end)) { periodEnd = this.end; } now = (0, dayjs_1.default)(); if (periodStart.isAfter(now) || periodEnd.isBefore(now)) { return null; } return { start: periodStart, end: periodEnd }; }, enumerable: false, configurable: true }); Object.defineProperty(Campaign.prototype, "nextTotalMeasurementPeriod", { /** * @returns {?{start: dayjs.Dayjs, end: dayjs.Dayjs}} */ get: function () { var current = this.currentMeasurementPeriod; if (!current) { return null; } var periodStart = this.strengthenAnonymity ? current.end : current.start; var periodEnd = periodStart; var counter = 0; while (counter < this.numberOfPeriods && periodEnd.add(this.aggregationPeriod) <= this.end) { periodEnd = periodEnd.add(this.aggregationPeriod); counter += 1; } if (periodStart.isSame(periodEnd)) { return null; } return { start: periodStart, end: periodEnd }; }, enumerable: false, configurable: true }); /** * Apply the `eventAggregationRule` to the given event with the given value. * * @param {Event} event * The event to apply the value to. * * @param {number=} value * The value to apply. */ Campaign.prototype.apply = function (event, value) { if (this.onlyRecordOnce || typeof value !== 'number') { return; } var oldVal = typeof event.value === 'number' ? event.value : 0; switch (this.eventAggregationRule) { case "sum": event.value = oldVal + value; break; case "avg": // times was already increased in CleanInsights#getAndMeasure! event.value = (oldVal * (event.times - 1) + value) / event.times; break; } }; Campaign.prototype.toString = function () { return "[".concat(this.constructor.name, ": start=").concat(this.start, ", end=").concat(this.end, ", aggregationPeriodLength=").concat(this.aggregationPeriodLength, ", numberOfPeriods=").concat(this.numberOfPeriods, ", onlyRecordOnce=").concat(this.onlyRecordOnce, ", eventAggregationRule=").concat(this.eventAggregationRule, "]"); }; return Campaign; }()); exports.Campaign = Campaign;