analytics
Version:
Lightweight analytics library for tracking events, page views, & identifying users. Works with any third party analytics provider via an extendable plugin system.
4,968 lines • 164 kB
JavaScript
var _analytics = (function (exports) {
'use strict';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var defineProperty = _defineProperty;
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(source, true).forEach(function (key) {
defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(source).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
var objectSpread2 = _objectSpread2;
function dotProp (t, e, l, n, r) {
for (e = e.split ? e.split(".") : e, n = 0; n < e.length; n++) t = t ? t[e[n]] : r;
return t === r ? l : t;
}
var i = "undefined" != typeof window;
function c(t) {
return "function" == typeof t;
}
function p(t) {
return "string" == typeof t;
}
function a(t) {
return void 0 === t;
}
function y(t) {
return "boolean" == typeof t;
}
function g(t) {
return "[object Array]" === Object.prototype.toString.call(t);
}
function l(t) {
if ("object" != typeof t || null === t) return !1;
for (var n = t; null !== Object.getPrototypeOf(n);) n = Object.getPrototypeOf(n);
return Object.getPrototypeOf(t) === n;
}
function t$1(e$$1) {
try {
return decodeURIComponent(e$$1.replace(/\+/g, " "));
} catch (e$$1) {
return null;
}
}
function s$1(r$$1) {
return function (e$$1) {
for (var r$$1, n$$1 = {}, o$$1 = /([^&=]+)=?([^&]*)/g; r$$1 = o$$1.exec(e$$1);) {
var a$$1 = t$1(r$$1[1]),
i$$1 = t$1(r$$1[2]);
"[]" === a$$1.substring(a$$1.length - 2) ? (n$$1[a$$1 = a$$1.substring(0, a$$1.length - 2)] || (n$$1[a$$1] = [])).push(i$$1) : n$$1[a$$1] = "" === i$$1 || i$$1;
}
for (var u$$1 in n$$1) {
var c$$1 = u$$1.split("[");
c$$1.length > 1 && (m(n$$1, c$$1.map(function (e$$1) {
return e$$1.replace(/[?[\]\\ ]/g, "");
}), n$$1[u$$1]), delete n$$1[u$$1]);
}
return n$$1;
}(function (r$$1) {
if (r$$1) {
var n$$1 = r$$1.match(/\?(.*)/);
return n$$1 && n$$1[1] ? n$$1[1].split("#")[0] : "";
}
return i && window.location.search.substring(1);
}(r$$1));
}
function m(e$$1, r$$1, n$$1) {
for (var t$$1 = r$$1.length - 1, o$$1 = 0; o$$1 < t$$1; ++o$$1) {
var a$$1 = r$$1[o$$1];
a$$1 in e$$1 || (e$$1[a$$1] = {}), e$$1 = e$$1[a$$1];
}
e$$1[r$$1[t$$1]] = n$$1;
}
function y$1() {
for (var e$$1 = "", r$$1 = 0, n$$1 = 4294967295 * Math.random() | 0; r$$1++ < 36;) {
var t$$1 = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"[r$$1 - 1],
o$$1 = 15 & n$$1;
e$$1 += "-" == t$$1 || "4" == t$$1 ? t$$1 : ("x" == t$$1 ? o$$1 : 3 & o$$1 | 8).toString(16), n$$1 = r$$1 % 8 == 0 ? 4294967295 * Math.random() | 0 : n$$1 >> 4;
}
return e$$1;
}
var l$2 = "object" == typeof self && self.self === self && self || "object" == typeof global && global.global === global && global || void 0,
e$1 = "undefined";
function o$2(e) {
return l$2[e];
}
function f$2(e, o) {
return l$2[e] = o, o;
}
function n$1(l) {
f$2(l);
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) {
for (var i$$1 = 0, arr2 = new Array(arr.length); i$$1 < arr.length; i$$1++) {
arr2[i$$1] = arr[i$$1];
}
return arr2;
}
}
var arrayWithoutHoles = _arrayWithoutHoles;
function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
}
var iterableToArray = _iterableToArray;
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance");
}
var nonIterableSpread = _nonIterableSpread;
function _toConsumableArray(arr) {
return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
}
var toConsumableArray = _toConsumableArray;
function createCommonjsModule(fn, module) {
return module = {
exports: {}
}, fn(module, module.exports), module.exports;
}
var _typeof_1 = createCommonjsModule(function (module) {
function _typeof2(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof2 = function _typeof2(obj) {
return typeof obj;
};
} else {
_typeof2 = function _typeof2(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof2(obj);
}
function _typeof(obj) {
if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
module.exports = _typeof = function _typeof(obj) {
return _typeof2(obj);
};
} else {
module.exports = _typeof = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
};
}
return _typeof(obj);
}
module.exports = _typeof;
});
var runtime_1 = createCommonjsModule(function (module) {
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var runtime = function (exports) {
var Op = Object.prototype;
var hasOwn = Op.hasOwnProperty;
var undefined; // More compressible than void 0.
var $Symbol = typeof Symbol === "function" ? Symbol : {};
var iteratorSymbol = $Symbol.iterator || "@@iterator";
var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
return obj[key];
}
try {
// IE 8 has a broken Object.defineProperty that only works on DOM objects.
define({}, "");
} catch (err) {
define = function (obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
// If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
var generator = Object.create(protoGenerator.prototype);
var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
// .throw, and .return methods.
generator._invoke = makeInvokeMethod(innerFn, self, context);
return generator;
}
exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
// record like context.tryEntries[i].completion. This interface could
// have been (and was previously) designed to take a closure to be
// invoked without arguments, but in all the cases we care about we
// already have an existing method we want to call, so there's no need
// to create a new function object. We can even get away with assuming
// the method takes exactly one argument, since that happens to be true
// in every case, so we don't have to touch the arguments object. The
// only additional allocation required is the completion record, which
// has a stable shape and so hopefully should be cheap to allocate.
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
var GenStateSuspendedStart = "suspendedStart";
var GenStateSuspendedYield = "suspendedYield";
var GenStateExecuting = "executing";
var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
// breaking out of the dispatch switch statement.
var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
// .constructor.prototype properties for functions that return Generator
// objects. For full spec compliance, you may wish to configure your
// minifier not to mangle the names of these two functions.
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
// don't natively support it.
var IteratorPrototype = {};
IteratorPrototype[iteratorSymbol] = function () {
return this;
};
var getProto = Object.getPrototypeOf;
var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
// This environment has a native %IteratorPrototype%; use it instead
// of the polyfill.
IteratorPrototype = NativeIteratorPrototype;
}
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
GeneratorFunctionPrototype.constructor = GeneratorFunction;
GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
// Iterator interface in terms of a single ._invoke method.
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
exports.isGeneratorFunction = function (genFun) {
var ctor = typeof genFun === "function" && genFun.constructor;
return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
// do is to check its .name property.
(ctor.displayName || ctor.name) === "GeneratorFunction" : false;
};
exports.mark = function (genFun) {
if (Object.setPrototypeOf) {
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
} else {
genFun.__proto__ = GeneratorFunctionPrototype;
define(genFun, toStringTagSymbol, "GeneratorFunction");
}
genFun.prototype = Object.create(Gp);
return genFun;
}; // Within the body of any async function, `await x` is transformed to
// `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
// `hasOwn.call(value, "__await")` to determine if the yielded value is
// meant to be awaited.
exports.awrap = function (arg) {
return {
__await: arg
};
};
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if (record.type === "throw") {
reject(record.arg);
} else {
var result = record.arg;
var value = result.value;
if (value && typeof value === "object" && hasOwn.call(value, "__await")) {
return PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
});
}
return PromiseImpl.resolve(value).then(function (unwrapped) {
// When a yielded Promise is resolved, its final value becomes
// the .value of the Promise<{value,done}> result for the
// current iteration.
result.value = unwrapped;
resolve(result);
}, function (error) {
// If a rejected Promise was yielded, throw the rejection back
// into the async generator function so it can be handled there.
return invoke("throw", error, resolve, reject);
});
}
}
var previousPromise;
function enqueue(method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = // If enqueue has been called before, then we want to wait until
// all previous Promises have been resolved before calling invoke,
// so that results are always delivered in the correct order. If
// enqueue has not been called before, then it is important to
// call invoke immediately, without waiting on a callback to fire,
// so that the async generator function has the opportunity to do
// any necessary setup in a predictable way. This predictability
// is why the Promise constructor synchronously invokes its
// executor callback, and why async functions synchronously
// execute code before the first await. Since we implement simple
// async functions in terms of async generators, it is especially
// important to get this right, even though it requires care.
previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
// invocations of the iterator.
callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
} // Define the unified helper method that is used to implement .next,
// .throw, and .return (see defineIteratorMethods).
this._invoke = enqueue;
}
defineIteratorMethods(AsyncIterator.prototype);
AsyncIterator.prototype[asyncIteratorSymbol] = function () {
return this;
};
exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
// AsyncIterator objects; they just return a Promise for the value of
// the final result produced by the iterator.
exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
if (PromiseImpl === void 0) PromiseImpl = Promise;
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
: iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
};
function makeInvokeMethod(innerFn, self, context) {
var state = GenStateSuspendedStart;
return function invoke(method, arg) {
if (state === GenStateExecuting) {
throw new Error("Generator is already running");
}
if (state === GenStateCompleted) {
if (method === "throw") {
throw arg;
} // Be forgiving, per 25.3.3.3.3 of the spec:
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
return doneResult();
}
context.method = method;
context.arg = arg;
while (true) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if (context.method === "next") {
// Setting context._sent for legacy support of Babel's
// function.sent implementation.
context.sent = context._sent = context.arg;
} else if (context.method === "throw") {
if (state === GenStateSuspendedStart) {
state = GenStateCompleted;
throw context.arg;
}
context.dispatchException(context.arg);
} else if (context.method === "return") {
context.abrupt("return", context.arg);
}
state = GenStateExecuting;
var record = tryCatch(innerFn, self, context);
if (record.type === "normal") {
// If an exception is thrown from innerFn, we leave state ===
// GenStateExecuting and loop back for another invocation.
state = context.done ? GenStateCompleted : GenStateSuspendedYield;
if (record.arg === ContinueSentinel) {
continue;
}
return {
value: record.arg,
done: context.done
};
} else if (record.type === "throw") {
state = GenStateCompleted; // Dispatch the exception by looping back around to the
// context.dispatchException(context.arg) call above.
context.method = "throw";
context.arg = record.arg;
}
}
};
} // Call delegate.iterator[context.method](context.arg) and handle the
// result, either by returning a { value, done } result from the
// delegate iterator, or by modifying context.method and context.arg,
// setting context.delegate to null, and returning the ContinueSentinel.
function maybeInvokeDelegate(delegate, context) {
var method = delegate.iterator[context.method];
if (method === undefined) {
// A .throw or .return when the delegate iterator has no .throw
// method always terminates the yield* loop.
context.delegate = null;
if (context.method === "throw") {
// Note: ["return"] must be used for ES3 parsing compatibility.
if (delegate.iterator["return"]) {
// If the delegate iterator has a return method, give it a
// chance to clean up.
context.method = "return";
context.arg = undefined;
maybeInvokeDelegate(delegate, context);
if (context.method === "throw") {
// If maybeInvokeDelegate(context) changed context.method from
// "return" to "throw", let that override the TypeError below.
return ContinueSentinel;
}
}
context.method = "throw";
context.arg = new TypeError("The iterator does not provide a 'throw' method");
}
return ContinueSentinel;
}
var record = tryCatch(method, delegate.iterator, context.arg);
if (record.type === "throw") {
context.method = "throw";
context.arg = record.arg;
context.delegate = null;
return ContinueSentinel;
}
var info = record.arg;
if (!info) {
context.method = "throw";
context.arg = new TypeError("iterator result is not an object");
context.delegate = null;
return ContinueSentinel;
}
if (info.done) {
// Assign the result of the finished delegate to the temporary
// variable specified by delegate.resultName (see delegateYield).
context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
// exception, let the outer generator proceed normally. If
// context.method was "next", forget context.arg since it has been
// "consumed" by the delegate iterator. If context.method was
// "return", allow the original .return call to continue in the
// outer generator.
if (context.method !== "return") {
context.method = "next";
context.arg = undefined;
}
} else {
// Re-yield the result returned by the delegate method.
return info;
} // The delegate iterator is finished, so forget it and continue with
// the outer generator.
context.delegate = null;
return ContinueSentinel;
} // Define Generator.prototype.{next,throw,return} in terms of the
// unified ._invoke helper method.
defineIteratorMethods(Gp);
define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
// @@iterator function is called on it. Some browsers' implementations of the
// iterator prototype chain incorrectly implement this, causing the Generator
// object to not be returned from this call. This ensures that doesn't happen.
// See https://github.com/facebook/regenerator/issues/274 for more details.
Gp[iteratorSymbol] = function () {
return this;
};
Gp.toString = function () {
return "[object Generator]";
};
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
if (1 in locs) {
entry.catchLoc = locs[1];
}
if (2 in locs) {
entry.finallyLoc = locs[2];
entry.afterLoc = locs[3];
}
this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal";
delete record.arg;
entry.completion = record;
}
function Context(tryLocsList) {
// The root entry object (effectively a try statement without a catch
// or a finally block) gives us a place to store values thrown from
// locations where there is no enclosing try statement.
this.tryEntries = [{
tryLoc: "root"
}];
tryLocsList.forEach(pushTryEntry, this);
this.reset(true);
}
exports.keys = function (object) {
var keys = [];
for (var key in object) {
keys.push(key);
}
keys.reverse(); // Rather than returning an object with a next method, we keep
// things simple and return the next function itself.
return function next() {
while (keys.length) {
var key = keys.pop();
if (key in object) {
next.value = key;
next.done = false;
return next;
}
} // To avoid creating an additional object, we just hang the .value
// and .done properties off the next function object itself. This
// also ensures that the minifier will not anonymize the function.
next.done = true;
return next;
};
};
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) {
return iteratorMethod.call(iterable);
}
if (typeof iterable.next === "function") {
return iterable;
}
if (!isNaN(iterable.length)) {
var i$$1 = -1,
next = function next() {
while (++i$$1 < iterable.length) {
if (hasOwn.call(iterable, i$$1)) {
next.value = iterable[i$$1];
next.done = false;
return next;
}
}
next.value = undefined;
next.done = true;
return next;
};
return next.next = next;
}
} // Return an iterator with no values.
return {
next: doneResult
};
}
exports.values = values;
function doneResult() {
return {
value: undefined,
done: true
};
}
Context.prototype = {
constructor: Context,
reset: function (skipTempReset) {
this.prev = 0;
this.next = 0; // Resetting context._sent for legacy support of Babel's
// function.sent implementation.
this.sent = this._sent = undefined;
this.done = false;
this.delegate = null;
this.method = "next";
this.arg = undefined;
this.tryEntries.forEach(resetTryEntry);
if (!skipTempReset) {
for (var name in this) {
// Not sure about the optimal order of these conditions:
if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
this[name] = undefined;
}
}
}
},
stop: function () {
this.done = true;
var rootEntry = this.tryEntries[0];
var rootRecord = rootEntry.completion;
if (rootRecord.type === "throw") {
throw rootRecord.arg;
}
return this.rval;
},
dispatchException: function (exception) {
if (this.done) {
throw exception;
}
var context = this;
function handle(loc, caught) {
record.type = "throw";
record.arg = exception;
context.next = loc;
if (caught) {
// If the dispatched exception was caught by a catch block,
// then let that catch block handle the exception normally.
context.method = "next";
context.arg = undefined;
}
return !!caught;
}
for (var i$$1 = this.tryEntries.length - 1; i$$1 >= 0; --i$$1) {
var entry = this.tryEntries[i$$1];
var record = entry.completion;
if (entry.tryLoc === "root") {
// Exception thrown outside of any try block that could handle
// it, so set the completion value of the entire function to
// throw the exception.
return handle("end");
}
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc");
var hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
} else if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else if (hasCatch) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
}
} else if (hasFinally) {
if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else {
throw new Error("try statement without catch or finally");
}
}
}
},
abrupt: function (type, arg) {
for (var i$$1 = this.tryEntries.length - 1; i$$1 >= 0; --i$$1) {
var entry = this.tryEntries[i$$1];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
// Ignore the finally entry if control is not jumping to a
// location outside the try/catch block.
finallyEntry = null;
}
var record = finallyEntry ? finallyEntry.completion : {};
record.type = type;
record.arg = arg;
if (finallyEntry) {
this.method = "next";
this.next = finallyEntry.finallyLoc;
return ContinueSentinel;
}
return this.complete(record);
},
complete: function (record, afterLoc) {
if (record.type === "throw") {
throw record.arg;
}
if (record.type === "break" || record.type === "continue") {
this.next = record.arg;
} else if (record.type === "return") {
this.rval = this.arg = record.arg;
this.method = "return";
this.next = "end";
} else if (record.type === "normal" && afterLoc) {
this.next = afterLoc;
}
return ContinueSentinel;
},
finish: function (finallyLoc) {
for (var i$$1 = this.tryEntries.length - 1; i$$1 >= 0; --i$$1) {
var entry = this.tryEntries[i$$1];
if (entry.finallyLoc === finallyLoc) {
this.complete(entry.completion, entry.afterLoc);
resetTryEntry(entry);
return ContinueSentinel;
}
}
},
"catch": function (tryLoc) {
for (var i$$1 = this.tryEntries.length - 1; i$$1 >= 0; --i$$1) {
var entry = this.tryEntries[i$$1];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if (record.type === "throw") {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
} // The context.catch method must only be called with a location
// argument that corresponds to a known catch block.
throw new Error("illegal catch attempt");
},
delegateYield: function (iterable, resultName, nextLoc) {
this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
};
if (this.method === "next") {
// Deliberately forget the last sent value so that we don't
// accidentally pass it on to the delegate.
this.arg = undefined;
}
return ContinueSentinel;
}
}; // Regardless of whether this script is executing as a CommonJS module
// or not, return the runtime object so that we can declare the variable
// regeneratorRuntime in the outer scope, which allows this module to be
// injected easily by `bin/regenerator --include-runtime script.js`.
return exports;
}( // If this script is executing as a CommonJS module, use module.exports
// as the regeneratorRuntime namespace. Otherwise create a new empty
// object. Either way, the resulting object will be used to initialize
// the regeneratorRuntime variable at the top of this file.
module.exports);
try {
regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
// This module should not be running in strict mode, so the above
// assignment should always work unless something is misconfigured. Just
// in case runtime.js accidentally runs in strict mode, we can escape
// strict mode using a global Function call. This could conceivably fail
// if a Content Security Policy forbids using Function, but in that case
// the proper solution is to fix the accidental strict mode problem. If
// you've misconfigured your bundler to force strict mode and applied a
// CSP to forbid Function, and you're not willing to fix either of those
// problems, please detail your unique predicament in a GitHub issue.
Function("r", "regeneratorRuntime = r")(runtime);
}
});
var regenerator = runtime_1;
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
var asyncToGenerator = _asyncToGenerator;
function _defineProperty$1(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var defineProperty$1 = _defineProperty$1;
function ownKeys$1(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2$1(target) {
for (var i$$1 = 1; i$$1 < arguments.length; i$$1++) {
var source = arguments[i$$1] != null ? arguments[i$$1] : {};
if (i$$1 % 2) {
ownKeys$1(source, true).forEach(function (key) {
defineProperty$1(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys$1(source).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
var objectSpread2$1 = _objectSpread2$1;
var FUNC = 'function';
var UNDEF = 'undefined';
var REDUCER = 'reducer';
var base = '@@redux/';
var ACTION_INIT = base + 'INIT';
var ACTION_TEST = base + Math.random().toString(36);
var $$observable =
/* #__PURE__ */
function () {
return (typeof Symbol === "undefined" ? "undefined" : _typeof_1(Symbol)) === FUNC && Symbol.observable || '@@observable';
}();
/*
* Creates a Redux store that holds the state tree.
* The only way to change the data in the store is to call `dispatch()` on it.
*
* There should only be a single store in your app. To specify how different
* parts of the state tree respond to actions, you may combine several reducers
* into a single reducer function by using `combineReducers`.
*
* @param {Function} reducer A function that returns the next state tree, given
* the current state tree and the action to handle.
*
* @param {any} [preloadedState] The initial state. You may optionally specify it
* to hydrate the state from the server in universal apps, or to restore a
* previously serialized user session.
* If you use `combineReducers` to produce the root reducer function, this must be
* an object with the same shape as `combineReducers` keys.
*
* @param {Function} [enhancer] The store enhancer. You may optionally specify it
* to enhance the store with third-party capabilities such as middleware,
* time travel, persistence, etc. The only store enhancer that ships with Redux
* is `applyMiddleware()`.
*
* @returns {Store} A Redux store that lets you read the state, dispatch actions
* and subscribe to changes.
*/
var msg = ' != ' + FUNC;
function createStore(reducer, preloadedState, enhancer) {
if (_typeof_1(preloadedState) === FUNC && _typeof_1(enhancer) === UNDEF) {
enhancer = preloadedState;
preloadedState = undefined;
}
if (_typeof_1(enhancer) !== UNDEF) {
if (_typeof_1(enhancer) !== FUNC) {
throw new Error('enhancer' + msg);
}
return enhancer(createStore)(reducer, preloadedState);
}
if (_typeof_1(reducer) !== FUNC) {
throw new Error(REDUCER + msg);
}
var currentReducer = reducer;
var currentState = preloadedState;
var currentListeners = [];
var nextListeners = currentListeners;
var isDispatching = false;
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice();
}
}
/*
* Reads the state tree managed by the store.
*
* @returns {any} The current state tree of your application.
*/
function getState() {
return currentState;
}
/*
* Adds a change listener. It will be called any time an action is dispatched,
* and some part of the state tree may potentially have changed. You may then
* call `getState()` to read the current state tree inside the callback.
*
* You may call `dispatch()` from a change listener, with the following
* caveats:
*
* 1. The subscriptions are snapshotted just before every `dispatch()` call.
* If you subscribe or unsubscribe while the listeners are being invoked, this
* will not have any effect on the `dispatch()` that is currently in progress.
* However, the next `dispatch()` call, whether nested or not, will use a more
* recent snapshot of the subscription list.
*
* 2. The listener should not expect to see all state changes, as the state
* might have been updated multiple times during a nested `dispatch()` before
* the listener is called. It is, however, guaranteed that all subscribers
* registered before the `dispatch()` started will be called with the latest
* state by the time it exits.
*
* @param {Function} listener A callback to be invoked on every dispatch.
* @returns {Function} A function to remove this change listener.
*/
function subscribe(listener) {
if (_typeof_1(listener) !== FUNC) {
throw new Error('Listener' + msg);
}
var isSubscribed = true;
ensureCanMutateNextListeners();
nextListeners.push(listener);
return function unsubscribe() {
if (!isSubscribed) {
return;
}
isSubscribed = false;
ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
};
}
/**
* Dispatches an action. It is the only way to trigger a state change.
*
* The `reducer` function, used to create the store, will be called with the
* current state tree and the given `action`. Its return value will
* be considered the **next** state of the tree, and the change listeners
* will be notified.
*
* The base implementation only supports plain object actions. If you want to
* dispatch a Promise, an Observable, a thunk, or something else, you need to
* wrap your store creating function into the corresponding middleware. For
* example, see the documentation for the `redux-thunk` package. Even the
* middleware will eventually dispatch plain object actions using this method.
*
* @param {Object} action A plain object representing “what changed”. It is
* a good idea to keep actions serializable so you can record and replay user
* sessions, or use the time travelling `redux-devtools`. An action must have
* a `type` property which may not be `undefined`. It is a good idea to use
* string constants for action types.
*
* @returns {Object} For convenience, the same action object you dispatched.
*
* Note that, if you use a custom middleware, it may wrap `dispatch()` to
* return something else (for example, a Promise you can await).
*/
function dispatch(action) {
/* // add default info to actions...
console.log('dispatch before', _action)
const action = {
..._action,
...{
action: {
..._action.action,
...{ customInfo: 'yoooo'}
}
}
}
console.log('dispatch after', action)
/** */
if (!l(action)) {
throw new Error('Act != obj');
}
if (_typeof_1(action.type) === UNDEF) {
throw new Error('ActType ' + UNDEF);
}
if (isDispatching) {
throw new Error('Dispatch in ' + REDUCER);
}
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}
var listeners = currentListeners = nextListeners;
for (var i$$1 = 0; i$$1 < listeners.length; i$$1++) {
var listener = listeners[i$$1];
listener();
}
return action;
}
/**
* Replaces the reducer currently used by the store to calculate the state.
*
* You might need this if your app implements code splitting and you want to
* load some of the reducers dynamically. You might also need this if you
* implement a hot reloading mechanism for Redux.
*
* @param {Function} nextReducer The reducer for the store to use instead.
* @returns {void}
*/
function replaceReducer(nextReducer) {
if (_typeof_1(nextReducer) !== FUNC) {
throw new Error('next ' + REDUCER + msg);
}
currentReducer = nextReducer;
dispatch({
type: ACTION_INIT
});
}
/**
* Interoperability point for observable/reactive libraries.
* @returns {observable} A minimal observable of state changes.
* For more information, see the observable proposal:
* https://github.com/tc39/proposal-observable
*/
function observable() {
var outerSubscribe = subscribe;
return defineProperty$1({
/*
* The minimal observable subscription method.
* @param {Object} observer Any object that can be used as an observer.
* The observer object should have a `next` method.
* @returns {subscription} An object with an `unsubscribe` method that can
* be used to unsubscribe the observable from the store, and prevent further
* emission of values from the observable.
*/
subscribe: function subscribe(observer) {
if (_typeof_1(observer) !== 'object') {
throw new TypeError('Observer != obj');
}
function observeState() {
if (observer.next) {
observer.next(getState());
}
}
observeState();
var unsubscribe = outerSubscribe(observeState);
return {
unsubscribe: unsubscribe
};
}
}, $$observable, function () {
return this;
});
} // When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
dispatch({
type: ACTION_INIT
});
return defineProperty$1({
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}, $$observable, observable);
}
function getUndefinedStateErrorMessage(key, action) {
var actionType = action && action.type;
var actionName = actionType && actionType.toString() || '?';
return 'action ' + actionName + REDUCER + ' ' + key + ' returns ' + UNDEF;
}
function assertReducerShape(reducers) {
Object.keys(reducers).forEach(function (key) {
var reducer = reducers[key];
var initialState = reducer(undefined, {
type: ACTION_INIT
});
if (_typeof_1(initialState) === UNDEF || _typeof_1(reducer(undefined, {
type: ACTION_TEST
})) === UNDEF) {
throw new Error(REDUCER + ' ' + key + ' ' + UNDEF);
}
});
}
/**
* Turns an object whose values are different reducer functions, into a single
* reducer function. It will call every child reducer, and gather their results
* into a single state object, whose keys correspond to the keys of the passed
* reducer functions.
*
* @param {Object} reducers An object whose values correspond to different
* reducer functions that need to be combined into one. One handy way to obtain
* it is to use ES6 `import * as reducers` syntax. The reducers may never return
* undefined for any action. Instead, they should return their initial state
* if the state passed to them was undefined, and the current state for any
* unrecognized action.
*
* @returns {Function} A reducer function that invokes every reducer inside the
* passed object, and builds a state object with the same shape.
*/
function combineReducers(reducers) {
var reducerKeys = Object.keys(reducers);
var finalReducers = {};
for (var i$$1 = 0; i$$1 < reducerKeys.length; i$$1++) {
var key = reducerKeys[i$$1];
if (_typeof_1(reducers[key]) === FUNC) {
finalReducers[key] = reducers[key];
}
}
var finalReducerKeys = Object.keys(finalReducers);
var shapeAssertionError;
try {
assertReducerShape(finalReducers);
} catch (e$$1) {
shapeAssertionError = e$$1;
}
return function combination() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var action = arguments.length > 1 ? arguments[1] : undefined;
if (shapeAssertionError) {
throw shapeAssertionError;
}
var hasChanged = false;
var nextState = {};
for (var _i = 0; _i < finalReducerKeys.length; _i++) {
var _key = finalReducerKeys[_i];
var reducer = finalReducers[_key];
var previousStateForKey = state[_key];
var nextStateForKey = reducer(previousStateForKey, action);
if (_typeof_1(nextStateForKey) === UNDEF) {
var errorMessage = getUndefinedStateErrorMessage(_key, action);
throw new Error(errorMessage);
}
nextState[_key] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
return hasChanged ? nextState : state;
};
}
function compose() {
for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
if (funcs.length === 0) {
return function (arg) {
return arg;
};
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(function (a$$1, b$$1) {
return function () {
return a$$1(b$$1.apply(void 0, arguments));
};
});
}
/**
* Creates a store enhancer that applies middleware to the dispatch method
* of the Redux store. This is handy for a variety of tasks, such as expressing
* asynchronous actions in a concise manner, or logging every action payload.
*
* See `redux-thunk` package as an example of the Redux middleware.
*
* Because middleware is potentially asynchronous, this should be the first
* store enhancer in the composition chain.
*
* Note that each middleware will be given the `dispatch` and `getState` functions
* as named arguments.
*
* @param {...Function} middlewares The middleware chain to be applied.
* @returns {Function} A store enhancer applying the middleware.
*/
function applyMiddleware() {
for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {
middlewares[_key] = arguments[_key];
}
return function (createStore) {
return function (reducer, preloadedState, enhancer) {
var store = createStore(reducer, preloadedState, enhancer);
var _dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch(action) {
return _dispatch(action);
}
};
chain = middlewares.map(function (middleware) {
return middleware(middlewareAPI);
});
_dispatch = compose.apply(void 0, toConsumableArray(chain))(store.dispatch);
return objectSpread2$1(objectSpread2$1({}, store), {}, {
dispatch: _dispatch
});
};
};
}
var LIBRARY_NAME = 'analytics';
var ID = 'userId';
var ANONID = 'anonymousId';
var ERROR_URL = 'https://lytics.dev/errors/';
var PREFIX = '__';
/**
* Anonymous visitor Id localstorage key
* @typedef {String} ANON_ID
*/
var ANON_ID = PREFIX + 'anon_id'; // __anon_id
/**
* Visitor Id localstorage key
* @typedef {String} USER_ID
*/
var USER_ID = PREFIX + 'user_id'; // __user_id
/**
* Visitor traits localstorage key
* @typedef {String} USER_TRAITS
*/
var USER_TRAITS = PREFIX + 'user_traits'; // __user_traits
var constants =
/*#__PURE__*/
Object.freeze({
ANON_ID: ANON_ID,
USER_ID: USER_ID,
USER_TRAITS: USER_TRAITS
});
var coreEvents = [
/**
* `bootstrap` - Fires when analytics library starts up.
* This is the first event fired. '.on/once' listeners are not allowed on bootstrap
* Plugins can attach logic to this event
*/
'bootstrap',
/**
* `params` - Fires when analytics parses URL parameters
*/
'params',
/**
* `campaign` - Fires if params contain "utm" parameters
*/
'campaign',
/**
* `initializeStart` - Fires before 'initialize', allows for plugins to cancel loading of other plugins
*/
'initializeStart',
/**
* `initialize` - Fires when analytics loads plugins
*/
'initialize',
/**
* `initializeEnd` - Fires after initialize, allows for plugins to run logic after initialization methods run
*/
'initializeEnd',
/**
* `ready` - Fires when all analytic providers are fully loaded. This waits for 'initialize' and 'loaded' to return true
*/
'ready',
/**
* `resetStart` - Fires if analytic.reset() is called.
* Use this event to cancel reset based on a specific condition
*/
'resetStart',
/**
* `reset` - Fires if analytic.reset() is called.
* Use this event to run custom cleanup logic (if needed)
*/
'reset',
/**
* `resetEnd` - Fires after analytic.reset() is called.
* Use this event to run a callback after user data is reset
*/
'resetEnd',
/******************
* Page Events
******************/
/**
* `pageStart` - Fires before 'page' events fire.
* This allows for dynamic page view cancellation based on current state of user or options passed in.
*/
'pageStart',
/**
* `page` - Core analytics hook for page views.
* If your plugin or integration tracks page views, this is the event to fire on.
*/
'page',
/**
* `pageEnd` - Fires after all registered 'page' methods fire.
*/
'pageEnd',
/**
* `pageAborted` - Fires if 'page' call is cancelled by a plugin
*/
'pageAborted',
/****************
* Track Events
***************/
/**
* `trackStart` - Called before the 'track' events fires.
* This allows for dynamic page view cancellation based on current state of user or options passed in.
*/
'trackStart',
/**
* `track` - Core analytics hook for event tracking.
* If your plugin or integration tracks custom events, this is the event to fire on.
*/
'track',
/**
* `trackEnd` - Fires after all registered 'track' events fire from plugins.
*/
'trackEnd',
/**
* `trackAborted` - Fires if 'track' call is cancelled by a plugin
*/
'trackAborted',
/******************
* Identify Events
******************/
/**
* `identifyStart` - Called before the 'identify' events fires.
* This allows for dynamic page view cancellation based on current state of user or options passed in.
*/
'identifyStart',
/**
* `identify` - Core analytics hook for user identification.
* If your plugin or integration identifies users or user traits, this is the event to fire on.
*/
'identify',
/**
* `identifyEnd` - Fires after all registered 'identify' events fire from plugins.
*/
'identifyEnd',
/**
* `identifyAborted` - Fires if 'track' call is cancelled by a plugin
*/
'identifyAborted',
/**
* `userIdChanged` - Fires when a user id is updated
*/
'userIdChanged',
/******************
* Plugin Events
******************/
/**
* `registerPlugins` - Fires when analytics is registering plugins
*/
'registerPlugins',
/**
* `enablePlugin` - Fires when 'analytics.plugins.enable()' is called
*/
'enablePlugin',
/**
* `disablePlugin` - Fires when 'analytics.plugins.disable()' is called
*/
'disablePlugin',
/*
* `loadPlugin` - Fires when 'analytics.loadPlugin()' is called
*/
// 'loadPlugin',
/******************
* Browser activity events
******************/
/**
* `online` - Fires when browser network goes online.
* This fires only when coming back online from an offline state.
*/
'online',
/**
* `offline` - Fires when browser network goes offline.
*/
'offline',
/******************
* Storage events
******************/
/**
* `setItemStart` - Fires when analytics.storage.setItem is initialized.
* This event gives plugins the ability to intercept keys & values and alter them before they are persisted.
*/
'setItemStart',
/**
* `setItem` - Fires when analytics.storage.setItem is called.
* This event gives plugins the ability to intercept keys & values and alter them before they are persisted.
*/
'setItem',
/**
* `setItemEnd` - Fires when setItem storage is complete.
*/
'setItemEnd',
/**
* `setItemAborted` - Fires when setItem storage is cancelled by a plugin.
*/
'setItemAborted',
/**
* `removeItemStart` - Fires when analytics.storage.removeItem is initialized.
* This event gives plugins the ability to intercept removeItem calls and abort / alter them.
*/
'removeItemStart',
/**
* `removeItem` - Fires when analytics.storage.removeItem is called.
* This event gives plugins the ability to intercept removeItem calls and abort / alter them.
*/
'removeItem',
/**
* `removeItemEnd` - Fires when removeItem storage is complete.
*/
'removeItemEnd',
/**
* `removeItemAborted` - Fires when removeItem storage is cancelled by a plugin.
*/
'removeItemAborted'];
/* Keys on a plugin that are not considered events */
var nonEvents = ['name', 'EVENTS', 'config', 'loaded'];
var pluginEvents = {
registerPluginType: function registerPluginType(name) {
return "registerPlugin:".concat(name);
},
pluginReadyType: function pluginReadyType(name) {
return "ready:".concat(name);
}
};
var EVENTS = coreEvents.reduce(function (acc, curr) {
acc[curr] = curr;
return acc;
}, pluginEvents);
function isReservedAction(type) {
return coreEvents.includes(type);
}
var utmRegex = /^utm_/;
var propRegex = /^an_prop_/;
var traitRegex = /^an_trait_/; // Middleware runs during EVENTS.initialize
function initializeMiddleware(instance) {
var setItem = instance.storage.setItem;
return function (store) {
return function (next) {
return function (action) {
/* Handle bootstrap event */
if (action.type === EVENTS.bootstrap) {
var params = action.params,
user = action.user,
persistedUser = action.persistedUser,
initialUser = action.initialUser;
var isKnownId = persistedUser.userId === user.userId;
/* 1. Set anonymous ID */
if (persistedUser.anonymousId !== user.anonymousId) {
setItem(ANON_ID, user.anonymousId);
}
/* 2. Set userId */
if (!isKnownId) {
setItem(USER_ID, user.userId);
}
/* 3. Set traits if they are different */
if (initialUser.traits) {
setItem(USER_TRAITS, objectSpread2$1(objectSpread2$1({}, isKnownId && persistedUser.traits ? persistedUser.traits : {}), initialUser.traits));
/* TODO multi user setup
setItem(`${USER_TRAITS}.${user.userId}`, {
...(isKnownId) ? existingTraits : {},
...initialUser.traits
})
*/
}
/* 4. Parse url params */
var paramsArray = Object.keys(action.params);
if (paramsArray.length) {
var an_uid = params.an_uid,
an_event = params.an_event;
var groupedParams = paramsArray.reduce(function (acc, key) {
// match utm params & dclid (display) & gclid (cpc)
if (key.match(utmRegex) || key.match(/^(d|g)clid/)) {
var cleanName = key.replace(utmRegex, '');
var keyName = cleanName === 'campaign' ? 'name' : cleanName;
acc.campaign[keyName] = params[key];
}
if (key.match(propRegex)) {
acc.props[key.replace(propRegex, '')] = params[key];
}
if (key.match(traitRegex)) {
acc.traits[key.replace(traitRegex, '')] = params[key];
}
return acc;
}, {
campaign: {},
props: {},
traits: {}
});
store.dispatch(objectSpread2$1(objectSpread2$1({
type: EVENTS.params,
raw: params
}, groupedParams), an_uid ? {
userId: an_uid
} : {}));
/* If userId set, call identify */
if (an_uid) {
// timeout to debounce and make sure integration is registered. Todo refactor
setTimeout(function () {
return instance.identify(an_uid, groupedParams.traits);
}, 0);
}
/* If tracking event set, call track */
if (an_event) {
// timeout to debounce and make sure integration is registered. Todo refactor
setTimeout(function () {
return instance.track(an_event, groupedParams.props);
}, 0);
} // if url has utm params
if (Object.keys(groupedParams.campaign).length) {
store.dispatch({
type: EVENTS.campaign,
campaign: groupedParams.campaign
});
}
}
}
return next(action);
};
};
};
}
/* user reducer */
function userReducer(storage) {
return function user() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (action.type === EVENTS.setItemEnd) {
// Set anonymousId if changed by storage.setItem
if (action.key === ANON_ID) {
return objectSpread2$1(objectSpread2$1({}, state), {
anonymousId: action.value
});
} // Set userId if changed by storage.setItem
if (action.key === USER_ID) {
return objectSpread2$1(objectSpread2$1({}, state), {
userId: action.value
});
}
}
switch (action.type) {
case EVENTS.identify:
return Object.assign({}, state, {
userId: action.userId,
traits: objectSpread2$1(objectSpread2$1({}, state.traits), action.traits)
});
case EVENTS.reset:
// Side effect to fix race condition in Node. TODO refactor
// This is from default storage.removeItem: (key) => globalContext[key] = undefined
[USER_ID, ANON_ID, USER_TRAITS].forEach(function (key) {
// sync storage, not instance.storage
storage.removeItem(key);
});
return Object.assign({}, state, {
userId: null,
// TODO reset anon id automatically?
anonymousId: null,
traits: {}
});
default:
return state;
}
};
}
function getPersistedUserData(storage) {
return {
userId: storage.getItem(USER_ID),
anonymousId: storage.getItem(ANON_ID),
traits: storage.getItem(USER_TRAITS)
};
}
var tempKey = function tempKey(key) {
return PREFIX + 'TEMP' + PREFIX + key;
};
function getUserPropFunc(storage) {
return function getUserProp(key, instance, payload) {
/* 1. Try current state */
var currentId = instance.getState('user')[key];
if (currentId) {
/*
console.log(`from state ${key}`, currentId)
/** */
return currentId;
}
/* 2. Try event payload */
if (payload && l(payload) && payload[key]) {
/*
console.log(`from payload ${key}`, payload[key])
/** */
return payload[key];
}
/* 3. Try persisted data */
var persistedInfo = getPersistedUserData(storage)[key];
if (persistedInfo) {
/*
console.log(`from persistedInfo ${key}`, persistedInfo)
/** */
return persistedInfo;
}
/* 4. Else, try to get in memory placeholder. TODO watch this for future issues */
return o$2(tempKey(key)) || null;
};
}
function identifyMiddleware(instance) {
var _instance$storage = instance.storage,
setItem = _instance$storage.setItem,
removeItem = _instance$storage.removeItem,
getItem = _instance$storage.getItem;
return function (store) {
return function (next) {
return function (action) {
var userId = action.userId,
traits = action.traits,
options = action.options;
/* Reset user id and traits */
if (action.type === EVENTS.reset) {
// Remove stored data
[USER_ID, USER_TRAITS, ANON_ID].forEach(function (key) {
// Fires async removeItem dispatch
removeItem(key);
});
[ID, ANONID, 'traits'].forEach(function (key) {
// Remove from global context
n$1(tempKey(key));
});
}
if (action.type === EVENTS.identify) {
/* If no anon id. Set it! */
if (!getItem(ANON_ID)) {
setItem(ANON_ID, y$1());
}
var currentId = getItem(USER_ID);
var currentTraits = getItem(USER_TRAITS) || {};
if (currentId && currentId !== userId) {
store.dispatch({
type: EVENTS.userIdChanged,
old: {
userId: currentId,
traits: currentTraits
},
"new": {
userId: userId,
traits: traits
},
options: options
});
}
/* Save user id */
if (userId) {
setItem(USER_ID, userId);
}
/* Save user traits */
if (traits) {
setItem(USER_TRAITS, objectSpread2$1(objectSpread2$1({}, currentTraits), traits));
}
}
return next(action);
};
};
};
}
var stack = {};
function runCallback(id, payload) {
if (stack[id] && c(stack[id])) {
// console.log(`run ${id}`)
stack[id](payload);
delete stack[id];
}
}
function waitForReady(data, predicate, timeout) {
return new Promise(function (resolve, reject) {
if (predicate()) {
return resolve(data);
} // Timeout. Add to queue
if (timeout < 1) {
return reject(objectSpread2$1(objectSpread2$1({}, data), {}, {
queue: true
})); // eslint-disable-line
} // Else recursive retry
return pause(10).then(function (_) {
return waitForReady(data, predicate, timeout - 10).then(resolve, reject);
});
});
}
function pause(ms) {
return new Promise(function (resolve) {
return setTimeout(resolve, ms);
});
}
function processQueue(store, getPlugins, instance) {
var pluginMethods = getPlugins();
var _store$getState = store.getState(),
plugins = _store$getState.plugins,
context = _store$getState.context,
queue = _store$getState.queue,
user = _store$getState.user;
var isOnline = !context.offline;
/* If network connection found and there is items in queue, process them all */
if (isOnline && queue && queue.actions && queue.actions.length) {
var pipeline = queue.actions.reduce(function (acc, item, index) {
var isLoaded = plugins[item.plugin].loaded;
if (isLoaded) {
acc.process.push(item);
acc.processIndex.push(index);
} else {
acc.requeue.push(item);
acc.requeueIndex.push(index);
}
return acc;
}, {
processIndex: [],
process: [],
requeue: [],
requeueIndex: []
});
if (pipeline.processIndex && pipeline.processIndex.length) {
pipeline.processIndex.forEach(function (i$$1) {
var processAction = queue.actions[i$$1]; // console.log('RePROCESS THIS>', processAction)
// Call methods directly right now
var currentPlugin = processAction.plugin;
var currentMethod = processAction.payload.type;
var method = pluginMethods[currentPlugin][currentMethod];
if (method && c(method)) {
/* enrich queued payload with userId / anon id if missing */
/* TODO hoist enrich into where action queued? */
// console.log('before', processAction.payload)
var enrichedPayload = enrich(processAction.payload, user); // console.log('user.userId', user.userId)
// console.log('user.anonymousId', user.anonymousId)
// console.log('after enrich', enrichedPayload)
method({
payload: enrichedPayload,
config: plugins[currentPlugin].config,
instance: instance
});
/* Then redispatch for .on listeners / other middleware */
var pluginEvent = "".concat(currentMethod, ":").concat(currentPlugin);
store.dispatch(objectSpread2$1(objectSpread2$1({}, enrichedPayload), {}, {
type: pluginEvent,
/* Internal data for analytics engine */
_: {
called: pluginEvent,
from: 'queueDrain'
}
}));
}
});
/* Removed processed actions */
var reQueueActions = queue.actions.filter(function (value, index) {
// note !~ === return pipeline.processIndex.indexOf(index) === -1
return !~pipeline.processIndex.indexOf(index);
});
/* Set queue actions. TODO refactor to non mutatable or move out of redux */
queue.actions = reQueueActions;
}
}
}
function enrich() {
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var user = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return [ID, ANONID].reduce(function (acc, key) {
if (payload.hasOwnProperty(key) && user[key] && user[key] !== payload[key]) {
// console.log(`${key} stale update with ${user[key]}`)
acc[key] = user[key];
}
return acc;
}, payload);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
var arrayWithHoles = _arrayWithHoles;
function _iterableToArrayLimit(arr, i$$1) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i$$1 && _arr.length === i$$1) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
var iterableToArrayLimit = _iterableToArrayLimit;
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
var nonIterableRest = _nonIterableRest;
function _slicedToArray(arr, i$$1) {
return arrayWithHoles(arr) || iterableToArrayLimit(arr, i$$1) || nonIterableRest();
}
var slicedToArray = _slicedToArray;
function fitlerDisabledPlugins(allPlugins) {
var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return Object.keys(allPlugins).filter(function (name) {
var fromCallOptions = options.plugins || {}; // If enabled/disabled by options. Override settings
if (y(fromCallOptions[name])) {
return fromCallOptions[name];
} // If all: false disable everything unless true explicitly set
if (fromCallOptions.all === false) {
return false;
} // else use state.plugin settings
if (settings[name] && settings[name].enabled === false) {
return false;
}
return true;
}).map(function (name) {
return allPlugins[name];
});
}
var endsWithStartRegex = /Start$/;
var bootstrapRegex = /^bootstrap/;
var readyRegex = /^ready/;
function runPlugins(_x, _x2, _x3, _x4, _x5) {
return _ref.apply(this, arguments);
}
/**
* Async reduce over matched plugin methods
* Fires plugin functions
*/
function _ref() {
_ref = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee(action, getPlugins, instance, store, eventsInfo) {
var pluginObject, originalType, updatedType, state, activePlugins, allActivePluginKeys, allMatches, actionBefore, actionDuring, afterName, actionAfter;
return regenerator.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
pluginObject = c(getPlugins) ? getPlugins() : getPlugins;
originalType = action.type;
updatedType = originalType.replace(endsWithStartRegex, '');
/* If action already dispatched exit early. This makes it so plugin methods are not fired twice. */
if (!(action._ && action._.called)) {
_context.next = 5;
break;
}
return _context.abrupt("return", action);
case 5:
state = instance.getState();
/* Remove plugins that are disabled by options or by settings */
activePlugins = fitlerDisabledPlugins(pluginObject, state.plugins, action.options);
/* If analytics.plugin.enable calls do special behavior */
if (originalType === EVENTS.initializeStart && action.fromEnable) {
// Return list of all enabled plugins that have NOT been initialized yet
activePlugins = Object.keys(state.plugins).filter(function (name) {
var info = state.plugins[name];
return action.plugins.includes(name) && !info.initialized;
}).map(function (name) {
return pluginObject[name];
});
} // console.log(`engine activePlugins ${action.type}`, activePlugins)
allActivePluginKeys = activePlugins.map(function (p$$1) {
return p$$1.name;
}); // console.log('allActivePluginKeys', allActivePluginKeys)
allMatches = getAllMatchingCalls(originalType, activePlugins, pluginObject); // console.log('allMatches', allMatches)
/* @TODO cache matches and purge on enable/disable/add plugin */
/**
* Process all 'actionBefore' hooks
* Example:
* This is processes 'pageStart' methods from plugins and update the event to send through the chain
*/
_context.next = 12;
return processEvent({
action: action,
data: {
exact: allMatches.before,
namespaced: allMatches.beforeNS
},
state: state,
allPlugins: pluginObject,
allMatches: allMatches,
instance: instance,
store: store,
EVENTS: eventsInfo
});
case 12:
actionBefore = _context.sent;
if (!shouldAbortAll(actionBefore, allActivePluginKeys.length)) {
_context.next = 15;
break;
}
return _context.abrupt("return", actionBefore);
case 15:
if (!(originalType === updatedType)) {
_context.next = 19;
break;
}
/* If type the same don't double process */
actionDuring = actionBefore;
_context.next = 22;
break;
case 19:
_context.next = 21;
return processEvent({
action: objectSpread2$1(objectSpread2$1({}, actionBefore), {}, {
type: updatedType
}),
data: {
exact: allMatches.during,
namespaced: allMatches.duringNS
},
state: state,
allPlugins: pluginObject,
allMatches: allMatches,
instance: instance,
store: store,
EVENTS: eventsInfo
});
case 21:
actionDuring = _context.sent;
case 22:
if (!originalType.match(endsWithStartRegex)) {
_context.next = 28;
break;
}
afterName = "".concat(updatedType, "End");
_context.next = 26;
return processEvent({
action: objectSpread2$1(objectSpread2$1({}, actionDuring), {}, {
type: afterName
}),
data: {
exact: allMatches.after,
namespaced: allMatches.afterNS
},
state: state,
allPlugins: pluginObject,
allMatches: allMatches,
instance: instance,
store: store,
EVENTS: eventsInfo
});
case 26:
actionAfter = _context.sent; // console.log('____ actionAfter', actionAfter)
/* Fire callback if supplied */
if (actionAfter.meta && actionAfter.meta.hasCallback) {
/*
console.log('End of engine action has callback')
console.log(actionAfter.meta)
console.log('stack', stack)
/** */
// @TODO figure out exact args calls and .on will get
runCallback(actionAfter.meta.rid, {
payload: actionAfter
});
}
case 28:
return _context.abrupt("return", actionBefore);
case 29:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _ref.apply(this, arguments);
}
function processEvent(_x6) {
return _processEvent.apply(this, arguments);
}
function _processEvent() {
_processEvent = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee5(_ref2) {
var data, action, instance, state, allPlugins, allMatches, store, EVENTS$$1, plugins, context, method, isStartEvent, abortable, makeArgs, queueData, payloads, resolvedAction, endAction;
return regenerator.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
data = _ref2.data, action = _ref2.action, instance = _ref2.instance, state = _ref2.state, allPlugins = _ref2.allPlugins, allMatches = _ref2.allMatches, store = _ref2.store, EVENTS$$1 = _ref2.EVENTS;
plugins = state.plugins, context = state.context;
method = action.type;
isStartEvent = method.match(endsWithStartRegex); // console.log(`data ${method}`, data)
// console.log(`data allMatches ${method}`, allMatches)
abortable = data.exact.map(function (x) {
return x.pluginName;
});
/* If abort is called from xyzStart */
if (isStartEvent) {
abortable = allMatches.during.map(function (x) {
return x.pluginName;
});
}
/* make args for functions to concume */
makeArgs = argumentFactory(instance, abortable); // console.log('makeArgs', makeArgs)
/* Check if plugin loaded, if not mark action for queue */
queueData = data.exact.reduce(function (acc, thing) {
var pluginName = thing.pluginName,
methodName = thing.methodName;
var addToQueue = false; // Queue actions if plugin not loaded except for initialize and reset
if (!methodName.match(/^initialize/) && !methodName.match(/^reset/)) {
addToQueue = !plugins[pluginName].loaded;
}
/* If offline and its a core method. Add to queue */
if (context.offline && methodName.match(/^(page|track|identify)/)) {
addToQueue = true;
}
acc["".concat(pluginName)] = addToQueue;
return acc;
}, {});
/* generate plugin specific payloads */
_context5.next = 10;
return data.exact.reduce(
/*#__PURE__*/
function () {
var _ref6 = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee3(scoped, curr, i$$1) {
var pluginName, curScope, scopedPayload;
return regenerator.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
pluginName = curr.pluginName;
_context3.next = 3;
return scoped;
case 3:
curScope = _context3.sent;
if (!(data.namespaced && data.namespaced[pluginName])) {
_context3.next = 11;
break;
}
_context3.next = 7;
return data.namespaced[pluginName].reduce(
/*#__PURE__*/
function () {
var _ref7 = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee2(acc, p$$1, count) {
var curScopeData, genAbort, val, returnValue;
return regenerator.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
genAbort = function _ref8(currentAct, pname, otherPlug) {
return function (reason, plugins) {
var callsite = otherPlug || pname; // console.log(`__abort msg: ${reason}`)
// console.log(`__abort ${pname}`)
// console.log(`__abort xxx: ${plugins}`)
// console.log(`__abort otherPlug`, otherPlug)
return objectSpread2$1(objectSpread2$1({}, currentAct), {}, {
abort: {
reason: reason,
plugins: plugins || [pname],
caller: method,
from: callsite
}
});
};
};
_context2.next = 3;
return acc;
case 3:
curScopeData = _context2.sent;
if (!(!p$$1.method || !c(p$$1.method))) {
_context2.next = 6;
break;
}
return _context2.abrupt("return", curScopeData);
case 6:
/* Make sure plugins don’t call themselves */
validateMethod(p$$1.methodName, p$$1.pluginName);
_context2.next = 9;
return p$$1.method({
payload: curScopeData,
instance: instance,
abort: genAbort(curScopeData, pluginName, p$$1.pluginName),
config: getConfig(p$$1.pluginName, plugins, allPlugins),
plugins: plugins
});
case 9:
val = _context2.sent;
returnValue = l(val) ? val : {};
return _context2.abrupt("return", Promise.resolve(objectSpread2$1(objectSpread2$1({}, curScopeData), returnValue)));
case 12:
case "end":
return _context2.stop();
}
}
}, _callee2);
}));
return function (_x10, _x11, _x12) {
return _ref7.apply(this, arguments);
};
}(), Promise.resolve(action));
case 7:
scopedPayload = _context3.sent;
/* Set scoped payload */
curScope[pluginName] = scopedPayload;
_context3.next = 12;
break;
case 11:
/* Set payload as default action */
curScope[pluginName] = action;
case 12:
return _context3.abrupt("return", Promise.resolve(curScope));
case 13:
case "end":
return _context3.stop();
}
}
}, _callee3);
}));
return function (_x7, _x8, _x9) {
return _ref6.apply(this, arguments);
};
}(), Promise.resolve({}));
case 10:
payloads = _context5.sent;
_context5.next = 13;
return data.exact.reduce(
/*#__PURE__*/
function () {
var _ref9 = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee4(promise, curr, i$$1) {
var lastLoop, pluginName, currentPlugin, currentActionValue, payloadValue, funcArgs, val, returnValue, merged, scopedPayload, nameSpaceEvent, actionDepth, updatedPayload;
return regenerator.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
lastLoop = data.exact.length === i$$1 + 1;
pluginName = curr.pluginName;
currentPlugin = allPlugins[pluginName];
_context4.next = 5;
return promise;
case 5:
currentActionValue = _context4.sent;
payloadValue = payloads[pluginName] ? payloads[pluginName] : {};
/* If eventStart, allow for value merging */
if (isStartEvent) {
payloadValue = currentActionValue;
}
if (!shouldAbort(payloadValue, pluginName)) {
_context4.next = 11;
break;
} // console.log(`> Abort from payload specific "${pluginName}" abort value`, payloadValue)
abortDispatch({
data: payloadValue,
method: method,
instance: instance,
pluginName: pluginName,
store: store
});
return _context4.abrupt("return", Promise.resolve(currentActionValue));
case 11:
if (!shouldAbort(currentActionValue, pluginName)) {
_context4.next = 14;
break;
} // console.log(`> Abort from ${method} abort value`, currentActionValue)
if (lastLoop) {
abortDispatch({
data: currentActionValue,
method: method,
instance: instance,
// pluginName,
store: store
});
}
return _context4.abrupt("return", Promise.resolve(currentActionValue));
case 14:
if (!(queueData.hasOwnProperty(pluginName) && queueData[pluginName] === true)) {
_context4.next = 17;
break;
} // console.log('Queue this instead', pluginName)
store.dispatch({
type: "queue",
plugin: pluginName,
payload: payloadValue,
/* Internal data for analytics engine */
_: {
called: "queue",
from: 'queueMechanism' // for debugging
}
});
return _context4.abrupt("return", Promise.resolve(currentActionValue));
case 17:
/*
const checkForLoaded = () => {
const p = instance.getState('plugins')
return p[currentPlugin.name].loaded
}
// const p = instance.getState('plugins')
console.log(`loaded "${currentPlugin.name}" > ${method}:`, p[currentPlugin.name].loaded)
// await waitForReady(currentPlugin, checkForLoaded, 10000).then((d) => {
// console.log(`Loaded ${method}`, currentPlugin.name)
// }).catch((e) => {
// console.log(`Error ${method} ${currentPlugin.name}`, e)
// // TODO dispatch failure
// })
*/
// @TODO figure out if we want queuing semantics
funcArgs = makeArgs(payloads[pluginName], allPlugins[pluginName]); // console.log(`funcArgs ${method} ${pluginName}`, funcArgs)
/* Run the plugin function */
_context4.next = 20;
return currentPlugin[method]({
// currentPlugin: pluginName,
abort: funcArgs.abort,
// Send in original action value or scope payload
payload: payloadValue,
instance: instance,
config: getConfig(pluginName, plugins, allPlugins),
plugins: plugins
});
case 20:
val = _context4.sent;
returnValue = l(val) ? val : {};
merged = objectSpread2$1(objectSpread2$1({}, currentActionValue), returnValue);
scopedPayload = payloads[pluginName]; // || currentActionValue
if (shouldAbort(scopedPayload, pluginName)) {
// console.log(`>> HANDLE abort ${method} ${pluginName}`)
abortDispatch({
data: scopedPayload,
method: method,
instance: instance,
pluginName: pluginName,
store: store
});
} else {
nameSpaceEvent = "".concat(method, ":").concat(pluginName);
actionDepth = (nameSpaceEvent.match(/:/g) || []).length;
if (actionDepth < 2 && !method.match(bootstrapRegex) && !method.match(readyRegex)) {
updatedPayload = isStartEvent ? merged : payloadValue; // Dispatched for `.on('xyz') listeners.
instance.dispatch(objectSpread2$1(objectSpread2$1({}, updatedPayload), {}, {
type: nameSpaceEvent,
_: {
called: nameSpaceEvent,
from: 'submethod'
}
}));
}
} // console.log('merged', merged)
return _context4.abrupt("return", Promise.resolve(merged));
case 26:
case "end":
return _context4.stop();
}
}
}, _callee4);
}));
return function (_x13, _x14, _x15) {
return _ref9.apply(this, arguments);
};
}(), Promise.resolve(action));
case 13:
resolvedAction = _context5.sent;
if (!(!method.match(endsWithStartRegex) && !method.match(/^registerPlugin/) && // !method.match(/^disablePlugin/) &&
// !method.match(/^enablePlugin/) &&
!method.match(readyRegex) && !method.match(bootstrapRegex) && !method.match(/^params/) && !method.match(/^userIdChanged/))) {
_context5.next = 21;
break;
}
if (EVENTS$$1.plugins.includes(method)) ; // console.log(`Dont dispatch for ${method}`, resolvedAction)
// return resolvedAction
/*
Verify this original action setup.
It's intended to keep actions from double dispatching themselves
*/
if (!(resolvedAction._ && resolvedAction._.originalAction === method)) {
_context5.next = 18;
break;
}
return _context5.abrupt("return", resolvedAction);
case 18:
endAction = objectSpread2$1(objectSpread2$1({}, resolvedAction), {
_: {
originalAction: resolvedAction.type,
called: resolvedAction.type,
from: 'engineEnd'
}
});
/* If all plugins are aborted, dispatch xAborted */
if (shouldAbortAll(resolvedAction, data.exact.length) && !method.match(/End$/)) {
endAction = objectSpread2$1(objectSpread2$1({}, endAction), {
type: resolvedAction.type + 'Aborted'
});
}
store.dispatch(endAction);
case 21:
return _context5.abrupt("return", resolvedAction);
case 22:
case "end":
return _context5.stop();
}
}
}, _callee5);
}));
return _processEvent.apply(this, arguments);
}
function abortDispatch(_ref3) {
var data = _ref3.data,
method = _ref3.method,
instance = _ref3.instance,
pluginName = _ref3.pluginName,
store = _ref3.store;
var postFix = pluginName ? ':' + pluginName : '';
var abortEvent = method + 'Aborted' + postFix;
store.dispatch(objectSpread2$1(objectSpread2$1({}, data), {}, {
type: abortEvent,
_: {
called: abortEvent,
from: 'abort'
}
}));
}
function getConfig(name, pluginState, allPlugins) {
var pluginData = pluginState[name] || allPlugins[name];
if (pluginData && pluginData.config) {
return pluginData.config;
}
return {};
}
function getPluginFunctions(methodName, plugins) {
return plugins.reduce(function (arr, plugin) {
return !plugin[methodName] ? arr : arr.concat({
methodName: methodName,
pluginName: plugin.name,
method: plugin[methodName]
});
}, []);
}
function formatMethod(type) {
return type.replace(endsWithStartRegex, '');
}
/**
* Return array of event names
* @param {String} eventType - original event type
* @param {String} namespace - optional namespace postfix
* @return {array} - type, method, end
*/
function getEventNames(eventType, namespace) {
var method = formatMethod(eventType);
var postFix = namespace ? ":".concat(namespace) : ''; // `typeStart:pluginName`
var type = "".concat(eventType).concat(postFix); // `type:pluginName`
var methodName = "".concat(method).concat(postFix); // `typeEnd:pluginName`
var end = "".concat(method, "End").concat(postFix);
return [type, methodName, end];
}
/* Collect all calls for a given event in the system */
function getAllMatchingCalls(eventType, activePlugins, allPlugins) {
var eventNames = getEventNames(eventType); // console.log('eventNames', eventNames)
// 'eventStart', 'event', & `eventEnd`
var core = eventNames.map(function (word) {
return getPluginFunctions(word, activePlugins);
}); // Gather nameSpaced Events
return activePlugins.reduce(function (acc, plugin) {
var name = plugin.name;
var nameSpacedEvents = getEventNames(eventType, name); // console.log('eventNames namespaced', nameSpacedEvents)
var _nameSpacedEvents$map = nameSpacedEvents.map(function (word) {
return getPluginFunctions(word, activePlugins);
}),
_nameSpacedEvents$map2 = slicedToArray(_nameSpacedEvents$map, 3),
beforeFuncs = _nameSpacedEvents$map2[0],
duringFuncs = _nameSpacedEvents$map2[1],
afterFuncs = _nameSpacedEvents$map2[2];
if (beforeFuncs.length) {
acc.beforeNS[name] = beforeFuncs;
}
if (duringFuncs.length) {
acc.duringNS[name] = duringFuncs;
}
if (afterFuncs.length) {
acc.afterNS[name] = afterFuncs;
}
return acc;
}, {
before: core[0],
beforeNS: {},
during: core[1],
duringNS: {},
after: core[2],
afterNS: {}
});
}
function shouldAbort(_ref4, pluginName) {
var abort = _ref4.abort;
if (!abort) return false;
if (abort === true) return true;
return includes(abort, pluginName) || abort && includes(abort.plugins, pluginName);
}
function shouldAbortAll(_ref5, pluginsCount) {
var abort = _ref5.abort;
if (!abort) return false;
if (abort === true || p(abort)) return true;
var plugins = abort.plugins;
return isArray$1(abort) && abort.length === pluginsCount || isArray$1(plugins) && plugins.length === pluginsCount;
}
function isArray$1(arr) {
return Array.isArray(arr);
}
function includes(arr, name) {
if (!arr || !isArray$1(arr)) return false;
return arr.includes(name);
}
/**
* Generate arguments to pass to plugin methods
* @param {Object} instance - analytics instance
* @param {array} abortablePlugins - plugins that can be cancelled by caller
* @return {*} function to inject plugin params
*/
function argumentFactory(instance, abortablePlugins) {
// console.log('abortablePlugins', abortablePlugins)
return function (action, plugin, otherPlugin) {
var config = plugin.config,
name = plugin.name;
var method = "".concat(name, ".").concat(action.type);
if (otherPlugin) {
method = otherPlugin.event;
}
var abortF = action.type.match(endsWithStartRegex) ? abortFunction(name, method, abortablePlugins, otherPlugin, action) : notAbortableError(action, method);
return {
/* self: plugin, for future maybe */
// clone objects to avoid reassign
payload: formatPayload(action),
instance: instance,
config: config || {},
abort: abortF
};
};
}
function abortFunction(pluginName, method, abortablePlugins, otherPlugin, action) {
return function (reason, plugins) {
var caller = otherPlugin ? otherPlugin.name : pluginName;
var pluginsToAbort = plugins && isArray$1(plugins) ? plugins : abortablePlugins;
if (otherPlugin) {
pluginsToAbort = plugins && isArray$1(plugins) ? plugins : [pluginName];
if (!pluginsToAbort.includes(pluginName) || pluginsToAbort.length !== 1) {
throw new Error("Method ".concat(method, " can only abort ").concat(pluginName, " plugin. ").concat(JSON.stringify(pluginsToAbort), " input valid"));
}
}
return objectSpread2$1(objectSpread2$1({}, action), {}, {
// 🔥 todo verify this merge is ok
abort: {
reason: reason,
plugins: pluginsToAbort,
caller: method,
_: caller
}
});
};
}
function notAbortableError(action, method) {
return function () {
throw new Error(action.type + ' action not cancellable. Remove abort in ' + method);
};
}
/**
* Verify plugin is not calling itself with whatever:myPluginName self refs
*/
function validateMethod(actionName, pluginName) {
var text = getNameSpacedAction(actionName);
var methodCallMatchesPluginNamespace = text && text.name === pluginName;
if (methodCallMatchesPluginNamespace) {
var sub = getNameSpacedAction(text.method);
var subText = sub ? 'or ' + sub.method : '';
throw new Error([pluginName + ' plugin is calling method ' + actionName, 'Plugins cant call self', "Use ".concat(text.method, " ").concat(subText, " in ").concat(pluginName, " plugin insteadof ").concat(actionName)].join('\n'));
}
}
function getNameSpacedAction(event) {
var split = event.match(/(.*):(.*)/);
if (!split) {
return false;
}
return {
method: split[1],
name: split[2]
};
}
function formatPayload(action) {
return Object.keys(action).reduce(function (acc, key) {
// redact type from { payload }
if (key === 'type') {
return acc;
}
if (l(action[key])) {
acc[key] = Object.assign({}, action[key]);
} else {
acc[key] = action[key];
}
return acc;
}, {});
}
/*
function getMatchingMethods(eventType, activePlugins) {
const exact = getPluginFunctions(eventType, activePlugins)
// console.log('exact', exact)
// Gather nameSpaced Events
return activePlugins.reduce((acc, plugin) => {
const { name } = plugin
const clean = getPluginFunctions(`${eventType}:${name}`, activePlugins)
if (clean.length) {
acc.namespaced[name] = clean
}
return acc
}, {
exact: exact,
namespaced: {}
})
}
*/
function pluginMiddleware(instance, getPlugins, systemEvents) {
var isReady = {};
return function (store) {
return function (next) {
return (
/*#__PURE__*/
function () {
var _ref = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee(action) {
var type, abort, plugins, updatedAction, allPlugins, pluginsArray, allRegisteredPlugins, completed, failed, disabled, waitForPluginsToLoad, updated;
return regenerator.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
type = action.type, abort = action.abort, plugins = action.plugins;
updatedAction = action;
if (!abort) {
_context.next = 4;
break;
}
return _context.abrupt("return", next(action));
case 4:
/* Analytics.plugins.enable called, we need to init the plugins */
if (type === EVENTS.enablePlugin) {
store.dispatch({
type: EVENTS.initializeStart,
plugins: plugins,
disabled: [],
fromEnable: true,
meta: action.meta
});
}
if (type === EVENTS.disablePlugin) {
// If cached callback, resolve promise/run callback. debounced to fix race condition
setTimeout(function () {
return runCallback(action.meta.rid, {
payload: action
});
}, 0);
}
/* @TODO implement
if (type === EVENTS.loadPlugin) {
// Rerun initialize calls in plugins
const allPlugins = getPlugins()
const pluginsToLoad = Object.keys(allPlugins).filter((name) => {
return plugins.includes(name)
}).reduce((acc, curr) => {
acc[curr] = allPlugins[curr]
return acc
}, {})
const initializeAction = {
type: EVENTS.initializeStart,
plugins: plugins
}
const updated = await runPlugins(initializeAction, pluginsToLoad, instance, store, systemEvents)
return next(updated)
}
*/
// || type.match(/^initializeAbort:/)
if (type === EVENTS.initializeEnd) {
allPlugins = getPlugins();
pluginsArray = Object.keys(allPlugins);
allRegisteredPlugins = pluginsArray.filter(function (name) {
return plugins.includes(name);
}).map(function (name) {
return allPlugins[name];
});
completed = [];
failed = [];
disabled = action.disabled; // console.log('allRegisteredPlugins', allRegisteredPlugins)
waitForPluginsToLoad = allRegisteredPlugins.map(function (plugin) {
var loaded = plugin.loaded,
name = plugin.name;
/* Plugins will abort trying to load after 10 seconds. 1e4 === 10000 MS */
return waitForReady(plugin, loaded, 1e4).then(function (d$$1) {
if (!isReady[name]) {
// only dispatch namespaced rdy once
store.dispatch({
type: EVENTS.pluginReadyType(name),
// `ready:${name}`
name: name,
events: Object.keys(plugin).filter(function (name) {
return !nonEvents.includes(name);
})
});
isReady[name] = true;
}
completed = completed.concat(name);
return plugin; // It's loaded! run the command
})["catch"](function (e$$1) {
// Timeout Add to queue
// console.log('Error generic waitForReady. Push this to queue', e)
if (e$$1 instanceof Error) {
throw new Error(e$$1);
}
failed = failed.concat(e$$1.name); // Failed to fire, add to queue
return e$$1;
});
});
Promise.all(waitForPluginsToLoad).then(function (calls) {
// setTimeout to ensure runs after 'page'
var payload = {
plugins: completed,
failed: failed,
disabled: disabled
};
setTimeout(function () {
if (pluginsArray.length === waitForPluginsToLoad.length + disabled.length) {
store.dispatch(objectSpread2$1(objectSpread2$1({}, {
type: EVENTS.ready
}), payload));
}
}, 0);
});
}
/* New plugin system */
if (!(type !== EVENTS.bootstrap)) {
_context.next = 13;
break;
}
if (/^ready:([^:]*)$/.test(type)) {
// Immediately flush queue
setTimeout(function () {
return processQueue(store, getPlugins, instance);
}, 0);
}
_context.next = 11;
return runPlugins(action, getPlugins, instance, store, systemEvents);
case 11:
updated = _context.sent;
return _context.abrupt("return", next(updated));
case 13:
return _context.abrupt("return", next(updatedAction));
case 14:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}()
);
};
};
}
function storageMiddleware(storage) {
return function (store) {
return function (next) {
return function (action) {
var type = action.type,
key = action.key,
value = action.value,
options = action.options;
if (type === EVENTS.setItem || type === EVENTS.removeItem) {
if (action.abort) {
return next(action);
} // Run storage set or remove
if (type === EVENTS.setItem) {
storage.setItem(key, value, options);
} else {
storage.removeItem(key, options);
}
}
return next(action);
};
};
};
}
/*
Todo: emit events for keys we care about
window.addEventListener('storage', (event) => console.log(event));
*/
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var classCallCheck = _classCallCheck;
/* Class to fix dynamic middlewares from conflicting with each other
if more than one analytic instance is active */
var DynamicMiddleware = function DynamicMiddleware() {
var _this = this;
classCallCheck(this, DynamicMiddleware);
defineProperty$1(this, "before", []);
defineProperty$1(this, "after", []);
defineProperty$1(this, "addMiddleware", function (middlewares, position) {
_this[position] = _this[position].concat(middlewares);
});
defineProperty$1(this, "removeMiddleware", function (middleware, position) {
var index = _this[position].findIndex(function (d$$1) {
return d$$1 === middleware;
});
if (index === -1) return;
_this[position] = [].concat(toConsumableArray(_this[position].slice(0, index)), toConsumableArray(_this[position].slice(index + 1)));
});
defineProperty$1(this, "dynamicMiddlewares", function (position) {
return function (store) {
return function (next) {
return function (action) {
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch(act) {
return store.dispatch(act);
}
};
var chain = _this[position].map(function (middleware) {
return middleware(middlewareAPI);
});
return compose.apply(void 0, toConsumableArray(chain))(next)(action);
};
};
};
});
};
function createReducer(getPlugins) {
return function plugins() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var action = arguments.length > 1 ? arguments[1] : undefined;
var newState = {};
if (action.type === 'initialize:aborted') {
return state;
}
if (/^registerPlugin:([^:]*)$/.test(action.type)) {
var name = getNameFromEventType(action.type, 'registerPlugin');
var plugin = getPlugins()[name];
if (!plugin || !name) {
return state;
}
var isEnabled = action.enabled;
newState[name] = {
enabled: isEnabled,
/* if no initialization method. Set initialized true */
initialized: isEnabled ? Boolean(!plugin.initialize) : false,
/* If plugin enabled === false, set loaded to false, else check plugin.loaded function */
loaded: isEnabled ? Boolean(plugin.loaded()) : false,
config: plugin.config || {}
};
return objectSpread2$1(objectSpread2$1({}, state), newState);
}
if (/^initialize:([^:]*)$/.test(action.type)) {
var _name = getNameFromEventType(action.type, EVENTS.initialize);
var _plugin = getPlugins()[_name];
if (!_plugin || !_name) {
return state;
}
newState[_name] = objectSpread2$1(objectSpread2$1({}, state[_name]), {
initialized: true,
/* check plugin.loaded function */
loaded: Boolean(_plugin.loaded())
});
return objectSpread2$1(objectSpread2$1({}, state), newState);
}
if (/^ready:([^:]*)$/.test(action.type)) {
// const name = getNameFromEventType(action.type, 'ready')
newState[action.name] = objectSpread2$1(objectSpread2$1({}, state[action.name]), {
loaded: true
});
return objectSpread2$1(objectSpread2$1({}, state), newState);
}
switch (action.type) {
/* case EVENTS.pluginFailed:
// console.log('PLUGIN_FAILED', action.name)
newState[action.name] = {
...state[action.name],
...{ loaded: false }
}
return { ...state, ...newState }
*/
/* When analytics.plugins.disable called */
case EVENTS.disablePlugin:
return objectSpread2$1(objectSpread2$1({}, state), togglePluginStatus(action.plugins, false, state));
/* When analytics.plugins.enable called */
case EVENTS.enablePlugin:
return objectSpread2$1(objectSpread2$1({}, state), togglePluginStatus(action.plugins, true, state));
default:
return state;
}
};
}
function getNameFromEventType(type, baseName) {
return type.substring(baseName.length + 1, type.length);
}
function togglePluginStatus(plugins, status, currentState) {
return plugins.reduce(function (acc, pluginKey) {
acc[pluginKey] = objectSpread2$1(objectSpread2$1({}, currentState[pluginKey]), {
enabled: status
});
return acc;
}, currentState);
}
function serialize(obj) {
try {
return JSON.parse(JSON.stringify(obj));
} catch (err) {}
return obj;
}
var initialState = {
last: {},
history: [] // track reducer
};
function trackReducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments.length > 1 ? arguments[1] : undefined;
var type = action.type,
event = action.event,
properties = action.properties,
options = action.options,
meta = action.meta;
switch (type) {
case EVENTS.track:
var trackEvent = serialize(objectSpread2$1(objectSpread2$1({
event: event,
properties: properties
}, Object.keys(options).length && {
options: options
}), {}, {
meta: meta
}));
return objectSpread2$1(objectSpread2$1({}, state), {
last: trackEvent,
// Todo prevent LARGE arrays https://bit.ly/2MnBwPT
history: state.history.concat(trackEvent)
});
default:
return state;
}
}
/*
TODO figure out if this should live in state...
Queue could be in mermory as well.
But also needs to be persisted to storage
*/
var initialState$1 = {
actions: []
};
function queueReducer() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$1;
var action = arguments.length > 1 ? arguments[1] : undefined;
var type = action.type,
payload = action.payload;
switch (type) {
case 'queue':
var actionChain;
/* prioritize identify in event queue */
if (payload && payload.type && payload.type === EVENTS.identify) {
actionChain = [action].concat(state.actions);
} else {
actionChain = state.actions.concat(action);
}
return objectSpread2$1(objectSpread2$1({}, state), {}, {
actions: actionChain
});
case 'dequeue':
return [];
// todo push events to history
default:
return state;
}
}
var hashRegex = /#.*$/;
function canonicalUrl() {
if (!i) return;
var tags = document.getElementsByTagName('link');
for (var i$$1 = 0, tag; tag = tags[i$$1]; i$$1++) {
if (tag.getAttribute('rel') === 'canonical') {
return tag.getAttribute('href');
}
}
}
function urlPath(url) {
var regex = /(http[s]?:\/\/)?([^\/\s]+\/)(.*)/g;
var matches = regex.exec(url);
var pathMatch = matches && matches[3] ? matches[3].split('?')[0].replace(hashRegex, '') : '';
return '/' + pathMatch;
}
/**
* Return the canonical URL and rmove the hash.
* @param {string} search - search param
* @return {string} return current canonical URL
*/
function currentUrl(search) {
var canonical = canonicalUrl();
if (!canonical) return window.location.href.replace(hashRegex, '');
return canonical.match(/\?/) ? canonical : canonical + search;
}
/**
* Page data for overides
* @typedef {object} PageData
* @property {string} [title] - Page title
* @property {string} [url] - Page url
* @property {string} [path] - Page path
* @property {string} [search] - Page search
* @property {string} [width] - Page width
* @property {string} [height] - Page height
*/
/**
* Get information about current page
* @typedef {Function} getPageData
* @param {PageData} [pageData = {}] - Page data overides
* @return {PageData} resolved page data
*/
var getPageData = function getPageData() {
var pageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (!i) return pageData;
var _document = document,
title = _document.title,
referrer = _document.referrer;
var _window = window,
location = _window.location,
innerWidth = _window.innerWidth,
innerHeight = _window.innerHeight;
var hash = location.hash,
search = location.search;
var url = currentUrl(search);
var page = {
title: title,
url: url,
path: urlPath(url),
hash: hash,
search: search,
width: innerWidth,
height: innerHeight
};
if (referrer && referrer !== '') {
page.referrer = referrer;
}
return objectSpread2$1(objectSpread2$1({}, page), pageData);
};
var initialState$2 = {
last: {},
history: [] // page reducer
};
function page() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$2;
var action = arguments.length > 1 ? arguments[1] : undefined;
var properties = action.properties,
options = action.options,
meta = action.meta;
switch (action.type) {
case EVENTS.page:
var viewData = serialize(objectSpread2$1({
properties: properties,
meta: meta
}, Object.keys(options).length && {
options: options
}));
return objectSpread2$1(objectSpread2$1({}, state), {
last: viewData,
// Todo prevent LARGE arrays https://bit.ly/2MnBwPT
history: state.history.concat(viewData)
});
default:
return state;
}
} // TODO fix os. os getting stripped out for node build
function getNodeOS() {
return 'na'; // os.platform()
}
var osName;
var referrer;
var locale;
var timeZone;
{
osName = getNodeOS();
referrer = {};
}
var initialState$3 = {
initialized: false,
sessionId: y$1(),
app: null,
version: null,
debug: false,
offline: i ? !navigator.onLine : false,
// use node network is-online
os: {
name: osName
},
userAgent: i ? navigator.userAgent : 'node',
// https://github.com/bestiejs/platform.js
library: {
name: LIBRARY_NAME,
// TODO fix version number. npm run publish:patch has wrong version
version: "0.10.10"
},
timezone: timeZone,
locale: locale,
campaign: {},
referrer: referrer // context reducer
};
function context() {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$3;
var action = arguments.length > 1 ? arguments[1] : undefined;
var initialized = state.initialized;
var type = action.type,
campaign = action.campaign;
switch (type) {
case EVENTS.campaign:
return objectSpread2$1(objectSpread2$1({}, state), {
campaign: campaign
});
case EVENTS.offline:
return objectSpread2$1(objectSpread2$1({}, state), {
offline: true
});
case EVENTS.online:
return objectSpread2$1(objectSpread2$1({}, state), {
offline: false
});
default:
if (!initialized) {
return objectSpread2$1(objectSpread2$1(objectSpread2$1({}, initialState$3), state), {
initialized: true
});
}
return state;
}
}
var excludeItems = ['plugins', 'reducers', 'storage']; // Pull plugins and reducers off intital config
function makeContext(config) {
return Object.keys(config).reduce(function (acc, current) {
if (excludeItems.includes(current)) {
return acc;
}
acc[current] = config[current];
return acc;
}, {});
}
function Debug() {
// initialize global history
var globalVariable = PREFIX + LIBRARY_NAME + PREFIX; // Global key is window.__analytics__
f$2(globalVariable, []); // Return debugger
return function (createStore$$1) {
return function (reducer, preloadedState, enhancer) {
var store = createStore$$1(reducer, preloadedState, enhancer);
var origDispatch = store.dispatch;
var dispatch = function dispatch(action) {
var a$$1 = action.action || action;
l$2[globalVariable].push(a$$1);
return origDispatch(action);
};
return Object.assign(store, {
dispatch: dispatch
});
};
};
}
function composeWithDebug(config) {
return function () {
return compose(compose.apply(null, arguments), Debug(config));
};
}
function ensureArray(singleOrArray) {
if (!singleOrArray) return [];
if (g(singleOrArray)) return singleOrArray;
return [singleOrArray];
}
/**
* Grab first function found from arguments
* @param {array} [argArray] - arguments array to find first function
* @returns {Function|undefined}
*/
function getCallbackFromArgs(argArray) {
var args = argArray || Array.prototype.slice.call(arguments);
var cb;
for (var i$$1 = 0; i$$1 < args.length; i$$1++) {
if (c(args[i$$1])) {
cb = args[i$$1];
break;
}
}
return cb;
}
function timeStamp() {
return new Date().getTime();
}
function deferredPromiseResolver(resolver, callback) {
return function (data) {
if (callback) callback(data);
resolver(data);
};
}
function generateMeta() {
var meta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var resolve = arguments.length > 1 ? arguments[1] : undefined;
var possibleCallbacks = arguments.length > 2 ? arguments[2] : undefined;
var rid = y$1();
if (resolve) {
// stack[`${rid}-info`] = meta
stack[rid] = deferredPromiseResolver(resolve, getCallbackFromArgs(possibleCallbacks));
}
return objectSpread2$1(objectSpread2$1({}, meta), {}, {
rid: rid,
ts: timeStamp()
}, !resolve ? {} : {
hasCallback: true
});
}
/**
* Analytics library configuration
*
* After the library is initialized with config, the core API is exposed & ready for use in the application.
*
* @param {object} config - analytics core config
* @param {string} [config.app] - Name of site / app
* @param {string} [config.version] - Version of your app
* @param {boolean} [config.debug] - Should analytics run in debug mode
* @param {Array.<AnalyticsPlugin>} [config.plugins] - Array of analytics plugins
* @return {AnalyticsInstance} Analytics Instance
* @example
*
* import Analytics from 'analytics'
* import pluginABC from 'analytics-plugin-abc'
* import pluginXYZ from 'analytics-plugin-xyz'
*
* // initialize analytics
* const analytics = Analytics({
* app: 'my-awesome-app',
* plugins: [
* pluginABC,
* pluginXYZ
* ]
* })
*
*/
function analytics() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var customReducers = config.reducers || {};
var initialUser = config.initialUser || {}; // @TODO add custom value reolvers for userId and anonId
// const resolvers = config.resolvers || {}
/* Parse plugins array */
var parsedOptions = (config.plugins || []).reduce(function (acc, plugin) {
if (c(plugin)) {
/* Custom redux middleware */
acc.middlewares = acc.middlewares.concat(plugin);
return acc;
} // Legacy plugin with name
if (plugin.NAMESPACE) plugin.name = plugin.NAMESPACE;
if (!plugin.name) {
/* Plugins must supply a "name" property. See error url for more details */
throw new Error(ERROR_URL + '1');
} // if plugin exposes EVENTS capture available events
var definedEvents = plugin.EVENTS ? Object.keys(plugin.EVENTS).map(function (k) {
return plugin.EVENTS[k];
}) : [];
var enabledFromMerge = !(plugin.enabled === false);
var enabledFromPluginConfig = !(plugin.config && plugin.config.enabled === false); // top level { enabled: false } takes presidence over { config: enabled: false }
acc.pluginEnabled[plugin.name] = enabledFromMerge && enabledFromPluginConfig;
delete plugin.enabled;
if (plugin.methods) {
acc.methods[plugin.name] = Object.keys(plugin.methods).reduce(function (a$$1, c$$1) {
// enrich methods with analytics instance
a$$1[c$$1] = appendArguments(plugin.methods[c$$1]);
return a$$1;
}, {}); // Remove additional methods from plugins
delete plugin.methods;
} // Convert available methods into events
var methodsToEvents = Object.keys(plugin); // Combine events
var allEvents = methodsToEvents.concat(definedEvents); // Dedupe events list
var allEventsUnique = new Set(acc.events.concat(allEvents));
acc.events = Array.from(allEventsUnique);
acc.pluginsArray = acc.pluginsArray.concat(plugin);
if (acc.plugins[plugin.name]) {
throw new Error(plugin.name + 'AlreadyLoaded');
}
acc.plugins[plugin.name] = plugin;
if (!acc.plugins[plugin.name].loaded) {
// set default loaded func
acc.plugins[plugin.name].loaded = function () {
return true;
};
}
return acc;
}, {
plugins: {},
pluginEnabled: {},
methods: {},
pluginsArray: [],
middlewares: [],
events: []
});
/* Storage by default is set to global & is not persisted */
var storage = config.storage ? config.storage : {
getItem: o$2,
setItem: f$2,
removeItem: n$1
};
var getUserProp = getUserPropFunc(storage); // mutable intregrations object for dynamic loading
var customPlugins = parsedOptions.plugins;
/* Grab all registered events from plugins loaded */
var allPluginEvents = parsedOptions.events.filter(function (name) {
return !nonEvents.includes(name);
}).sort();
var uniqueEvents = new Set(allPluginEvents.concat(coreEvents).filter(function (name) {
return !nonEvents.includes(name);
}));
var allSystemEvents = Array.from(uniqueEvents).sort();
/* plugin methods(functions) must be kept out of state. thus they live here */
var getPlugins = function getPlugins() {
return customPlugins;
};
var _ref = new DynamicMiddleware(),
addMiddleware = _ref.addMiddleware,
removeMiddleware = _ref.removeMiddleware,
dynamicMiddlewares = _ref.dynamicMiddlewares;
var nonAbortable = function nonAbortable() {
// throw new Error(`${ERROR_URL}3`)
throw new Error('Abort disabled inListener');
}; // Parse URL parameters
var params = s$1(); // Initialize visitor information
var persistedUser = getPersistedUserData(storage);
var visitorInfo = objectSpread2$1(objectSpread2$1(objectSpread2$1(objectSpread2$1({}, persistedUser), initialUser), !params.an_uid ? {} : {
userId: params.an_uid
}), !params.an_aid ? {} : {
anonymousId: params.an_aid
}); // If no anon id set, create one
if (!visitorInfo.anonymousId) {
visitorInfo.anonymousId = y$1();
}
/**
* Async Management methods for plugins.
*
* This is also where [custom methods](https://bit.ly/329vFXy) are loaded into the instance.
* @typedef {Object} Plugins
* @property {EnablePlugin} enable - Set storage value
* @property {DisablePlugin} disable - Remove storage value
* @example
*
* // Enable a plugin by namespace
* analytics.plugins.enable('keenio')
*
* // Disable a plugin by namespace
* analytics.plugins.disable('google-analytics')
*/
var plugins = objectSpread2$1({
/**
* Enable analytics plugin
* @typedef {Function} EnablePlugin
* @param {String|Array} plugins - name of plugins(s) to disable
* @param {Function} [callback] - callback after enable runs
* @returns {Promise}
* @example
*
* analytics.plugins.enable('google-analytics').then(() => {
* console.log('do stuff')
* })
*
* // Enable multiple plugins at once
* analytics.plugins.enable(['google-analytics', 'segment']).then(() => {
* console.log('do stuff')
* })
*/
enable: function enable(plugins, callback) {
return new Promise(function (resolve) {
store.dispatch({
type: EVENTS.enablePlugin,
plugins: ensureArray(plugins),
_: {
originalAction: EVENTS.enablePlugin
}
}, resolve, [callback]);
});
},
/**
* Disable analytics plugin
* @typedef {Function} DisablePlugin
* @param {String|Array} plugins - name of integration(s) to disable
* @param {Function} callback - callback after disable runs
* @returns {Promise}
* @example
*
* analytics.plugins.disable('google').then(() => {
* console.log('do stuff')
* })
*
* analytics.plugins.disable(['google', 'segment']).then(() => {
* console.log('do stuff')
* })
*/
disable: function disable(plugins, callback) {
return new Promise(function (resolve) {
store.dispatch({
type: EVENTS.disablePlugin,
plugins: ensureArray(plugins),
_: {
originalAction: EVENTS.disablePlugin
}
}, resolve, [callback]);
});
}
}, parsedOptions.methods);
/**
* Analytic instance returned from initialization
* @typedef {Object} AnalyticsInstance
* @property {Identify} identify - Identify a user
* @property {Track} track - Track an analytics event
* @property {Page} page - Trigger page view
* @property {User} user - Get user data
* @property {Reset} reset - Clear information about user & reset analytics
* @property {Ready} ready - Fire callback on analytics ready event
* @property {On} on - Fire callback on analytics lifecycle events.
* @property {Once} once - Fire callback on analytics lifecycle events once.
* @property {GetState} getState - Get data about user, activity, or context.
* @property {Storage} storage - storage methods
* @property {Plugins} plugins - plugin methods
*/
var instance = {
/**
* Identify a user. This will trigger `identify` calls in any installed plugins and will set user data in localStorage
* @typedef {Function} Identify
* @param {String} userId - Unique ID of user
* @param {Object} [traits] - Object of user traits
* @param {Object} [options] - Options to pass to identify call
* @param {Function} [callback] - Callback function after identify completes
* @returns {Promise}
* @api public
*
* @example
*
* // Basic user id identify
* analytics.identify('xyz-123')
*
* // Identify with additional traits
* analytics.identify('xyz-123', {
* name: 'steve',
* company: 'hello-clicky'
* })
*
* // Fire callback with 2nd or 3rd argument
* analytics.identify('xyz-123', () => {
* console.log('do this after identify')
* })
*
* // Disable sending user data to specific analytic tools
* analytics.identify('xyz-123', {}, {
* plugins: {
* // disable sending this identify call to segment
* segment: false
* }
* })
*
* // Send user data to only to specific analytic tools
* analytics.identify('xyz-123', {}, {
* plugins: {
* // disable this specific identify in all plugins except customerio
* all: false,
* customerio: true
* }
* })
*/
identify: function () {
var _identify = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee(userId, traits, options, callback) {
var id, data, opts, user, resolvedId;
return regenerator.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
id = p(userId) ? userId : null;
data = l(userId) ? userId : traits;
opts = options || {};
user = instance.user();
/* sets temporary in memory id. Not to be relied on */
f$2(tempKey(ID), id);
resolvedId = id || data.userId || getUserProp(ID, instance, data);
return _context.abrupt("return", new Promise(function (resolve) {
store.dispatch(objectSpread2$1({
type: EVENTS.identifyStart,
userId: resolvedId,
traits: data || {},
options: opts,
anonymousId: user.anonymousId
}, user.id && user.id !== id && {
previousId: user.id
}), resolve, [traits, options, callback]);
}));
case 7:
case "end":
return _context.stop();
}
}
}, _callee);
}));
function identify(_x, _x2, _x3, _x4) {
return _identify.apply(this, arguments);
}
return identify;
}(),
/**
* Track an analytics event. This will trigger `track` calls in any installed plugins
* @typedef {Function} Track
* @param {String} eventName - Event name
* @param {Object} [payload] - Event payload
* @param {Object} [options] - Event options
* @param {Function} [callback] - Callback to fire after tracking completes
* @returns {Promise}
* @api public
*
* @example
*
* // Basic event tracking
* analytics.track('buttonClicked')
*
* // Event tracking with payload
* analytics.track('itemPurchased', {
* price: 11,
* sku: '1234'
* })
*
* // Fire callback with 2nd or 3rd argument
* analytics.track('newsletterSubscribed', () => {
* console.log('do this after track')
* })
*
* // Disable sending this event to specific analytic tools
* analytics.track('cartAbandoned', {
* items: ['xyz', 'abc']
* }, {
* plugins: {
* // disable track event for segment
* segment: false
* }
* })
*
* // Send event to only to specific analytic tools
* analytics.track('customerIoOnlyEventExample', {
* price: 11,
* sku: '1234'
* }, {
* plugins: {
* // disable this specific track call all plugins except customerio
* all: false,
* customerio: true
* }
* })
*/
track: function () {
var _track = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee2(eventName, payload, options, callback) {
var name, data, opts;
return regenerator.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
name = l(eventName) ? eventName.event : eventName;
if (!(!name || !p(name))) {
_context2.next = 3;
break;
}
throw new Error('EventMissing');
case 3:
data = l(eventName) ? eventName : payload || {};
opts = l(options) ? options : {};
return _context2.abrupt("return", new Promise(function (resolve) {
store.dispatch({
type: EVENTS.trackStart,
event: name,
properties: data,
options: opts,
userId: getUserProp(ID, instance, payload),
anonymousId: getUserProp(ANONID, instance, payload)
}, resolve, [payload, options, callback]);
}));
case 6:
case "end":
return _context2.stop();
}
}
}, _callee2);
}));
function track(_x5, _x6, _x7, _x8) {
return _track.apply(this, arguments);
}
return track;
}(),
/**
* Trigger page view. This will trigger `page` calls in any installed plugins
* @typedef {Function} Page
* @param {PageData} [data] - Page data overrides.
* @param {Object} [options] - Page tracking options
* @param {Function} [callback] - Callback to fire after page view call completes
* @returns {Promise}
* @api public
*
* @example
*
* // Basic page tracking
* analytics.page()
*
* // Page tracking with page data overrides
* analytics.page({
* url: 'https://google.com'
* })
*
* // Fire callback with 1st, 2nd or 3rd argument
* analytics.page(() => {
* console.log('do this after page')
* })
*
* // Disable sending this pageview to specific analytic tools
* analytics.page({}, {
* plugins: {
* // disable page tracking event for segment
* segment: false
* }
* })
*
* // Send pageview to only to specific analytic tools
* analytics.page({}, {
* plugins: {
* // disable this specific page in all plugins except customerio
* all: false,
* customerio: true
* }
* })
*/
page: function () {
var _page = asyncToGenerator(
/*#__PURE__*/
regenerator.mark(function _callee3(data, options, callback) {
var d$$1, opts;
return regenerator.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
d$$1 = l(data) ? data : {};
opts = l(options) ? options : {};
/*
// @TODO add custom value reolvers for userId and anonId
if (resolvers.getUserId) {
const asyncUserId = await resolvers.getUserId()
console.log('x', x)
}
*/
return _context3.abrupt("return", new Promise(function (resolve) {
store.dispatch({
type: EVENTS.pageStart,
properties: getPageData(d$$1),
options: opts,
userId: getUserProp(ID, instance, d$$1),
anonymousId: getUserProp(ANONID, instance, d$$1)
}, resolve, [data, options, callback]);
}));
case 3:
case "end":
return _context3.stop();
}
}
}, _callee3);
}));
function page$$1(_x9, _x10, _x11) {
return _page.apply(this, arguments);
}
return page$$1;
}(),
/**
* Get user data
* @typedef {Function} User
* @param {string} [key] - dot.prop.path of user data. Example: 'traits.company.name'
* @returns {string|object} value of user data or null
*
* @example
*
* // Get all user data
* const userData = analytics.user()
*
* // Get user id
* const userId = analytics.user('userId')
*
* // Get user company name
* const companyName = analytics.user('traits.company.name')
*/
user: function user(key) {
if (key === ID || key === 'id') {
return getUserProp(ID, instance);
}
if (key === ANONID || key === 'anonId') {
return getUserProp(ANONID, instance);
}
var user = instance.getState('user');
if (!key) return user;
return dotProp(user, key);
},
/**
* Clear all information about the visitor & reset analytic state.
* @typedef {Function} Reset
* @param {Function} [callback] - Handler to run after reset
* @returns {Promise}
* @example
*
* // Reset current visitor
* analytics.reset()
*/
reset: function reset(callback) {
return new Promise(function (resolve) {
store.dispatch({
type: EVENTS.resetStart
}, resolve, callback);
});
},
/**
* Fire callback on analytics ready event
* @typedef {Function} Ready
* @param {Function} callback - function to trigger when all providers have loaded
* @returns {DetachListeners} - Function to detach listener
*
* @example
*
* analytics.ready() => {
* console.log('all plugins have loaded or were skipped', payload)
* })
*/
ready: function ready(callback) {
return instance.on(EVENTS.ready, callback);
},
/**
* Attach an event handler function for analytics lifecycle events.
* @typedef {Function} On
* @param {String} name - Name of event to listen to
* @param {Function} callback - function to fire on event
* @return {DetachListeners} - Function to detach listener
*
* @example
*
* // Fire function when 'track' calls happen
* analytics.on('track', ({ payload }) => {
* console.log('track call just happened. Do stuff')
* })
*
* // Remove listener before it is called
* const removeListener = analytics.on('track', ({ payload }) => {
* console.log('This will never get called')
* })
*
* // cleanup .on listener
* removeListener()
*/
on: function on(name, callback) {
if (!name || !c(callback)) {
return false;
}
if (name === EVENTS.bootstrap) {
throw new Error('.on disabled for ' + name);
}
var startRegex = /Start$|Start:/;
if (name === '*') {
var beforeHandler = function beforeHandler(store) {
return function (next) {
return function (action) {
if (action.type.match(startRegex)) {
callback({
// eslint-disable-line
payload: action,
instance: instance,
plugins: customPlugins
});
}
return next(action);
};
};
};
var afterHandler = function afterHandler(store) {
return function (next) {
return function (action) {
if (!action.type.match(startRegex)) {
callback({
// eslint-disable-line
payload: action,
instance: instance,
plugins: customPlugins
});
}
return next(action);
};
};
};
addMiddleware(beforeHandler, before);
addMiddleware(afterHandler, after);
/**
* Detach listeners
* @typedef {Function} DetachListeners
*/
return function () {
removeMiddleware(beforeHandler, before);
removeMiddleware(afterHandler, after);
};
}
var position = name.match(startRegex) ? before : after; // eslint-disable-line
var handler = function handler(store) {
return function (next) {
return function (action) {
// Subscribe to EVERYTHING
if (action.type === name) {
callback({
// eslint-disable-line
payload: action,
instance: instance,
plugins: customPlugins,
abort: nonAbortable
});
}
/* For future matching of event subpaths `track:*` etc
} else if (name.match(/\*$/)) {
const match = (name === '*') ? '.' : name
const regex = new RegExp(`${match}`, 'g')
} */
return next(action);
};
};
};
addMiddleware(handler, position);
return function () {
return removeMiddleware(handler, position);
};
},
/**
* Attach a handler function to an event and only trigger it only once.
* @typedef {Function} Once
* @param {String} name - Name of event to listen to
* @param {Function} callback - function to fire on event
* @return {DetachListeners} - Function to detach listener
*
* @example
*
* // Fire function only once 'track'
* analytics.once('track', ({ payload }) => {
* console.log('This will only triggered once when analytics.track() fires')
* })
*
* // Remove listener before it is called
* const listener = analytics.once('track', ({ payload }) => {
* console.log('This will never get called b/c listener() is called')
* })
*
* // cleanup .once listener before it fires
* listener()
*/
once: function once(name, callback) {
if (!name || !c(callback)) {
return false;
}
if (name === EVENTS.bootstrap) {
throw new Error('.once disabled for ' + name);
}
var detachListener = instance.on(name, function (_ref2) {
var payload = _ref2.payload;
callback({
// eslint-disable-line
payload: payload,
instance: instance,
plugins: customPlugins,
abort: nonAbortable
}); // detach listener after its called once
detachListener();
});
return detachListener;
},
/**
* Get data about user, activity, or context. Access sub-keys of state with `dot.prop` syntax.
* @typedef {Function} GetState
* @param {string} [key] - dot.prop.path value of state
* @return {any}
*
* @example
*
* // Get the current state of analytics
* analytics.getState()
*
* // Get a subpath of state
* analytics.getState('context.offline')
*/
getState: function getState(key) {
var state = store.getState();
if (key) return dotProp(state, key);
return Object.assign({}, state);
},
/*
* Emit events for other plugins or middleware to react to.
* @param {Object} action - event to dispatch
*/
dispatch: function dispatch(action) {
var actionData = p(action) ? {
type: action
} : action;
if (isReservedAction(actionData.type)) {
throw new Error('reserved action ' + actionData.type);
}
var _private = action._ || {}; // Dispatch actionStart
// const autoPrefixType = `${actionData.type.replace(/Start$/, '')}Start`
var dispatchData = objectSpread2$1(objectSpread2$1({}, actionData), {}, {
_: objectSpread2$1({
originalAction: actionData.type
}, _private) // type: `${autoPrefixType}`
});
store.dispatch(dispatchData);
},
// Do not use. Will be removed. Here for Backwards compatiblity.
// Moved to analytics.plugins.enable
enablePlugin: plugins.enable,
/// Do not use. Will be removed. Here for Backwards compatiblity.
/// Moved to analytics.plugins.disable
disablePlugin: plugins.disable,
// Do not use. Will be removed. Here for Backwards compatiblity.
// New plugins api
plugins: plugins,
/**
* Storage utilities for persisting data.
* These methods will allow you to save data in localStorage, cookies, or to the window.
* @typedef {Object} Storage
* @property {GetItem} getItem - Get value from storage
* @property {SetItem} setItem - Set storage value
* @property {RemoveItem} removeItem - Remove storage value
*
* @example
*
* // Pull storage off analytics instance
* const { storage } = analytics
*
* // Get value
* storage.getItem('storage_key')
*
* // Set value
* storage.setItem('storage_key', 'value')
*
* // Remove value
* storage.removeItem('storage_key')
*/
storage: {
/**
* Get value from storage
* @typedef {Function} GetItem
* @param {String} key - storage key
* @param {Object} [options] - storage options
* @return {Any}
*
* @example
*
* analytics.storage.getItem('storage_key')
*/
getItem: storage.getItem,
/**
* Set storage value
* @typedef {Function} SetItem
* @param {String} key - storage key
* @param {any} value - storage value
* @param {Object} [options] - storage options
*
* @example
*
* analytics.storage.setItem('storage_key', 'value')
*/
setItem: function setItem(key, value, options) {
store.dispatch({
type: EVENTS.setItemStart,
key: key,
value: value,
options: options
});
},
/**
* Remove storage value
* @typedef {Function} RemoveItem
* @param {String} key - storage key
* @param {Object} [options] - storage options
*
* @example
*
* analytics.storage.removeItem('storage_key')
*/
removeItem: function removeItem(key, options) {
store.dispatch({
type: EVENTS.removeItemStart,
key: key,
options: options
});
}
},
/*
* Set the anonymous ID of the visitor
* @param {String} anonymousId - anonymous Id to set
* @param {Object} [options] - storage options
*
* @example
*
* // Set anonymous ID
* analytics.setAnonymousId('1234567')
*/
setAnonymousId: function setAnonymousId(anonymousId, options) {
/* sets temporary in memory id. Not to be relied on */
// set(tempKey(ANONID), anonymousId)
instance.storage.setItem(ANON_ID, anonymousId, options);
},
/*
* Events exposed by core analytics library and all loaded plugins
* @type {Array}
*/
events: {
all: allSystemEvents,
core: coreEvents,
plugins: allPluginEvents // byType: (type) => {} @Todo grab logic from engine and give inspectable events
}
};
var enrichMiddleware = function enrichMiddleware(storeAPI) {
return function (next) {
return function (action) {
if (!action.meta) {
action.meta = generateMeta();
}
return next(action);
};
};
};
var middlewares = parsedOptions.middlewares.concat([enrichMiddleware,
/* Core analytics middleware */
dynamicMiddlewares(before), // Before dynamic middleware <-- fixed pageStart .on listener
/* Plugin engine */
pluginMiddleware(instance, getPlugins, {
all: allSystemEvents,
plugins: allPluginEvents
}), storageMiddleware(storage), initializeMiddleware(instance), identifyMiddleware(instance, storage),
/* after dynamic middleware */
dynamicMiddlewares(after)]);
/* Initial analytics state keys */
var coreReducers = {
context: context,
user: userReducer(storage),
page: page,
track: trackReducer,
plugins: createReducer(getPlugins),
queue: queueReducer
};
var composeEnhancers = compose;
var composeWithGlobalDebug = compose;
if (i && config.debug) {
var devTools = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
if (devTools) {
composeEnhancers = devTools({
trace: true,
traceLimit: 25
});
}
composeWithGlobalDebug = function composeWithGlobalDebug() {
if (arguments.length === 0) return Debug();
if (l(_typeof_1(arguments[0]))) return composeWithDebug(arguments[0]);
return composeWithDebug().apply(null, arguments);
};
}
var initialConfig = makeContext(config);
var intialPluginState = parsedOptions.pluginsArray.reduce(function (acc, plugin) {
var name = plugin.name,
config = plugin.config,
loaded = plugin.loaded;
var isEnabled = parsedOptions.pluginEnabled[name];
acc[name] = {
enabled: isEnabled,
// If plugin enabled & has no initialize method, set initialized to true, else false
initialized: isEnabled ? Boolean(!plugin.initialize) : false,
loaded: Boolean(loaded()),
config: config || {}
};
return acc;
}, {});
var initialState = {
context: initialConfig,
user: visitorInfo,
plugins: intialPluginState // Todo allow for more userland defined initial state?
/* Create analytics store! */
};
var store = createStore( // register reducers
combineReducers(objectSpread2$1(objectSpread2$1({}, coreReducers), customReducers)), // set user defined initial state
initialState, // register middleware & plugins used
composeWithGlobalDebug(composeEnhancers(applyMiddleware.apply(void 0, toConsumableArray(middlewares)))));
/* Supe up dispatch with callback promise resolver. Happens in enrichMeta */
function enhanceDispatch(fn) {
return function (event, resolver, callbacks) {
// console.log('original event', event)
var meta = generateMeta(event.meta, resolver, ensureArray(callbacks)); // if (resolver) console.log('dispatch resolver', resolver)
// if (callbacks) console.log('dispatch callbacks', callbacks)
var newEvent = objectSpread2$1(objectSpread2$1({}, event), {
meta: meta
}); // console.log('newEvent', newEvent)
return fn.apply(null, [newEvent]);
};
} // Automatically apply meta to dispatch calls
store.dispatch = enhanceDispatch(store.dispatch);
/* Synchronously call bootstrap & register Plugin methods */
var pluginKeys = Object.keys(customPlugins);
/* Bootstrap analytic plugins */
store.dispatch({
type: EVENTS.bootstrap,
plugins: pluginKeys,
config: initialConfig,
params: params,
user: visitorInfo,
initialUser: initialUser,
persistedUser: persistedUser
});
var enabledPlugins = pluginKeys.filter(function (name) {
return parsedOptions.pluginEnabled[name];
});
var disabledPlugins = pluginKeys.filter(function (name) {
return !parsedOptions.pluginEnabled[name];
});
/* Register analytic plugins */
store.dispatch({
type: EVENTS.registerPlugins,
plugins: pluginKeys,
enabled: parsedOptions.pluginEnabled
});
/* dispatch register for individual plugins */
parsedOptions.pluginsArray.map(function (plugin, i$$1) {
var bootstrap = plugin.bootstrap,
config = plugin.config,
name = plugin.name;
if (bootstrap && c(bootstrap)) {
bootstrap({
instance: instance,
config: config,
payload: plugin
});
}
/* Register plugins */
store.dispatch({
type: EVENTS.registerPluginType(name),
name: name,
enabled: parsedOptions.pluginEnabled[name],
plugin: plugin
});
/* All plugins registered initialize, is last loop */
if (parsedOptions.pluginsArray.length === i$$1 + 1) {
store.dispatch({
type: EVENTS.initializeStart,
plugins: enabledPlugins,
disabled: disabledPlugins
});
}
});
function appendArguments(fn) {
return function () {
/* Get original args */
var args = Array.prototype.slice.call(arguments);
/* Create clone of args */
var newArgs = new Array(fn.length);
for (var i$$1 = 0; i$$1 < args.length; i$$1++) {
newArgs[i$$1] = args[i$$1];
}
/* Append new arg to end */
newArgs[newArgs.length] = instance; // Set instance on extended methods
return fn.apply({
instance: instance
}, newArgs);
};
}
/* Return analytics instance */
return instance;
} // Duplicated strings
var before = 'before';
var after = 'after';
var i$2 = a$2(),
r$1 = p$2,
c$2 = p$2;
function u$2(e) {
return i$2 ? p$2(e, "", -1) : n$1(e);
}
function a$2() {
if (typeof i$2 !== e$1) return i$2;
try {
p$2(e$1, "1"), i$2 = -1 !== document.cookie.indexOf(e$1), u$2(e$1);
} catch (e) {
i$2 = !1;
}
return i$2;
}
function p$2(t, r, c, u, a, p) {
if (typeof window !== e$1) {
var d = arguments.length > 1;
return i$2 || (d ? f$2(t, r) : o$2(t)), d ? document.cookie = t + "=" + encodeURIComponent(r) + (c ? "; expires=" + new Date(+new Date() + 1e3 * c).toUTCString() + (u ? "; path=" + u : "") + (a ? "; domain=" + a : "") + (p ? "; secure" : "") : "") : decodeURIComponent((("; " + document.cookie).split("; " + t + "=")[1] || "").split(";")[0]);
}
}
var a$3 = l$3();
function l$3() {
if (typeof a$3 !== e$1) return a$3;
a$3 = !0;
try {
typeof localStorage !== e$1 && typeof JSON !== e$1 || (a$3 = !1), localStorage.setItem(e$1, e$1), localStorage.removeItem(e$1);
} catch (t) {
a$3 = !1;
}
return a$3;
}
function s$2(o$$1) {
var t$$1 = o$$1;
try {
if ("true" === (t$$1 = JSON.parse(o$$1))) return !0;
if ("false" === t$$1) return !1;
if (l(t$$1)) return t$$1;
parseFloat(t$$1) === t$$1 && (t$$1 = parseFloat(t$$1));
} catch (o$$1) {}
if (null !== t$$1 && "" !== t$$1) return t$$1;
}
var k = l$3(),
y$2 = a$2();
function b$2(t$$1, r$$1) {
if (t$$1) {
var e$$1 = C(r$$1),
l$$1 = !F(e$$1),
i$$1 = d$2(e$$1) ? s$2(localStorage.getItem(t$$1)) : void 0;
if (l$$1 && !a(i$$1)) return i$$1;
var c$$1 = h$1(e$$1) ? s$2(r$1(t$$1)) : void 0;
if (l$$1 && c$$1) return c$$1;
var n$$1 = o$2(t$$1);
return l$$1 ? n$$1 : {
localStorage: i$$1,
cookie: c$$1,
global: n$$1
};
}
}
function I(r$$1, e$$1, i$$1) {
if (r$$1 && !a(e$$1)) {
var c$$1 = {},
n$$1 = C(i$$1),
g$$1 = JSON.stringify(e$$1),
f$$1 = !F(n$$1);
return d$2(n$$1) && (c$$1.localStorage = {
location: "localStorage",
current: e$$1,
previous: s$2(localStorage.getItem(r$$1))
}, localStorage.setItem(r$$1, g$$1), f$$1) ? c$$1.localStorage : h$1(n$$1) && (c$$1.cookie = {
location: "cookie",
current: e$$1,
previous: s$2(r$1(r$$1))
}, c$2(r$$1, g$$1), f$$1) ? c$$1.cookie : (c$$1.global = {
location: "global",
current: e$$1,
previous: o$2(r$$1)
}, f$2(r$$1, e$$1), f$$1 ? c$$1.global : c$$1);
}
}
function x$1(o$$1, t$$1) {
if (o$$1) {
var e$$1 = C(t$$1),
a$$1 = b$2(o$$1, "*"),
l$$1 = {};
return !a(a$$1.localStorage) && d$2(e$$1) && (localStorage.removeItem(o$$1), l$$1.localStorage = a$$1.localStorage), !a(a$$1.cookie) && h$1(e$$1) && (u$2(o$$1), l$$1.cookie = a$$1.cookie), !a(a$$1.global) && J(e$$1, "global") && (n$1(o$$1), l$$1.global = a$$1.global), l$$1;
}
}
function C(o$$1) {
return o$$1 ? p(o$$1) ? o$$1 : o$$1.storage : "any";
}
function d$2(o$$1) {
return k && J(o$$1, "localStorage");
}
function h$1(o$$1) {
return y$2 && J(o$$1, "cookie");
}
function F(o$$1) {
return "*" === o$$1 || "all" === o$$1;
}
function J(o$$1, t$$1) {
return "any" === o$$1 || o$$1 === t$$1 || F(o$$1);
}
var N = {
setItem: I,
getItem: b$2,
removeItem: x$1
};
function analyticsLib() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var defaultSettings = {
storage: N
};
return analytics(objectSpread2(objectSpread2({}, defaultSettings), opts));
}
exports.default = analyticsLib;
exports.init = analyticsLib;
exports.Analytics = analyticsLib;
exports.EVENTS = EVENTS;
exports.CONSTANTS = constants;
return exports;
}({}));