@rudderstack/analytics-js 3.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1734 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.rudderanalytics = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ let UaChTrackLevel=/*#__PURE__*/function(UaChTrackLevel){UaChTrackLevel["None"]="none";UaChTrackLevel["Default"]="default";UaChTrackLevel["Full"]="full";return UaChTrackLevel;}({});/**
8
+ * Represents the options parameter for anonymousId
9
+ */ /**
10
+ * Represents the beacon queue options parameter in loadOptions type
11
+ */let CookieSameSite=/*#__PURE__*/function(CookieSameSite){CookieSameSite["Strict"]="Strict";CookieSameSite["Lax"]="Lax";CookieSameSite["None"]="None";return CookieSameSite;}({});/**
12
+ * Represents the queue options parameter in loadOptions type
13
+ */ /**
14
+ * Represents the destinations queue options parameter in loadOptions type
15
+ */ /**
16
+ * Represents the options parameter in the load API
17
+ */
18
+
19
+ /**
20
+ * Represents residency server input the options
21
+ */let ResidencyServerRegion=/*#__PURE__*/function(ResidencyServerRegion){ResidencyServerRegion["US"]="US";ResidencyServerRegion["EU"]="EU";return ResidencyServerRegion;}({});
22
+
23
+ let LogLevel=/*#__PURE__*/function(LogLevel){LogLevel["Log"]="LOG";LogLevel["Info"]="INFO";LogLevel["Debug"]="DEBUG";LogLevel["Warn"]="WARN";LogLevel["Error"]="ERROR";LogLevel["None"]="NONE";return LogLevel;}({});
24
+
25
+ let PluginName=/*#__PURE__*/function(PluginName){PluginName["BeaconQueue"]="BeaconQueue";PluginName["DeviceModeDestinations"]="DeviceModeDestinations";PluginName["DeviceModeTransformation"]="DeviceModeTransformation";PluginName["ErrorReporting"]="ErrorReporting";PluginName["ExternalAnonymousId"]="ExternalAnonymousId";PluginName["GoogleLinker"]="GoogleLinker";PluginName["NativeDestinationQueue"]="NativeDestinationQueue";PluginName["StorageEncryption"]="StorageEncryption";PluginName["StorageEncryptionLegacy"]="StorageEncryptionLegacy";PluginName["StorageMigrator"]="StorageMigrator";PluginName["XhrQueue"]="XhrQueue";PluginName["OneTrustConsentManager"]="OneTrustConsentManager";PluginName["KetchConsentManager"]="KetchConsentManager";PluginName["Bugsnag"]="Bugsnag";return PluginName;}({});
26
+
27
+ function _isPlaceholder(a){return a!=null&&typeof a==='object'&&a['@@functional/placeholder']===true;}
28
+
29
+ /**
30
+ * Optimized internal one-arity curry function.
31
+ *
32
+ * @private
33
+ * @category Function
34
+ * @param {Function} fn The function to curry.
35
+ * @return {Function} The curried function.
36
+ */function _curry1(fn){return function f1(a){if(arguments.length===0||_isPlaceholder(a)){return f1;}else {return fn.apply(this,arguments);}};}
37
+
38
+ /**
39
+ * Optimized internal two-arity curry function.
40
+ *
41
+ * @private
42
+ * @category Function
43
+ * @param {Function} fn The function to curry.
44
+ * @return {Function} The curried function.
45
+ */function _curry2(fn){return function f2(a,b){switch(arguments.length){case 0:return f2;case 1:return _isPlaceholder(a)?f2:_curry1(function(_b){return fn(a,_b);});default:return _isPlaceholder(a)&&_isPlaceholder(b)?f2:_isPlaceholder(a)?_curry1(function(_a){return fn(_a,b);}):_isPlaceholder(b)?_curry1(function(_b){return fn(a,_b);}):fn(a,b);}};}
46
+
47
+ /**
48
+ * Optimized internal three-arity curry function.
49
+ *
50
+ * @private
51
+ * @category Function
52
+ * @param {Function} fn The function to curry.
53
+ * @return {Function} The curried function.
54
+ */function _curry3(fn){return function f3(a,b,c){switch(arguments.length){case 0:return f3;case 1:return _isPlaceholder(a)?f3:_curry2(function(_b,_c){return fn(a,_b,_c);});case 2:return _isPlaceholder(a)&&_isPlaceholder(b)?f3:_isPlaceholder(a)?_curry2(function(_a,_c){return fn(_a,b,_c);}):_isPlaceholder(b)?_curry2(function(_b,_c){return fn(a,_b,_c);}):_curry1(function(_c){return fn(a,b,_c);});default:return _isPlaceholder(a)&&_isPlaceholder(b)&&_isPlaceholder(c)?f3:_isPlaceholder(a)&&_isPlaceholder(b)?_curry2(function(_a,_b){return fn(_a,_b,c);}):_isPlaceholder(a)&&_isPlaceholder(c)?_curry2(function(_a,_c){return fn(_a,b,_c);}):_isPlaceholder(b)&&_isPlaceholder(c)?_curry2(function(_b,_c){return fn(a,_b,_c);}):_isPlaceholder(a)?_curry1(function(_a){return fn(_a,b,c);}):_isPlaceholder(b)?_curry1(function(_b){return fn(a,_b,c);}):_isPlaceholder(c)?_curry1(function(_c){return fn(a,b,_c);}):fn(a,b,c);}};}
55
+
56
+ /**
57
+ * Tests whether or not an object is an array.
58
+ *
59
+ * @private
60
+ * @param {*} val The object to test.
61
+ * @return {Boolean} `true` if `val` is an array, `false` otherwise.
62
+ * @example
63
+ *
64
+ * _isArray([]); //=> true
65
+ * _isArray(null); //=> false
66
+ * _isArray({}); //=> false
67
+ */const _isArray = Array.isArray||function _isArray(val){return val!=null&&val.length>=0&&Object.prototype.toString.call(val)==='[object Array]';};
68
+
69
+ function _arrayFromIterator(iter){var list=[];var next;while(!(next=iter.next()).done){list.push(next.value);}return list;}
70
+
71
+ function _includesWith(pred,x,list){var idx=0;var len=list.length;while(idx<len){if(pred(x,list[idx])){return true;}idx+=1;}return false;}
72
+
73
+ function _functionName(f){// String(x => x) evaluates to "x => x", so the pattern may not match.
74
+ var match=String(f).match(/^function (\w*)/);return match==null?'':match[1];}
75
+
76
+ function _has(prop,obj){return Object.prototype.hasOwnProperty.call(obj,prop);}
77
+
78
+ // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
79
+ function _objectIs(a,b){// SameValue algorithm
80
+ if(a===b){// Steps 1-5, 7-10
81
+ // Steps 6.b-6.e: +0 != -0
82
+ return a!==0||1/a===1/b;}else {// Step 6.a: NaN == NaN
83
+ return a!==a&&b!==b;}}const _objectIs$1 = typeof Object.is==='function'?Object.is:_objectIs;
84
+
85
+ var toString=Object.prototype.toString;var _isArguments=/*#__PURE__*/function(){return toString.call(arguments)==='[object Arguments]'?function _isArguments(x){return toString.call(x)==='[object Arguments]';}:function _isArguments(x){return _has('callee',x);};}();
86
+
87
+ var hasEnumBug=!/*#__PURE__*/{toString:null}.propertyIsEnumerable('toString');var nonEnumerableProps=['constructor','valueOf','isPrototypeOf','toString','propertyIsEnumerable','hasOwnProperty','toLocaleString'];// Safari bug
88
+ var hasArgsEnumBug=/*#__PURE__*/function(){return arguments.propertyIsEnumerable('length');}();var contains=function contains(list,item){var idx=0;while(idx<list.length){if(list[idx]===item){return true;}idx+=1;}return false;};/**
89
+ * Returns a list containing the names of all the enumerable own properties of
90
+ * the supplied object.
91
+ * Note that the order of the output array is not guaranteed to be consistent
92
+ * across different JS platforms.
93
+ *
94
+ * @func
95
+ * @memberOf R
96
+ * @since v0.1.0
97
+ * @category Object
98
+ * @sig {k: v} -> [k]
99
+ * @param {Object} obj The object to extract properties from
100
+ * @return {Array} An array of the object's own properties.
101
+ * @see R.keysIn, R.values, R.toPairs
102
+ * @example
103
+ *
104
+ * R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
105
+ */var keys=typeof Object.keys==='function'&&!hasArgsEnumBug?/*#__PURE__*/_curry1(function keys(obj){return Object(obj)!==obj?[]:Object.keys(obj);}):/*#__PURE__*/_curry1(function keys(obj){if(Object(obj)!==obj){return [];}var prop,nIdx;var ks=[];var checkArgsLength=hasArgsEnumBug&&_isArguments(obj);for(prop in obj){if(_has(prop,obj)&&(!checkArgsLength||prop!=='length')){ks[ks.length]=prop;}}if(hasEnumBug){nIdx=nonEnumerableProps.length-1;while(nIdx>=0){prop=nonEnumerableProps[nIdx];if(_has(prop,obj)&&!contains(ks,prop)){ks[ks.length]=prop;}nIdx-=1;}}return ks;});
106
+
107
+ /**
108
+ * Gives a single-word string description of the (native) type of a value,
109
+ * returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not
110
+ * attempt to distinguish user Object types any further, reporting them all as
111
+ * 'Object'.
112
+ *
113
+ * @func
114
+ * @memberOf R
115
+ * @since v0.8.0
116
+ * @category Type
117
+ * @sig * -> String
118
+ * @param {*} val The value to test
119
+ * @return {String}
120
+ * @example
121
+ *
122
+ * R.type({}); //=> "Object"
123
+ * R.type(1); //=> "Number"
124
+ * R.type(false); //=> "Boolean"
125
+ * R.type('s'); //=> "String"
126
+ * R.type(null); //=> "Null"
127
+ * R.type([]); //=> "Array"
128
+ * R.type(/[A-z]/); //=> "RegExp"
129
+ * R.type(() => {}); //=> "Function"
130
+ * R.type(undefined); //=> "Undefined"
131
+ */var type=/*#__PURE__*/_curry1(function type(val){return val===null?'Null':val===undefined?'Undefined':Object.prototype.toString.call(val).slice(8,-1);});
132
+
133
+ /**
134
+ * private _uniqContentEquals function.
135
+ * That function is checking equality of 2 iterator contents with 2 assumptions
136
+ * - iterators lengths are the same
137
+ * - iterators values are unique
138
+ *
139
+ * false-positive result will be returned for comparison of, e.g.
140
+ * - [1,2,3] and [1,2,3,4]
141
+ * - [1,1,1] and [1,2,3]
142
+ * */function _uniqContentEquals(aIterator,bIterator,stackA,stackB){var a=_arrayFromIterator(aIterator);var b=_arrayFromIterator(bIterator);function eq(_a,_b){return _equals(_a,_b,stackA.slice(),stackB.slice());}// if *a* array contains any element that is not included in *b*
143
+ return !_includesWith(function(b,aItem){return !_includesWith(eq,aItem,b);},b,a);}function _equals(a,b,stackA,stackB){if(_objectIs$1(a,b)){return true;}var typeA=type(a);if(typeA!==type(b)){return false;}if(typeof a['fantasy-land/equals']==='function'||typeof b['fantasy-land/equals']==='function'){return typeof a['fantasy-land/equals']==='function'&&a['fantasy-land/equals'](b)&&typeof b['fantasy-land/equals']==='function'&&b['fantasy-land/equals'](a);}if(typeof a.equals==='function'||typeof b.equals==='function'){return typeof a.equals==='function'&&a.equals(b)&&typeof b.equals==='function'&&b.equals(a);}switch(typeA){case'Arguments':case'Array':case'Object':if(typeof a.constructor==='function'&&_functionName(a.constructor)==='Promise'){return a===b;}break;case'Boolean':case'Number':case'String':if(!(typeof a===typeof b&&_objectIs$1(a.valueOf(),b.valueOf()))){return false;}break;case'Date':if(!_objectIs$1(a.valueOf(),b.valueOf())){return false;}break;case'Error':return a.name===b.name&&a.message===b.message;case'RegExp':if(!(a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline&&a.sticky===b.sticky&&a.unicode===b.unicode)){return false;}break;}var idx=stackA.length-1;while(idx>=0){if(stackA[idx]===a){return stackB[idx]===b;}idx-=1;}switch(typeA){case'Map':if(a.size!==b.size){return false;}return _uniqContentEquals(a.entries(),b.entries(),stackA.concat([a]),stackB.concat([b]));case'Set':if(a.size!==b.size){return false;}return _uniqContentEquals(a.values(),b.values(),stackA.concat([a]),stackB.concat([b]));case'Arguments':case'Array':case'Object':case'Boolean':case'Number':case'String':case'Date':case'Error':case'RegExp':case'Int8Array':case'Uint8Array':case'Uint8ClampedArray':case'Int16Array':case'Uint16Array':case'Int32Array':case'Uint32Array':case'Float32Array':case'Float64Array':case'ArrayBuffer':break;default:// Values of other types are only equal if identical.
144
+ return false;}var keysA=keys(a);if(keysA.length!==keys(b).length){return false;}var extendedStackA=stackA.concat([a]);var extendedStackB=stackB.concat([b]);idx=keysA.length-1;while(idx>=0){var key=keysA[idx];if(!(_has(key,b)&&_equals(b[key],a[key],extendedStackA,extendedStackB))){return false;}idx-=1;}return true;}
145
+
146
+ /**
147
+ * Returns `true` if its arguments are equivalent, `false` otherwise. Handles
148
+ * cyclical data structures.
149
+ *
150
+ * Dispatches symmetrically to the `equals` methods of both arguments, if
151
+ * present.
152
+ *
153
+ * @func
154
+ * @memberOf R
155
+ * @since v0.15.0
156
+ * @category Relation
157
+ * @sig a -> b -> Boolean
158
+ * @param {*} a
159
+ * @param {*} b
160
+ * @return {Boolean}
161
+ * @example
162
+ *
163
+ * R.equals(1, 1); //=> true
164
+ * R.equals(1, '1'); //=> false
165
+ * R.equals([1, 2, 3], [1, 2, 3]); //=> true
166
+ *
167
+ * const a = {}; a.v = a;
168
+ * const b = {}; b.v = b;
169
+ * R.equals(a, b); //=> true
170
+ */var equals=/*#__PURE__*/_curry2(function equals(a,b){return _equals(a,b,[],[]);});
171
+
172
+ function _isObject(x){return Object.prototype.toString.call(x)==='[object Object]';}
173
+
174
+ /**
175
+ * Determine if the passed argument is an integer.
176
+ *
177
+ * @private
178
+ * @param {*} n
179
+ * @category Type
180
+ * @return {Boolean}
181
+ */const _isInteger = Number.isInteger||function _isInteger(n){return n<<0===n;};
182
+
183
+ function _isString(x){return Object.prototype.toString.call(x)==='[object String]';}
184
+
185
+ /**
186
+ * Returns the nth element of the given list or string. If n is negative the
187
+ * element at index length + n is returned.
188
+ *
189
+ * @func
190
+ * @memberOf R
191
+ * @since v0.1.0
192
+ * @category List
193
+ * @sig Number -> [a] -> a | Undefined
194
+ * @sig Number -> String -> String
195
+ * @param {Number} offset
196
+ * @param {*} list
197
+ * @return {*}
198
+ * @example
199
+ *
200
+ * const list = ['foo', 'bar', 'baz', 'quux'];
201
+ * R.nth(1, list); //=> 'bar'
202
+ * R.nth(-1, list); //=> 'quux'
203
+ * R.nth(-99, list); //=> undefined
204
+ *
205
+ * R.nth(2, 'abc'); //=> 'c'
206
+ * R.nth(3, 'abc'); //=> ''
207
+ * @symb R.nth(-1, [a, b, c]) = c
208
+ * @symb R.nth(0, [a, b, c]) = a
209
+ * @symb R.nth(1, [a, b, c]) = b
210
+ */var nth=/*#__PURE__*/_curry2(function nth(offset,list){var idx=offset<0?list.length+offset:offset;return _isString(list)?list.charAt(idx):list[idx];});
211
+
212
+ function _cloneRegExp(pattern){return new RegExp(pattern.source,pattern.flags?pattern.flags:(pattern.global?'g':'')+(pattern.ignoreCase?'i':'')+(pattern.multiline?'m':'')+(pattern.sticky?'y':'')+(pattern.unicode?'u':'')+(pattern.dotAll?'s':''));}
213
+
214
+ /**
215
+ * Copies an object.
216
+ *
217
+ * @private
218
+ * @param {*} value The value to be copied
219
+ * @param {Boolean} deep Whether or not to perform deep cloning.
220
+ * @return {*} The copied value.
221
+ */function _clone(value,deep,map){map||(map=new _ObjectMap());// this avoids the slower switch with a quick if decision removing some milliseconds in each run.
222
+ if(_isPrimitive(value)){return value;}var copy=function copy(copiedValue){// Check for circular and same references on the object graph and return its corresponding clone.
223
+ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,copiedValue);for(var key in value){if(Object.prototype.hasOwnProperty.call(value,key)){copiedValue[key]=deep?_clone(value[key],true,map):value[key];}}return copiedValue;};switch(type(value)){case'Object':return copy(Object.create(Object.getPrototypeOf(value)));case'Array':return copy([]);case'Date':return new Date(value.valueOf());case'RegExp':return _cloneRegExp(value);case'Int8Array':case'Uint8Array':case'Uint8ClampedArray':case'Int16Array':case'Uint16Array':case'Int32Array':case'Uint32Array':case'Float32Array':case'Float64Array':case'BigInt64Array':case'BigUint64Array':return value.slice();default:return value;}}function _isPrimitive(param){var type=typeof param;return param==null||type!='object'&&type!='function';}var _ObjectMap=/*#__PURE__*/function(){function _ObjectMap(){this.map={};this.length=0;}_ObjectMap.prototype.set=function(key,value){const hashedKey=this.hash(key);let bucket=this.map[hashedKey];if(!bucket){this.map[hashedKey]=bucket=[];}bucket.push([key,value]);this.length+=1;};_ObjectMap.prototype.hash=function(key){let hashedKey=[];for(var value in key){hashedKey.push(Object.prototype.toString.call(key[value]));}return hashedKey.join();};_ObjectMap.prototype.get=function(key){/**
224
+ * depending on the number of objects to be cloned is faster to just iterate over the items in the map just because the hash function is so costly,
225
+ * on my tests this number is 180, anything above that using the hash function is faster.
226
+ */if(this.length<=180){for(const p in this.map){const bucket=this.map[p];for(let i=0;i<bucket.length;i+=1){const element=bucket[i];if(element[0]===key){return element[1];}}}return;}const hashedKey=this.hash(key);const bucket=this.map[hashedKey];if(!bucket){return;}for(let i=0;i<bucket.length;i+=1){const element=bucket[i];if(element[0]===key){return element[1];}}};return _ObjectMap;}();
227
+
228
+ /**
229
+ * Creates a deep copy of the source that can be used in place of the source
230
+ * object without retaining any references to it.
231
+ * The source object may contain (nested) `Array`s and `Object`s,
232
+ * `Number`s, `String`s, `Boolean`s and `Date`s.
233
+ * `Function`s are assigned by reference rather than copied.
234
+ *
235
+ * Dispatches to a `clone` method if present.
236
+ *
237
+ * Note that if the source object has multiple nodes that share a reference,
238
+ * the returned object will have the same structure, but the references will
239
+ * be pointed to the location within the cloned value.
240
+ *
241
+ * @func
242
+ * @memberOf R
243
+ * @since v0.1.0
244
+ * @category Object
245
+ * @sig {*} -> {*}
246
+ * @param {*} value The object or array to clone
247
+ * @return {*} A deeply cloned copy of `val`
248
+ * @example
249
+ *
250
+ * const objects = [{}, {}, {}];
251
+ * const objectsClone = R.clone(objects);
252
+ * objects === objectsClone; //=> false
253
+ * objects[0] === objectsClone[0]; //=> false
254
+ */var clone=/*#__PURE__*/_curry1(function clone(value){return value!=null&&typeof value.clone==='function'?value.clone():_clone(value,true);});const clone$1 = clone;
255
+
256
+ /**
257
+ * Tests whether or not an object is a typed array.
258
+ *
259
+ * @private
260
+ * @param {*} val The object to test.
261
+ * @return {Boolean} `true` if `val` is a typed array, `false` otherwise.
262
+ * @example
263
+ *
264
+ * _isTypedArray(new Uint8Array([])); //=> true
265
+ * _isTypedArray(new Float32Array([])); //=> true
266
+ * _isTypedArray([]); //=> false
267
+ * _isTypedArray(null); //=> false
268
+ * _isTypedArray({}); //=> false
269
+ */function _isTypedArray(val){var type=Object.prototype.toString.call(val);return type==='[object Uint8ClampedArray]'||type==='[object Int8Array]'||type==='[object Uint8Array]'||type==='[object Int16Array]'||type==='[object Uint16Array]'||type==='[object Int32Array]'||type==='[object Uint32Array]'||type==='[object Float32Array]'||type==='[object Float64Array]'||type==='[object BigInt64Array]'||type==='[object BigUint64Array]';}
270
+
271
+ /**
272
+ * Returns the empty value of its argument's type. Ramda defines the empty
273
+ * value of Array (`[]`), Object (`{}`), String (`''`),
274
+ * TypedArray (`Uint8Array []`, `Float32Array []`, etc), and Arguments. Other
275
+ * types are supported if they define `<Type>.empty`,
276
+ * `<Type>.prototype.empty` or implement the
277
+ * [FantasyLand Monoid spec](https://github.com/fantasyland/fantasy-land#monoid).
278
+ *
279
+ * Dispatches to the `empty` method of the first argument, if present.
280
+ *
281
+ * @func
282
+ * @memberOf R
283
+ * @since v0.3.0
284
+ * @category Function
285
+ * @sig a -> a
286
+ * @param {*} x
287
+ * @return {*}
288
+ * @example
289
+ *
290
+ * R.empty(Just(42)); //=> Nothing()
291
+ * R.empty([1, 2, 3]); //=> []
292
+ * R.empty('unicorns'); //=> ''
293
+ * R.empty({x: 1, y: 2}); //=> {}
294
+ * R.empty(Uint8Array.from('123')); //=> Uint8Array []
295
+ */var empty=/*#__PURE__*/_curry1(function empty(x){return x!=null&&typeof x['fantasy-land/empty']==='function'?x['fantasy-land/empty']():x!=null&&x.constructor!=null&&typeof x.constructor['fantasy-land/empty']==='function'?x.constructor['fantasy-land/empty']():x!=null&&typeof x.empty==='function'?x.empty():x!=null&&x.constructor!=null&&typeof x.constructor.empty==='function'?x.constructor.empty():_isArray(x)?[]:_isString(x)?'':_isObject(x)?{}:_isArguments(x)?function(){return arguments;}():_isTypedArray(x)?x.constructor.from(''):void 0// else
296
+ ;});
297
+
298
+ /**
299
+ * Returns `true` if the given value is its type's empty value; `false`
300
+ * otherwise.
301
+ *
302
+ * @func
303
+ * @memberOf R
304
+ * @since v0.1.0
305
+ * @category Logic
306
+ * @sig a -> Boolean
307
+ * @param {*} x
308
+ * @return {Boolean}
309
+ * @see R.empty
310
+ * @example
311
+ *
312
+ * R.isEmpty([1, 2, 3]); //=> false
313
+ * R.isEmpty([]); //=> true
314
+ * R.isEmpty(''); //=> true
315
+ * R.isEmpty(null); //=> false
316
+ * R.isEmpty({}); //=> true
317
+ * R.isEmpty({length: 0}); //=> false
318
+ * R.isEmpty(Uint8Array.from('')); //=> true
319
+ */var isEmpty=/*#__PURE__*/_curry1(function isEmpty(x){return x!=null&&equals(x,empty(x));});const isEmpty$1 = isEmpty;
320
+
321
+ /**
322
+ * Retrieves the values at given paths of an object.
323
+ *
324
+ * @func
325
+ * @memberOf R
326
+ * @since v0.27.1
327
+ * @category Object
328
+ * @typedefn Idx = [String | Int | Symbol]
329
+ * @sig [Idx] -> {a} -> [a | Undefined]
330
+ * @param {Array} pathsArray The array of paths to be fetched.
331
+ * @param {Object} obj The object to retrieve the nested properties from.
332
+ * @return {Array} A list consisting of values at paths specified by "pathsArray".
333
+ * @see R.path
334
+ * @example
335
+ *
336
+ * R.paths([['a', 'b'], ['p', 0, 'q']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, 3]
337
+ * R.paths([['a', 'b'], ['p', 'r']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, undefined]
338
+ */var paths=/*#__PURE__*/_curry2(function paths(pathsArray,obj){return pathsArray.map(function(paths){var val=obj;var idx=0;var p;while(idx<paths.length){if(val==null){return;}p=paths[idx];val=_isInteger(p)?nth(p,val):val[p];idx+=1;}return val;});});
339
+
340
+ /**
341
+ * Retrieves the value at a given path. The nodes of the path can be arbitrary strings or non-negative integers.
342
+ * For anything else, the value is unspecified. Integer paths are meant to index arrays, strings are meant for objects.
343
+ *
344
+ * @func
345
+ * @memberOf R
346
+ * @since v0.2.0
347
+ * @category Object
348
+ * @typedefn Idx = String | Int | Symbol
349
+ * @sig [Idx] -> {a} -> a | Undefined
350
+ * @sig Idx = String | NonNegativeInt
351
+ * @param {Array} path The path to use.
352
+ * @param {Object} obj The object or array to retrieve the nested property from.
353
+ * @return {*} The data at `path`.
354
+ * @see R.prop, R.nth, R.assocPath, R.dissocPath
355
+ * @example
356
+ *
357
+ * R.path(['a', 'b'], {a: {b: 2}}); //=> 2
358
+ * R.path(['a', 'b'], {c: {b: 2}}); //=> undefined
359
+ * R.path(['a', 'b', 0], {a: {b: [1, 2, 3]}}); //=> 1
360
+ * R.path(['a', 'b', -2], {a: {b: [1, 2, 3]}}); //=> 2
361
+ * R.path([2], {'2': 2}); //=> 2
362
+ * R.path([-2], {'-2': 'a'}); //=> undefined
363
+ */var path=/*#__PURE__*/_curry2(function path(pathAr,obj){return paths([pathAr],obj)[0];});const path$1 = path;
364
+
365
+ /**
366
+ * Creates a new object with the own properties of the two provided objects. If
367
+ * a key exists in both objects, the provided function is applied to the key
368
+ * and the values associated with the key in each object, with the result being
369
+ * used as the value associated with the key in the returned object.
370
+ *
371
+ * @func
372
+ * @memberOf R
373
+ * @since v0.19.0
374
+ * @category Object
375
+ * @sig ((String, a, a) -> a) -> {a} -> {a} -> {a}
376
+ * @param {Function} fn
377
+ * @param {Object} l
378
+ * @param {Object} r
379
+ * @return {Object}
380
+ * @see R.mergeDeepWithKey, R.merge, R.mergeWith
381
+ * @example
382
+ *
383
+ * let concatValues = (k, l, r) => k == 'values' ? R.concat(l, r) : r
384
+ * R.mergeWithKey(concatValues,
385
+ * { a: true, thing: 'foo', values: [10, 20] },
386
+ * { b: true, thing: 'bar', values: [15, 35] });
387
+ * //=> { a: true, b: true, thing: 'bar', values: [10, 20, 15, 35] }
388
+ * @symb R.mergeWithKey(f, { x: 1, y: 2 }, { y: 5, z: 3 }) = { x: 1, y: f('y', 2, 5), z: 3 }
389
+ */var mergeWithKey=/*#__PURE__*/_curry3(function mergeWithKey(fn,l,r){var result={};var k;l=l||{};r=r||{};for(k in l){if(_has(k,l)){result[k]=_has(k,r)?fn(k,l[k],r[k]):l[k];}}for(k in r){if(_has(k,r)&&!_has(k,result)){result[k]=r[k];}}return result;});
390
+
391
+ /**
392
+ * Creates a new object with the own properties of the two provided objects.
393
+ * If a key exists in both objects:
394
+ * - and both associated values are also objects then the values will be
395
+ * recursively merged.
396
+ * - otherwise the provided function is applied to the key and associated values
397
+ * using the resulting value as the new value associated with the key.
398
+ * If a key only exists in one object, the value will be associated with the key
399
+ * of the resulting object.
400
+ *
401
+ * @func
402
+ * @memberOf R
403
+ * @since v0.24.0
404
+ * @category Object
405
+ * @sig ((String, a, a) -> a) -> {a} -> {a} -> {a}
406
+ * @param {Function} fn
407
+ * @param {Object} lObj
408
+ * @param {Object} rObj
409
+ * @return {Object}
410
+ * @see R.mergeWithKey, R.mergeDeepWith
411
+ * @example
412
+ *
413
+ * let concatValues = (k, l, r) => k == 'values' ? R.concat(l, r) : r
414
+ * R.mergeDeepWithKey(concatValues,
415
+ * { a: true, c: { thing: 'foo', values: [10, 20] }},
416
+ * { b: true, c: { thing: 'bar', values: [15, 35] }});
417
+ * //=> { a: true, b: true, c: { thing: 'bar', values: [10, 20, 15, 35] }}
418
+ */var mergeDeepWithKey=/*#__PURE__*/_curry3(function mergeDeepWithKey(fn,lObj,rObj){return mergeWithKey(function(k,lVal,rVal){if(_isObject(lVal)&&_isObject(rVal)){return mergeDeepWithKey(fn,lVal,rVal);}else {return fn(k,lVal,rVal);}},lObj,rObj);});
419
+
420
+ /**
421
+ * Creates a new object with the own properties of the two provided objects.
422
+ * If a key exists in both objects:
423
+ * - and both associated values are also objects then the values will be
424
+ * recursively merged.
425
+ * - otherwise the provided function is applied to associated values using the
426
+ * resulting value as the new value associated with the key.
427
+ * If a key only exists in one object, the value will be associated with the key
428
+ * of the resulting object.
429
+ *
430
+ * @func
431
+ * @memberOf R
432
+ * @since v0.24.0
433
+ * @category Object
434
+ * @sig ((a, a) -> a) -> {a} -> {a} -> {a}
435
+ * @param {Function} fn
436
+ * @param {Object} lObj
437
+ * @param {Object} rObj
438
+ * @return {Object}
439
+ * @see R.mergeWith, R.mergeDeepWithKey
440
+ * @example
441
+ *
442
+ * R.mergeDeepWith(R.concat,
443
+ * { a: true, c: { values: [10, 20] }},
444
+ * { b: true, c: { values: [15, 35] }});
445
+ * //=> { a: true, b: true, c: { values: [10, 20, 15, 35] }}
446
+ */var mergeDeepWith=/*#__PURE__*/_curry3(function mergeDeepWith(fn,lObj,rObj){return mergeDeepWithKey(function(k,lVal,rVal){return fn(lVal,rVal);},lObj,rObj);});const mergeDeepWith$1 = mergeDeepWith;
447
+
448
+ /**
449
+ * Returns a partial copy of an object containing only the keys that satisfy
450
+ * the supplied predicate.
451
+ *
452
+ * @func
453
+ * @memberOf R
454
+ * @since v0.8.0
455
+ * @category Object
456
+ * @sig ((v, k) -> Boolean) -> {k: v} -> {k: v}
457
+ * @param {Function} pred A predicate to determine whether or not a key
458
+ * should be included on the output object.
459
+ * @param {Object} obj The object to copy from
460
+ * @return {Object} A new object with only properties that satisfy `pred`
461
+ * on it.
462
+ * @see R.pick, R.filter
463
+ * @example
464
+ *
465
+ * const isUpperCase = (val, key) => key.toUpperCase() === key;
466
+ * R.pickBy(isUpperCase, {a: 1, b: 2, A: 3, B: 4}); //=> {A: 3, B: 4}
467
+ */var pickBy=/*#__PURE__*/_curry2(function pickBy(test,obj){var result={};for(var prop in obj){if(test(obj[prop],prop,obj)){result[prop]=obj[prop];}}return result;});const pickBy$1 = pickBy;
468
+
469
+ /**
470
+ * A function to check given value is a function
471
+ * @param value input value
472
+ * @returns boolean
473
+ */const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&value.call&&value.apply);/**
474
+ * A function to check given value is a string
475
+ * @param value input value
476
+ * @returns boolean
477
+ */const isString=value=>typeof value==='string';/**
478
+ * A function to check given value is null or not
479
+ * @param value input value
480
+ * @returns boolean
481
+ */const isNull=value=>value===null;/**
482
+ * A function to check given value is undefined
483
+ * @param value input value
484
+ * @returns boolean
485
+ */const isUndefined=value=>typeof value==='undefined';/**
486
+ * A function to check given value is null or undefined
487
+ * @param value input value
488
+ * @returns boolean
489
+ */const isNullOrUndefined=value=>isNull(value)||isUndefined(value);/**
490
+ * A function to check given value is defined
491
+ * @param value input value
492
+ * @returns boolean
493
+ */const isDefined=value=>!isUndefined(value);/**
494
+ * A function to check given value is defined and not null
495
+ * @param value input value
496
+ * @returns boolean
497
+ */const isDefinedAndNotNull=value=>!isNullOrUndefined(value);/**
498
+ * Determines if the input is an instance of Error
499
+ * @param obj input value
500
+ * @returns true if the input is an instance of Error and false otherwise
501
+ */const isTypeOfError=obj=>obj instanceof Error;
502
+
503
+ const getValueByPath=(obj,keyPath)=>{const pathParts=keyPath.split('.');return path$1(pathParts,obj);};const hasValueByPath=(obj,path)=>Boolean(getValueByPath(obj,path));/**
504
+ * Checks if the input is an object literal or built-in object type and not null
505
+ * @param value Input value
506
+ * @returns true if the input is an object and not null
507
+ */const isObjectAndNotNull=value=>!isNull(value)&&typeof value==='object'&&!Array.isArray(value);/**
508
+ * Checks if the input is an object literal and not null
509
+ * @param value Input value
510
+ * @returns true if the input is an object and not null
511
+ */const isObjectLiteralAndNotNull=value=>!isNull(value)&&Object.prototype.toString.call(value)==='[object Object]';const mergeDeepRightObjectArrays=(leftValue,rightValue)=>{if(!Array.isArray(leftValue)||!Array.isArray(rightValue)){return clone$1(rightValue);}const mergedArray=clone$1(leftValue);rightValue.forEach((value,index)=>{mergedArray[index]=Array.isArray(value)||isObjectAndNotNull(value)?// eslint-disable-next-line @typescript-eslint/no-use-before-define
512
+ mergeDeepRight(mergedArray[index],value):value;});return mergedArray;};const mergeDeepRight=(leftObject,rightObject)=>mergeDeepWith$1(mergeDeepRightObjectArrays,leftObject,rightObject);/**
513
+ Checks if the input is a non-empty object literal type and not undefined or null
514
+ * @param value input any
515
+ * @returns boolean
516
+ */const isNonEmptyObject=value=>isObjectLiteralAndNotNull(value)&&Object.keys(value).length>0;/**
517
+ * A utility to recursively remove undefined values from an object
518
+ * @param obj input object
519
+ * @returns a new object
520
+ */const removeUndefinedValues=obj=>{const result=pickBy$1(isDefined,obj);Object.entries(result).forEach(([key,value])=>{if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedValues(value);}});return result;};/**
521
+ * A utility to recursively remove undefined and null values from an object
522
+ * @param obj input object
523
+ * @returns a new object
524
+ */const removeUndefinedAndNullValues=obj=>{const result=pickBy$1(isDefinedAndNotNull,obj);Object.entries(result).forEach(([key,value])=>{if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};
525
+
526
+ const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value=>value.replace(/ {2,}/g,' ');/**
527
+ * A function to convert values to string
528
+ * @param val input value
529
+ * @returns stringified value
530
+ */const tryStringify=val=>{let retVal=val;if(!isString(val)&&!isNullOrUndefined(val)){try{retVal=JSON.stringify(val);}catch(e){retVal=null;}}return retVal;};// The following text encoding and decoding is done before base64 encoding to prevent
531
+ /**
532
+ * Converts a bytes array to base64 encoded string
533
+ * @param bytes bytes array to be converted to base64
534
+ * @returns base64 encoded string
535
+ */const bytesToBase64=bytes=>{const binString=Array.from(bytes,x=>String.fromCodePoint(x)).join('');return globalThis.btoa(binString);};/**
536
+ * Encodes a string to base64 even with unicode characters
537
+ * @param value input string
538
+ * @returns base64 encoded string
539
+ */const toBase64=value=>bytesToBase64(new TextEncoder().encode(value));
540
+
541
+ // if yes make them null instead of omitting in overloaded cases
542
+ /*
543
+ * Normalise the overloaded arguments of the page call facade
544
+ */const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const payload={};if(isFunction(callback)){payload.category=category;payload.name=name;payload.properties=clone$1(properties);payload.options=clone$1(options);payload.callback=callback;}if(isFunction(options)){payload.category=category;payload.name=name;payload.properties=clone$1(properties);payload.callback=options;}if(isFunction(properties)){payload.category=category;payload.name=name;payload.callback=properties;}if(isFunction(name)){payload.category=category;payload.callback=name;}if(isFunction(category)){payload.callback=category;}if(isObjectLiteralAndNotNull(category)){payload.options=clone$1(name);payload.properties=clone$1(category);delete payload.name;delete payload.category;}else if(isObjectLiteralAndNotNull(name)){payload.options=clone$1(properties);payload.properties=clone$1(name);delete payload.name;}if(isObjectLiteralAndNotNull(options)&&!isString(payload.options)){payload.options=options;}if(isObjectLiteralAndNotNull(properties)&&!isString(payload.properties)&&!isObjectLiteralAndNotNull(name)){payload.properties=properties;}if(isString(category)&&!isString(payload.category)){payload.category=category;}if(isString(name)&&!isString(payload.name)){payload.name=name;}if(isString(payload.category)&&!isString(payload.name)){payload.name=payload.category;delete payload.category;}if(isUndefined(payload.category)){delete payload.category;}payload.properties=mergeDeepRight(payload.properties&&isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{name:isString(payload.name)?payload.name:null,category:isString(payload.category)?payload.category:null});return payload;};/*
545
+ * Normalise the overloaded arguments of the track call facade
546
+ */const trackArgumentsToCallOptions=(event,properties,options,callback)=>{const payload={name:event};if(isFunction(callback)){payload.properties=clone$1(properties);payload.options=clone$1(options);payload.callback=callback;}if(isFunction(options)){payload.properties=clone$1(properties);payload.callback=options;}if(isFunction(properties)){payload.callback=properties;}if(isObjectLiteralAndNotNull(options)||isNull(options)){payload.options=options;}if(isObjectLiteralAndNotNull(properties)||isNull(properties)){payload.properties=properties;}// To match v1.1 generated payload
547
+ if(isUndefined(payload.properties)||isNull(payload.properties)){payload.properties={};}return payload;};/*
548
+ * Normalise the overloaded arguments of the identify call facade
549
+ */const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const payload={};if(isFunction(callback)){payload.traits=clone$1(traits);payload.options=clone$1(options);payload.callback=callback;}if(isFunction(options)){payload.traits=clone$1(traits);payload.callback=options;}if(isFunction(traits)){payload.callback=traits;}if(isObjectLiteralAndNotNull(userId)||isNull(userId)){delete payload.userId;payload.traits=clone$1(userId);payload.options=clone$1(traits);}else {payload.userId=tryStringify(userId);if(!isUndefined(traits)&&!isFunction(traits)){payload.traits=clone$1(traits);}if(!isUndefined(options)&&!isFunction(options)){payload.options=clone$1(options);}}return payload;};/*
550
+ * Normalise the overloaded arguments of the alias call facade
551
+ */const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const payload={};if(isFunction(callback)){payload.to=tryStringify(to)??null;payload.from=from;payload.options=clone$1(options);payload.callback=callback;}if(isFunction(options)){payload.to=tryStringify(to)??null;payload.from=from;payload.callback=options;}if(isFunction(from)){payload.to=tryStringify(to)??null;payload.callback=from;}else if(isObjectLiteralAndNotNull(from)||isNull(from)){payload.to=tryStringify(to)??null;payload.options=isNull(from)?null:clone$1(from);delete payload.from;}else {payload.to=tryStringify(to)??null;payload.from=tryStringify(from);}if(isFunction(to)){payload.to=null;payload.callback=to;}if(isObjectLiteralAndNotNull(to)){payload.to=null;payload.options=clone$1(to);}return payload;};/*
552
+ * Normalise the overloaded arguments of the group call facade
553
+ */const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const payload={};if(isFunction(callback)){payload.traits=clone$1(traits);payload.options=clone$1(options);payload.callback=callback;}if(isFunction(options)){payload.traits=clone$1(traits);payload.callback=options;}if(isFunction(traits)){payload.callback=traits;}// TODO: why do we enable overload for group that only passes callback? is there any use case?
554
+ if(isFunction(groupId)){payload.callback=groupId;}else if(isObjectLiteralAndNotNull(groupId)||isNull(groupId)){payload.traits=isNull(groupId)?undefined:clone$1(groupId);if(isFunction(traits)){payload.callback=traits;}else {payload.options=clone$1(traits);}}else {payload.groupId=tryStringify(groupId);payload.traits=!isObjectLiteralAndNotNull(traits)?undefined:clone$1(traits);payload.options=!isObjectLiteralAndNotNull(options)?undefined:clone$1(options);}return payload;};
555
+
556
+ const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
557
+
558
+ /**
559
+ * Create globally accessible RudderStackGlobals object
560
+ */const createExposedGlobals=(analyticsInstanceId='app')=>{if(!globalThis.RudderStackGlobals){globalThis.RudderStackGlobals={};}if(!globalThis.RudderStackGlobals[analyticsInstanceId]){globalThis.RudderStackGlobals[analyticsInstanceId]={};}};/**
561
+ * Add move values to globally accessible RudderStackGlobals object per analytics instance
562
+ */const setExposedGlobal=(keyName,value,analyticsInstanceId='app')=>{createExposedGlobals(analyticsInstanceId);globalThis.RudderStackGlobals[analyticsInstanceId][keyName]=value;};/**
563
+ * Get values from globally accessible RudderStackGlobals object by analytics instance
564
+ */const getExposedGlobal=(keyName,analyticsInstanceId='app')=>{createExposedGlobals(analyticsInstanceId);return globalThis.RudderStackGlobals[analyticsInstanceId][keyName];};
565
+
566
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';
567
+
568
+ /**
569
+ * Parse query string params into object values for keys that start with a defined prefix
570
+ */const getEventDataFromQueryString=(params,dataTypeNamePrefix)=>{const data={};params.forEach((value,key)=>{if(key.startsWith(dataTypeNamePrefix)){// remove prefix from key name
571
+ const dataKey=key.substring(dataTypeNamePrefix.length);// add new key value pair in generated object
572
+ data[dataKey]=params.get(key);}});return data;};/**
573
+ * Parse query string into preload buffer events & push into existing array before any other events
574
+ */const retrieveEventsFromQueryString=(argumentsArray=[])=>{// Mapping for trait and properties values based on key prefix
575
+ const eventArgumentToQueryParamMap={trait:QUERY_PARAM_TRAIT_PREFIX,properties:QUERY_PARAM_PROPERTY_PREFIX};const queryObject=new URLSearchParams(globalThis.location.search);// Add track events with name and properties
576
+ if(queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY)){argumentsArray.unshift(['track',queryObject.get(QUERY_PARAM_TRACK_EVENT_NAME_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.properties)]);}// Set userId and user traits
577
+ if(queryObject.get(QUERY_PARAM_USER_ID_KEY)){argumentsArray.unshift(['identify',queryObject.get(QUERY_PARAM_USER_ID_KEY),getEventDataFromQueryString(queryObject,eventArgumentToQueryParamMap.trait)]);}// Set anonymousID
578
+ if(queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)){argumentsArray.unshift(['setAnonymousId',queryObject.get(QUERY_PARAM_ANONYMOUS_ID_KEY)]);}};/**
579
+ * Retrieve an existing buffered load method call and remove from the existing array
580
+ */const getPreloadedLoadEvent=preloadedEventsArray=>{const loadMethodName='load';let loadEvent=[];/**
581
+ * Iterate the buffered API calls until we find load call and process it separately
582
+ */let i=0;while(i<preloadedEventsArray.length){if(preloadedEventsArray[i]&&preloadedEventsArray[i][0]===loadMethodName){loadEvent=preloadedEventsArray[i];preloadedEventsArray.splice(i,1);break;}i+=1;}return loadEvent;};/**
583
+ * Retrieve any existing events that were triggered before SDK load and enqueue in buffer
584
+ */const retrievePreloadBufferEvents=instance=>{const preloadedEventsArray=getExposedGlobal(GLOBAL_PRELOAD_BUFFER)||[];// Get events that are pre-populated via query string params
585
+ retrieveEventsFromQueryString(preloadedEventsArray);const sanitizedPreloadedEventsArray=preloadedEventsArray.filter(bufferedEvent=>bufferedEvent[0]!=='load');// Enqueue the non load events in the buffer of the global rudder analytics singleton
586
+ if(sanitizedPreloadedEventsArray.length>0){instance.enqueuePreloadBufferEvents(sanitizedPreloadedEventsArray);setExposedGlobal(GLOBAL_PRELOAD_BUFFER,[]);}};const consumePreloadBufferedEvent=(event,analyticsInstance)=>{const methodName=event.shift();let callOptions;if(isFunction(analyticsInstance[methodName])){switch(methodName){case'page':callOptions=pageArgumentsToCallOptions(...event);break;case'track':callOptions=trackArgumentsToCallOptions(...event);break;case'identify':callOptions=identifyArgumentsToCallOptions(...event);break;case'alias':callOptions=aliasArgumentsToCallOptions(...event);break;case'group':callOptions=groupArgumentsToCallOptions(...event);break;default:analyticsInstance[methodName](...event);break;}if(callOptions){analyticsInstance[methodName](callOptions);}}};
587
+
588
+ const LOG_LEVEL_MAP={[LogLevel.Log]:0,[LogLevel.Info]:1,[LogLevel.Debug]:2,[LogLevel.Warn]:3,[LogLevel.Error]:4,[LogLevel.None]:5};const DEFAULT_LOG_LEVEL=LogLevel.Error;const LOG_MSG_PREFIX='RS SDK';const LOG_MSG_PREFIX_STYLE='font-weight: bold; background: black; color: white;';const LOG_MSG_STYLE='font-weight: normal;';/**
589
+ * Service to log messages/data to output provider, default is console
590
+ */class Logger{constructor(minLogLevel=DEFAULT_LOG_LEVEL,scope='',logProvider=console){this.minLogLevel=LOG_LEVEL_MAP[minLogLevel];this.scope=scope;this.logProvider=logProvider;}log(...data){this.outputLog(LogLevel.Log,data);}info(...data){this.outputLog(LogLevel.Info,data);}debug(...data){this.outputLog(LogLevel.Debug,data);}warn(...data){this.outputLog(LogLevel.Warn,data);}error(...data){this.outputLog(LogLevel.Error,data);}outputLog(logMethod,data){if(this.minLogLevel<=LOG_LEVEL_MAP[logMethod]){this.logProvider[logMethod.toLowerCase()](...this.formatLogData(data));}}setScope(scopeVal){this.scope=scopeVal||this.scope;}// TODO: should we allow to change the level via global variable on run time
591
+ // to assist on the fly debugging?
592
+ setMinLogLevel(logLevel){this.minLogLevel=LOG_LEVEL_MAP[logLevel];if(isUndefined(this.minLogLevel)){this.minLogLevel=LOG_LEVEL_MAP[DEFAULT_LOG_LEVEL];}}/**
593
+ * Formats the console message using `scope` and styles
594
+ */formatLogData(data){if(Array.isArray(data)&&data.length>0){// prefix SDK identifier
595
+ let msg=`%c ${LOG_MSG_PREFIX}`;// format the log message using `scope`
596
+ if(this.scope){msg=`${msg} - ${this.scope}`;}// trim whitespaces for original message
597
+ const originalMsg=isString(data[0])?data[0].trim():'';// prepare the final message
598
+ msg=`${msg} %c ${originalMsg}`;const styledLogArgs=[msg,LOG_MSG_PREFIX_STYLE,// add style for the prefix
599
+ LOG_MSG_STYLE// reset the style for the actual message
600
+ ];// add first it if it was not a string msg
601
+ if(!isString(data[0])){styledLogArgs.push(data[0]);}// append rest of the original arguments
602
+ styledLogArgs.push(...data.slice(1));return styledLogArgs;}return data;}}const defaultLogger=new Logger();
603
+
604
+ const CAPABILITIES_MANAGER='CapabilitiesManager';const CONFIG_MANAGER='ConfigManager';const EVENT_MANAGER='EventManager';const PLUGINS_MANAGER='PluginsManager';const USER_SESSION_MANAGER='UserSessionManager';const ERROR_HANDLER='ErrorHandler';const PLUGIN_ENGINE='PluginEngine';const STORE_MANAGER='StoreManager';const READY_API='readyApi';const LOAD_CONFIGURATION='LoadConfiguration';const EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';
605
+
606
+ const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
607
+
608
+ const SOURCE_CONFIG_OPTION_ERROR=`"getSourceConfig" must be a function. Please make sure that it is defined and returns a valid source configuration object.`;const INTG_CDN_BASE_URL_ERROR=`Failed to load the SDK as the CDN base URL for integrations is not valid.`;const PLUGINS_CDN_BASE_URL_ERROR=`Failed to load the SDK as the CDN base URL for plugins is not valid.`;const DATA_PLANE_URL_ERROR=`Failed to load the SDK as the data plane URL could not be determined. Please check that the data plane URL is set correctly and try again.`;const XHR_PAYLOAD_PREP_ERROR=`Failed to prepare data for the request.`;const EVENT_OBJECT_GENERATION_ERROR=`Failed to generate the event object.`;const PLUGIN_EXT_POINT_MISSING_ERROR=`Failed to invoke plugin because the extension point name is missing.`;const PLUGIN_EXT_POINT_INVALID_ERROR=`Failed to invoke plugin because the extension point name is invalid.`;// ERROR
609
+ const UNSUPPORTED_CONSENT_MANAGER_ERROR=(context,selectedConsentManager,consentManagersToPluginNameMap)=>`${context}${LOG_CONTEXT_SEPARATOR}The consent manager "${selectedConsentManager}" is not supported. Please choose one of the following supported consent managers: "${Object.keys(consentManagersToPluginNameMap)}".`;const REPORTING_PLUGIN_INIT_FAILURE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to initialize the error reporting plugin.`;const NOTIFY_FAILURE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to notify the error.`;const PLUGIN_NAME_MISSING_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin name is missing.`;const PLUGIN_ALREADY_EXISTS_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" already exists.`;const PLUGIN_NOT_FOUND_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" not found.`;const PLUGIN_ENGINE_BUG_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" not found in plugins but found in byName. This indicates a bug in the plugin engine. Please report this issue to the development team.`;const PLUGIN_DEPS_ERROR=(context,pluginName,notExistDeps)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" could not be loaded because some of its dependencies "${notExistDeps}" do not exist.`;const PLUGIN_INVOCATION_ERROR=(context,extPoint,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to invoke the "${extPoint}" extension point of plugin "${pluginName}".`;const STORAGE_UNAVAILABILITY_ERROR_PREFIX=(context,storageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The "${storageType}" storage type is `;const SOURCE_CONFIG_FETCH_ERROR=reason=>`Failed to fetch the source config. Reason: ${reason}`;const WRITE_KEY_VALIDATION_ERROR=writeKey=>`The write key "${writeKey}" is invalid. It must be a non-empty string. Please check that the write key is correct and try again.`;const DATA_PLANE_URL_VALIDATION_ERROR=dataPlaneUrl=>`The data plane URL "${dataPlaneUrl}" is invalid. It must be a valid URL string. Please check that the data plane URL is correct and try again.`;const READY_API_CALLBACK_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}The callback is not a function.`;const XHR_DELIVERY_ERROR=(prefix,status,statusText,url)=>`${prefix} with status: ${status}, ${statusText} for URL: ${url}.`;const XHR_REQUEST_ERROR=(prefix,e,url)=>`${prefix} due to timeout or no connection (${e?e.type:''}) for URL: ${url}.`;const XHR_SEND_ERROR=(prefix,url)=>`${prefix} for URL: ${url}`;const STORE_DATA_SAVE_ERROR=key=>`Failed to save the value for "${key}" to storage`;const STORE_DATA_FETCH_ERROR=key=>`Failed to retrieve or parse data for "${key}" from storage`;// WARNING
610
+ const UNSUPPORTED_ERROR_REPORTING_PROVIDER_WARNING=(context,selectedErrorReportingProvider,errorReportingProvidersToPluginNameMap,defaultProvider)=>`${context}${LOG_CONTEXT_SEPARATOR}The error reporting provider "${selectedErrorReportingProvider}" is not supported. Please choose one of the following supported providers: "${Object.keys(errorReportingProvidersToPluginNameMap)}". The default provider "${defaultProvider}" will be used instead.`;const UNSUPPORTED_STORAGE_ENCRYPTION_VERSION_WARNING=(context,selectedStorageEncryptionVersion,storageEncryptionVersionsToPluginNameMap,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage encryption version "${selectedStorageEncryptionVersion}" is not supported. Please choose one of the following supported versions: "${Object.keys(storageEncryptionVersionsToPluginNameMap)}". The default version "${defaultVersion}" will be used instead.`;const STORAGE_DATA_MIGRATION_OVERRIDE_WARNING=(context,storageEncryptionVersion,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage data migration has been disabled because the configured storage encryption version (${storageEncryptionVersion}) is not the latest (${defaultVersion}). To enable storage data migration, please update the storage encryption version to the latest version.`;const UNSUPPORTED_RESIDENCY_SERVER_REGION_WARNING=(context,selectedResidencyServerRegion,defaultRegion)=>`${context}${LOG_CONTEXT_SEPARATOR}The residency server region "${selectedResidencyServerRegion}" is not supported. Please choose one of the following supported regions: "${Object.values(ResidencyServerRegion)}". The default region "${defaultRegion}" will be used instead.`;const RESERVED_KEYWORD_WARNING=(context,property,parentKeyPath,reservedElements)=>`${context}${LOG_CONTEXT_SEPARATOR}The "${property}" property defined under "${parentKeyPath}" is a reserved keyword. Please choose a different property name to avoid conflicts with reserved keywords (${reservedElements}).`;const INVALID_CONTEXT_OBJECT_WARNING=logContext=>`${logContext}${LOG_CONTEXT_SEPARATOR}Please make sure that the "context" property in the event API's "options" argument is a valid object literal with key-value pairs.`;const UNSUPPORTED_BEACON_API_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The Beacon API is not supported by your browser. The events will be sent using XHR instead.`;const TIMEOUT_NOT_NUMBER_WARNING=(context,timeout,defaultValue)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value "${timeout}" is not a number. The default timeout of ${defaultValue} ms will be used instead.`;const TIMEOUT_ZERO_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value is 0, which disables the automatic session tracking feature. If you want to enable session tracking, please provide a positive integer value for the timeout.`;const TIMEOUT_NOT_RECOMMENDED_WARNING=(context,timeout,minTimeout)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value ${timeout} ms is less than the recommended minimum of ${minTimeout} ms. Please consider increasing the timeout value to ensure optimal performance and reliability.`;const INVALID_SESSION_ID_WARNING=(context,sessionId,minSessionIdLength)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided session ID (${sessionId}) is either invalid, not a positive integer, or not at least "${minSessionIdLength}" digits long. A new session ID will be auto-generated instead.`;const STORAGE_QUOTA_EXCEEDED_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The storage is either full or unavailable, so the data will not be persisted. Switching to in-memory storage.`;const STORAGE_UNAVAILABLE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}No storage is available. The SDK will be initialized without storage.`;// DEBUG
611
+
612
+ // to next or return the value if it is the last one instead of an array per
613
+ // plugin that is the normal invoke
614
+ // TODO: add invoke method for extension point that we know only one plugin can be used. add invokeMultiple and invokeSingle methods
615
+ class PluginEngine{plugins=[];byName={};cache={};config={throws:true};constructor(options={},logger){this.config={throws:true,...options};this.logger=logger;}register(plugin,state){if(!plugin.name){const errorMessage=PLUGIN_NAME_MISSING_ERROR(PLUGIN_ENGINE);if(this.config.throws){throw new Error(errorMessage);}else {this.logger?.error(errorMessage,plugin);}}if(this.byName[plugin.name]){const errorMessage=PLUGIN_ALREADY_EXISTS_ERROR(PLUGIN_ENGINE,plugin.name);if(this.config.throws){throw new Error(errorMessage);}else {this.logger?.error(errorMessage);}}this.cache={};this.plugins=this.plugins.slice();let pos=this.plugins.length;this.plugins.forEach((pluginItem,index)=>{if(pluginItem.deps?.includes(plugin.name)){pos=Math.min(pos,index);}});this.plugins.splice(pos,0,plugin);this.byName[plugin.name]=plugin;if(plugin.initialize&&isFunction(plugin.initialize)){plugin.initialize(state);}}unregister(name){const plugin=this.byName[name];if(!plugin){const errorMessage=PLUGIN_NOT_FOUND_ERROR(PLUGIN_ENGINE,name);if(this.config.throws){throw new Error(errorMessage);}else {this.logger?.error(errorMessage);}}const index=this.plugins.indexOf(plugin);if(index===-1){const errorMessage=PLUGIN_ENGINE_BUG_ERROR(PLUGIN_ENGINE,name);if(this.config.throws){throw new Error(errorMessage);}else {this.logger?.error(errorMessage);}}this.cache={};delete this.byName[name];this.plugins=this.plugins.slice();this.plugins.splice(index,1);}getPlugin(name){return this.byName[name];}getPlugins(extPoint){const lifeCycleName=extPoint??'.';if(!this.cache[lifeCycleName]){this.cache[lifeCycleName]=this.plugins.filter(plugin=>{if(plugin.deps?.some(dependency=>!this.byName[dependency])){// If deps not exist, then not load it.
616
+ const notExistDeps=plugin.deps.filter(dependency=>!this.byName[dependency]);this.logger?.error(PLUGIN_DEPS_ERROR(PLUGIN_ENGINE,plugin.name,notExistDeps));return false;}return lifeCycleName==='.'?true:hasValueByPath(plugin,lifeCycleName);});}return this.cache[lifeCycleName];}// This method allows to process this.plugins so that it could
617
+ // do some unified pre-process before application starts.
618
+ processRawPlugins(callback){callback(this.plugins);this.cache={};}invoke(extPoint,allowMultiple=true,...args){let extensionPointName=extPoint;if(!extensionPointName){throw new Error(PLUGIN_EXT_POINT_MISSING_ERROR);}const noCall=extensionPointName.startsWith('!');const throws=this.config.throws??extensionPointName.endsWith('!');// eslint-disable-next-line unicorn/better-regex
619
+ extensionPointName=extensionPointName.replace(/(^!|!$)/g,'');if(!extensionPointName){throw new Error(PLUGIN_EXT_POINT_INVALID_ERROR);}const extensionPointNameParts=extensionPointName.split('.');extensionPointNameParts.pop();const pluginMethodPath=extensionPointNameParts.join('.');const pluginsToInvoke=allowMultiple?this.getPlugins(extensionPointName):[this.getPlugins(extensionPointName)[0]];return pluginsToInvoke.map(plugin=>{const method=getValueByPath(plugin,extensionPointName);if(!isFunction(method)||noCall){return method;}try{return method.apply(getValueByPath(plugin,pluginMethodPath),args);}catch(err){// When a plugin failed, doesn't break the app
620
+ if(throws){throw err;}else {this.logger?.error(PLUGIN_INVOCATION_ERROR(PLUGIN_ENGINE,extensionPointName,plugin.name),err);}}return null;});}invokeSingle(extPoint,...args){return this.invoke(extPoint,false,...args)[0];}invokeMultiple(extPoint,...args){return this.invoke(extPoint,true,...args);}}const defaultPluginEngine=new PluginEngine({throws:true},defaultLogger);
621
+
622
+ function i(){throw new Error("Cycle detected");}function t(){if(!(h>1)){var i,t=!1;while(void 0!==n){var o=n;n=void 0;s++;while(void 0!==o){var r=o.o;o.o=void 0;o.f&=-3;if(!(8&o.f)&&c(o))try{o.c();}catch(o){if(!t){i=o;t=!0;}}o=r;}}s=0;h--;if(t)throw i;}else h--;}function o(i){if(h>0)return i();h++;try{return i();}finally{t();}}var r=void 0,n=void 0,h=0,s=0,f=0;function v(i){if(void 0!==r){var t=i.n;if(void 0===t||t.t!==r){t={i:0,S:i,p:r.s,n:void 0,t:r,e:void 0,x:void 0,r:t};if(void 0!==r.s)r.s.n=t;r.s=t;i.n=t;if(32&r.f)i.S(t);return t;}else if(-1===t.i){t.i=0;if(void 0!==t.n){t.n.p=t.p;if(void 0!==t.p)t.p.n=t.n;t.p=r.s;t.n=void 0;r.s.n=t;r.s=t;}return t;}}}function e(i){this.v=i;this.i=0;this.n=void 0;this.t=void 0;}e.prototype.h=function(){return !0;};e.prototype.S=function(i){if(this.t!==i&&void 0===i.e){i.x=this.t;if(void 0!==this.t)this.t.e=i;this.t=i;}};e.prototype.U=function(i){if(void 0!==this.t){var t=i.e,o=i.x;if(void 0!==t){t.x=o;i.e=void 0;}if(void 0!==o){o.e=t;i.x=void 0;}if(i===this.t)this.t=o;}};e.prototype.subscribe=function(i){var t=this;return b(function(){var o=t.value,r=32&this.f;this.f&=-33;try{i(o);}finally{this.f|=r;}});};e.prototype.valueOf=function(){return this.value;};e.prototype.toString=function(){return this.value+"";};e.prototype.toJSON=function(){return this.value;};e.prototype.peek=function(){return this.v;};Object.defineProperty(e.prototype,"value",{get:function(){var i=v(this);if(void 0!==i)i.i=this.i;return this.v;},set:function(o){if(r instanceof l)!function(){throw new Error("Computed cannot have side-effects");}();if(o!==this.v){if(s>100)i();this.v=o;this.i++;f++;h++;try{for(var n=this.t;void 0!==n;n=n.x)n.t.N();}finally{t();}}}});function u(i){return new e(i);}function c(i){for(var t=i.s;void 0!==t;t=t.n)if(t.S.i!==t.i||!t.S.h()||t.S.i!==t.i)return !0;return !1;}function d(i){for(var t=i.s;void 0!==t;t=t.n){var o=t.S.n;if(void 0!==o)t.r=o;t.S.n=t;t.i=-1;if(void 0===t.n){i.s=t;break;}}}function a(i){var t=i.s,o=void 0;while(void 0!==t){var r=t.p;if(-1===t.i){t.S.U(t);if(void 0!==r)r.n=t.n;if(void 0!==t.n)t.n.p=r;}else o=t;t.S.n=t.r;if(void 0!==t.r)t.r=void 0;t=r;}i.s=o;}function l(i){e.call(this,void 0);this.x=i;this.s=void 0;this.g=f-1;this.f=4;}(l.prototype=new e()).h=function(){this.f&=-3;if(1&this.f)return !1;if(32==(36&this.f))return !0;this.f&=-5;if(this.g===f)return !0;this.g=f;this.f|=1;if(this.i>0&&!c(this)){this.f&=-2;return !0;}var i=r;try{d(this);r=this;var t=this.x();if(16&this.f||this.v!==t||0===this.i){this.v=t;this.f&=-17;this.i++;}}catch(i){this.v=i;this.f|=16;this.i++;}r=i;a(this);this.f&=-2;return !0;};l.prototype.S=function(i){if(void 0===this.t){this.f|=36;for(var t=this.s;void 0!==t;t=t.n)t.S.S(t);}e.prototype.S.call(this,i);};l.prototype.U=function(i){if(void 0!==this.t){e.prototype.U.call(this,i);if(void 0===this.t){this.f&=-33;for(var t=this.s;void 0!==t;t=t.n)t.S.U(t);}}};l.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var i=this.t;void 0!==i;i=i.x)i.t.N();}};l.prototype.peek=function(){if(!this.h())i();if(16&this.f)throw this.v;return this.v;};Object.defineProperty(l.prototype,"value",{get:function(){if(1&this.f)i();var t=v(this);this.h();if(void 0!==t)t.i=this.i;if(16&this.f)throw this.v;return this.v;}});function y(i){var o=i.u;i.u=void 0;if("function"==typeof o){h++;var n=r;r=void 0;try{o();}catch(t){i.f&=-2;i.f|=8;_(i);throw t;}finally{r=n;t();}}}function _(i){for(var t=i.s;void 0!==t;t=t.n)t.S.U(t);i.x=void 0;i.s=void 0;y(i);}function p(i){if(r!==this)throw new Error("Out-of-order effect");a(this);r=i;this.f&=-2;if(8&this.f)_(this);t();}function g(i){this.x=i;this.u=void 0;this.s=void 0;this.o=void 0;this.f=32;}g.prototype.c=function(){var i=this.S();try{if(8&this.f)return;if(void 0===this.x)return;var t=this.x();if("function"==typeof t)this.u=t;}finally{i();}};g.prototype.S=function(){if(1&this.f)i();this.f|=1;this.f&=-9;y(this);d(this);h++;var t=r;r=this;return p.bind(this,t);};g.prototype.N=function(){if(!(2&this.f)){this.f|=2;this.o=n;n=this;}};g.prototype.d=function(){this.f|=8;if(!(1&this.f))_(this);};function b(i){var t=new g(i);try{t.c();}catch(i){t.d();throw i;}return t.d.bind(t);}
623
+
624
+ const BUILD_TYPE='modern';const SDK_CDN_BASE_URL='https://cdn.rudderlabs.com';const CDN_ARCH_VERSION_DIR='v3';const CDN_INT_DIR='js-integrations';const CDN_PLUGINS_DIR='plugins';const DEST_SDK_BASE_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/latest/${BUILD_TYPE}/${CDN_INT_DIR}`;const PLUGINS_BASE_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/latest/${BUILD_TYPE}/${CDN_PLUGINS_DIR}`;const DEFAULT_CONFIG_BE_URL='https://api.rudderstack.com';
625
+
626
+ const DEFAULT_XHR_TIMEOUT=10*1000;// 10 seconds
627
+ const DEFAULT_COOKIE_MAX_AGE=31536000*1000;// 1 year
628
+ const DEFAULT_SESSION_TIMEOUT=30*60*1000;// 30 minutes
629
+ const MIN_SESSION_TIMEOUT=10*1000;// 10 seconds
630
+
631
+ let StorageEncryptionVersion=/*#__PURE__*/function(StorageEncryptionVersion){StorageEncryptionVersion["Legacy"]="legacy";StorageEncryptionVersion["V3"]="v3";return StorageEncryptionVersion;}({});// default
632
+
633
+ const DEFAULT_ERROR_REPORTING_PROVIDER='bugsnag';const DEFAULT_STORAGE_ENCRYPTION_VERSION=StorageEncryptionVersion.V3;const ConsentManagersToPluginNameMap={oneTrust:PluginName.OneTrustConsentManager,ketch:PluginName.KetchConsentManager};const ErrorReportingProvidersToPluginNameMap={[DEFAULT_ERROR_REPORTING_PROVIDER]:PluginName.Bugsnag};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:PluginName.StorageEncryption,[StorageEncryptionVersion.Legacy]:PluginName.StorageEncryptionLegacy};
634
+
635
+ const defaultLoadOptions={logLevel:LogLevel.Error,configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT},sameSiteCookie:CookieSameSite.Lax,polyfillIfRequired:true,integrations:{All:true},useBeacon:false,lockIntegrationsVersion:false,uaChTrackLevel:UaChTrackLevel.None,plugins:[],useGlobalIntegrationsConfigInEvents:false,bufferDataPlaneEventsUntilReady:false,storage:{encryption:{version:DEFAULT_STORAGE_ENCRYPTION_VERSION},migrate:false}};const loadOptionsState=u(clone$1(defaultLoadOptions));
636
+
637
+ const defaultSessionInfo={autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT};const sessionState={userId:u(undefined),userTraits:u(undefined),anonymousUserId:u(undefined),groupId:u(undefined),groupTraits:u(undefined),initialReferrer:u(undefined),initialReferringDomain:u(undefined),sessionInfo:u({...defaultSessionInfo})};
638
+
639
+ const capabilitiesState={isOnline:u(true),storage:{isLocalStorageAvailable:u(false),isCookieStorageAvailable:u(false),isSessionStorageAvailable:u(false)},isBeaconAvailable:u(false),isLegacyDOM:u(false),isUaCHAvailable:u(false),isCryptoAvailable:u(false),isIE11:u(false),isAdBlocked:u(false)};
640
+
641
+ const reportingState={isErrorReportingEnabled:u(false),isMetricsReportingEnabled:u(false),errorReportingProviderPluginName:u(undefined)};
642
+
643
+ const sourceConfigState=u(undefined);
644
+
645
+ const lifecycleState={activeDataplaneUrl:u(undefined),integrationsCDNPath:u(DEST_SDK_BASE_URL),pluginsCDNPath:u(PLUGINS_BASE_URL),sourceConfigUrl:u(undefined),status:u(undefined),initialized:u(false),logLevel:u(LogLevel.Error),loaded:u(false),readyCallbacks:u([]),writeKey:u(undefined),dataPlaneUrl:u(undefined)};
646
+
647
+ const consentsState={data:u({initialized:false}),activeConsentManagerPluginName:u(undefined)};
648
+
649
+ const metricsState={retries:u(0),dropped:u(0),sent:u(0),queued:u(0),triggered:u(0)};
650
+
651
+ const contextState={app:u({name:APP_NAME,namespace:APP_NAMESPACE,version:APP_VERSION}),traits:u(null),library:u({name:APP_NAME,version:APP_VERSION}),userAgent:u(''),device:u(null),network:u(null),os:u({name:'',version:''}),locale:u(null),screen:u({density:0,width:0,height:0,innerWidth:0,innerHeight:0}),'ua-ch':u(undefined),campaign:u({})};
652
+
653
+ const nativeDestinationsState={configuredDestinations:u([]),activeDestinations:u([]),loadOnlyIntegrations:u({}),failedDestinations:u([]),loadIntegration:u(true),initializedDestinations:u([]),clientDestinationsReady:u(false),integrationsConfig:u({})};
654
+
655
+ const eventBufferState={toBeProcessedArray:u([]),readyCallbacksArray:u([])};
656
+
657
+ const pluginsState={ready:u(false),loadedPlugins:u([]),failedPlugins:u([]),pluginsToLoadFromConfig:u([]),activePlugins:u([]),totalPluginsToLoad:u(0)};
658
+
659
+ const pagePropertiesState={path:u(''),referrer:u(''),referring_domain:u(''),search:u(''),title:u(''),url:u(''),tab_url:u('')};
660
+
661
+ const storageState={encryptionPluginName:u(undefined),migrate:u(false)};
662
+
663
+ const defaultStateValues={capabilities:capabilitiesState,consents:consentsState,context:contextState,eventBuffer:eventBufferState,lifecycle:lifecycleState,loadOptions:loadOptionsState,metrics:metricsState,nativeDestinations:nativeDestinationsState,plugins:pluginsState,reporting:reportingState,session:sessionState,source:sourceConfigState,page:pagePropertiesState,storage:storageState};const state={...clone$1(defaultStateValues)};
664
+
665
+ const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
666
+ // eslint-disable-next-line func-names
667
+ return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
668
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
669
+ // @ts-ignore-next-line
670
+ while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
671
+ * Utility method for JSON stringify object excluding null values & circular references
672
+ *
673
+ * @param {*} value input
674
+ * @param {boolean} excludeNull if it should exclude nul or not
675
+ * @param {function} logger optional logger methods for warning
676
+ * @returns string
677
+ */const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};
678
+
679
+ const FAILED_REQUEST_ERR_MSG_PREFIX='The request failed';const ERROR_MESSAGES_TO_BE_FILTERED=[FAILED_REQUEST_ERR_MSG_PREFIX];
680
+
681
+ /**
682
+ * Utility method to normalise errors
683
+ */const processError=error=>{let errorMessage;try{if(isString(error)){errorMessage=error;}else if(error instanceof Error){errorMessage=error.message;}else {errorMessage=error.message?error.message:stringifyWithoutCircular(error);}}catch(e){errorMessage=`Unknown error: ${e.message}`;}return errorMessage;};/**
684
+ * A function to determine whether the error should be promoted to notify or not
685
+ * @param {Error} error
686
+ * @returns
687
+ */const isAllowedToBeNotified=error=>{if(error.message){return !ERROR_MESSAGES_TO_BE_FILTERED.some(e=>error.message.includes(e));}return true;};
688
+
689
+ /**
690
+ * A service to handle errors
691
+ */class ErrorHandler{// If no logger is passed errors will be thrown as unhandled error
692
+ constructor(logger,pluginEngine){this.logger=logger;this.pluginEngine=pluginEngine;}init(externalSrcLoader){if(!this.pluginEngine){return;}try{const extPoint='errorReporting.init';const errReportingInitVal=this.pluginEngine.invokeSingle(extPoint,state,this.pluginEngine,externalSrcLoader,this.logger);if(errReportingInitVal instanceof Promise){errReportingInitVal.then(client=>{this.errReportingClient=client;}).catch(err=>{this.logger?.error(REPORTING_PLUGIN_INIT_FAILURE_ERROR(ERROR_HANDLER),err);});}}catch(err){this.onError(err,ERROR_HANDLER);}}onError(error,context='',customMessage='',shouldAlwaysThrow=false){// Error handling is already implemented in processError method
693
+ let errorMessage=processError(error);// If no error message after we normalize, then we swallow/ignore the errors
694
+ if(!errorMessage){return;}errorMessage=removeDoubleSpaces(`${context}${LOG_CONTEXT_SEPARATOR}${customMessage} ${errorMessage}`);let normalizedError=error;// Enhance error message
695
+ if(isTypeOfError(error)){normalizedError.message=errorMessage;}else {normalizedError=new Error(errorMessage);}this.notifyError(normalizedError);if(this.logger){this.logger.error(errorMessage);if(shouldAlwaysThrow){throw normalizedError;}}else {throw normalizedError;}}/**
696
+ * Add breadcrumbs to add insight of a user's journey before an error
697
+ * occurred and send to external error monitoring service via a plugin
698
+ *
699
+ * @param {string} breadcrumb breadcrumbs message
700
+ */leaveBreadcrumb(breadcrumb){if(this.pluginEngine){try{this.pluginEngine.invokeSingle('errorReporting.breadcrumb',this.pluginEngine,this.errReportingClient,breadcrumb,this.logger);}catch(err){this.onError(err,'errorReporting.breadcrumb');}}}/**
701
+ * Send handled errors to external error monitoring service via a plugin
702
+ *
703
+ * @param {Error} error Error instance from handled error
704
+ */notifyError(error){if(this.pluginEngine&&isAllowedToBeNotified(error)){try{this.pluginEngine.invokeSingle('errorReporting.notify',this.pluginEngine,this.errReportingClient,error,state,this.logger);}catch(err){// Not calling onError here as we don't want to go into infinite loop
705
+ this.logger?.error(NOTIFY_FAILURE_ERROR(ERROR_HANDLER),err);}}}}const defaultErrorHandler=new ErrorHandler(defaultLogger,defaultPluginEngine);
706
+
707
+ let DestinationConnectionMode=/*#__PURE__*/function(DestinationConnectionMode){DestinationConnectionMode["Hybrid"]="hybrid";DestinationConnectionMode["Cloud"]="cloud";DestinationConnectionMode["Device"]="device";return DestinationConnectionMode;}({});
708
+
709
+ /**
710
+ * A function to filter and return non cloud mode destinations
711
+ * @param destination
712
+ *
713
+ * @returns boolean
714
+ */const isNonCloudDestination=destination=>Boolean(destination.config.connectionMode!==DestinationConnectionMode.Cloud||destination.config.useNativeSDKToSend===true||// this is the older flag for hybrid mode destinations
715
+ destination.config.useNativeSDK===true);const isHybridModeDestination=destination=>Boolean(destination.config.connectionMode===DestinationConnectionMode.Hybrid||destination.config.useNativeSDKToSend===true);/**
716
+ * A function to filter and return non cloud mode destinations
717
+ * @param destinations
718
+ *
719
+ * @returns destinations
720
+ */const getNonCloudDestinations=destinations=>destinations.filter(isNonCloudDestination);
721
+
722
+ let LifecycleStatus=/*#__PURE__*/function(LifecycleStatus){LifecycleStatus["Mounted"]="mounted";LifecycleStatus["BrowserCapabilitiesReady"]="browserCapabilitiesReady";LifecycleStatus["Configured"]="configured";LifecycleStatus["PluginsLoading"]="pluginsLoading";LifecycleStatus["PluginsReady"]="pluginsReady";LifecycleStatus["Initialized"]="initialized";LifecycleStatus["Loaded"]="loaded";LifecycleStatus["DestinationsLoading"]="destinationsLoading";LifecycleStatus["DestinationsReady"]="destinationsReady";LifecycleStatus["Ready"]="ready";return LifecycleStatus;}({});
723
+
724
+ /**
725
+ * List of plugin names that are loaded as dynamic imports in modern builds
726
+ */const remotePluginNames=[PluginName.BeaconQueue,PluginName.DeviceModeTransformation,PluginName.DeviceModeDestinations,PluginName.ErrorReporting,PluginName.ExternalAnonymousId,PluginName.GoogleLinker,PluginName.NativeDestinationQueue,PluginName.StorageEncryption,PluginName.StorageEncryptionLegacy,PluginName.StorageMigrator,PluginName.XhrQueue,PluginName.OneTrustConsentManager,PluginName.KetchConsentManager,PluginName.Bugsnag];
727
+
728
+ const remotesMap = {
729
+ 'rudderAnalyticsRemotePlugins':{url:()=>Promise.resolve(window.RudderStackGlobals && window.RudderStackGlobals.app && window.RudderStackGlobals.app.pluginsCDNPath ? "" + window.RudderStackGlobals.app.pluginsCDNPath + "/rsa-plugins.js" : "http://localhost:3002/cdn//rsa-plugins.js"),format:'esm',from:'vite'}
730
+ };
731
+ const loadJS = async (url, fn) => {
732
+ const resolvedUrl = typeof url === 'function' ? await url() : url;
733
+ const script = document.createElement('script');
734
+ script.type = 'text/javascript';
735
+ script.onload = fn;
736
+ script.src = resolvedUrl;
737
+ document.getElementsByTagName('head')[0].appendChild(script);
738
+ };
739
+
740
+ const wrapShareModule = remoteFrom => {
741
+ return {
742
+
743
+ }
744
+ };
745
+
746
+ async function __federation_method_ensure(remoteId) {
747
+ const remote = remotesMap[remoteId];
748
+ if (!remote.inited) {
749
+ if ('var' === remote.format) {
750
+ // loading js with script tag
751
+ return new Promise(resolve => {
752
+ const callback = () => {
753
+ if (!remote.inited) {
754
+ remote.lib = window[remoteId];
755
+ remote.lib.init(wrapShareModule(remote.from));
756
+ remote.inited = true;
757
+ }
758
+ resolve(remote.lib);
759
+ };
760
+ return loadJS(remote.url, callback);
761
+ });
762
+ } else if (['esm', 'systemjs'].includes(remote.format)) {
763
+ // loading js with import(...)
764
+ return new Promise((resolve, reject) => {
765
+ const getUrl = typeof remote.url === 'function' ? remote.url : () => Promise.resolve(remote.url);
766
+ getUrl().then(url => {
767
+ import(/* @vite-ignore */ url).then(lib => {
768
+ if (!remote.inited) {
769
+ const shareScope = wrapShareModule(remote.from);
770
+ lib.init(shareScope);
771
+ remote.lib = lib;
772
+ remote.lib.init(shareScope);
773
+ remote.inited = true;
774
+ }
775
+ resolve(remote.lib);
776
+ }).catch(reject);
777
+ });
778
+ })
779
+ }
780
+ } else {
781
+ return remote.lib;
782
+ }
783
+ }
784
+
785
+ function __federation_method_wrapDefault(module, need) {
786
+ if (!module?.default && need) {
787
+ let obj = Object.create(null);
788
+ obj.default = module;
789
+ obj.__esModule = true;
790
+ return obj;
791
+ }
792
+ return module;
793
+ }
794
+
795
+ function __federation_method_getRemote(remoteName, componentName) {
796
+ return __federation_method_ensure(remoteName).then((remote) => remote.get(componentName).then(factory => factory()));
797
+ }
798
+
799
+ /**
800
+ * Get the lazy loaded dynamic import for a plugin name
801
+ */const getFederatedModuleImport=pluginName=>{switch(pluginName){case PluginName.BeaconQueue:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./BeaconQueue").then(module=>__federation_method_wrapDefault(module, true));case PluginName.DeviceModeTransformation:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./DeviceModeTransformation").then(module=>__federation_method_wrapDefault(module, true));case PluginName.DeviceModeDestinations:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./DeviceModeDestinations").then(module=>__federation_method_wrapDefault(module, true));case PluginName.ErrorReporting:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./ErrorReporting").then(module=>__federation_method_wrapDefault(module, true));case PluginName.ExternalAnonymousId:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./ExternalAnonymousId").then(module=>__federation_method_wrapDefault(module, true));case PluginName.GoogleLinker:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./GoogleLinker").then(module=>__federation_method_wrapDefault(module, true));case PluginName.NativeDestinationQueue:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./NativeDestinationQueue").then(module=>__federation_method_wrapDefault(module, true));case PluginName.StorageEncryption:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./StorageEncryption").then(module=>__federation_method_wrapDefault(module, true));case PluginName.StorageEncryptionLegacy:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./StorageEncryptionLegacy").then(module=>__federation_method_wrapDefault(module, true));case PluginName.StorageMigrator:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./StorageMigrator").then(module=>__federation_method_wrapDefault(module, true));case PluginName.XhrQueue:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./XhrQueue").then(module=>__federation_method_wrapDefault(module, true));case PluginName.OneTrustConsentManager:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./OneTrustConsentManager").then(module=>__federation_method_wrapDefault(module, true));case PluginName.KetchConsentManager:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./KetchConsentManager").then(module=>__federation_method_wrapDefault(module, true));case PluginName.Bugsnag:return ()=>__federation_method_getRemote("rudderAnalyticsRemotePlugins" , "./Bugsnag").then(module=>__federation_method_wrapDefault(module, true));default:return undefined;}};/**
802
+ * Map of active plugin names to their dynamic import
803
+ */const modernBuildPluginImports=activePluginNames=>{const remotePlugins={};activePluginNames.forEach(pluginName=>{if(remotePluginNames.includes(pluginName)){const lazyLoadImport=getFederatedModuleImport(pluginName);if(lazyLoadImport){remotePlugins[pluginName]=lazyLoadImport;}}});return remotePlugins;};
804
+
805
+ /**
806
+ * Map of mandatory plugin names and direct imports
807
+ */const getMandatoryPluginsMap=()=>({});/**
808
+ * Map of optional plugin names and direct imports for legacy builds
809
+ */const getOptionalPluginsMap=()=>{{return {};}};/**
810
+ * Map of optional plugin names and dynamic imports for modern builds
811
+ */const getRemotePluginsMap=activePluginNames=>{return modernBuildPluginImports?.(activePluginNames)||{};};const pluginsInventory={...getMandatoryPluginsMap(),...getOptionalPluginsMap()};const remotePluginsInventory=activePluginNames=>({...getRemotePluginsMap(activePluginNames)});
812
+
813
+ // TODO: add retry mechanism for getting remote plugins
814
+ // TODO: add timeout error mechanism for marking remote plugins that failed to load as failed in state
815
+ class PluginsManager{constructor(engine,errorHandler,logger){this.engine=engine;this.errorHandler=errorHandler;this.logger=logger;this.onError=this.onError.bind(this);}/**
816
+ * Orchestrate the plugin loading and registering
817
+ */init(){state.lifecycle.status.value=LifecycleStatus.PluginsLoading;// Expose pluginsCDNPath to global object, so it can be used in the promise that determines
818
+ // remote plugin cdn path to support proxied plugin remotes
819
+ {setExposedGlobal('pluginsCDNPath',state.lifecycle.pluginsCDNPath.value);}this.setActivePlugins();this.registerLocalPlugins();this.registerRemotePlugins();this.attachEffects();}/**
820
+ * Update state based on plugin loaded status
821
+ */ // eslint-disable-next-line class-methods-use-this
822
+ attachEffects(){b(()=>{const isAllPluginsReady=state.plugins.activePlugins.value.length===0||state.plugins.loadedPlugins.value.length+state.plugins.failedPlugins.value.length===state.plugins.totalPluginsToLoad.value;if(isAllPluginsReady){o(()=>{state.plugins.ready.value=true;// TODO: decide what to do if a plugin fails to load for any reason.
823
+ // Should we stop here or should we progress?
824
+ state.lifecycle.status.value=LifecycleStatus.PluginsReady;});}});}/**
825
+ * Determine the list of plugins that should be loaded based on sourceConfig & load options
826
+ */ // eslint-disable-next-line class-methods-use-this
827
+ getPluginsToLoadBasedOnConfig(){// This contains the default plugins if load option has been omitted by user
828
+ let pluginsToLoadFromConfig=state.plugins.pluginsToLoadFromConfig.value;if(!pluginsToLoadFromConfig){return [];}// Error reporting related plugins
829
+ const supportedErrReportingProviderPluginNames=Object.values(ErrorReportingProvidersToPluginNameMap);if(state.reporting.errorReportingProviderPluginName.value){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!(pluginName!==state.reporting.errorReportingProviderPluginName.value&&supportedErrReportingProviderPluginNames.includes(pluginName)));}else {pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!(pluginName===PluginName.ErrorReporting||supportedErrReportingProviderPluginNames.includes(pluginName)));}// dataplane events delivery plugins
830
+ if(state.loadOptions.value.useBeacon===true&&state.capabilities.isBeaconAvailable.value){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!==PluginName.XhrQueue);}else {if(state.loadOptions.value.useBeacon===true){this.logger?.warn(UNSUPPORTED_BEACON_API_WARNING(PLUGINS_MANAGER));}pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!==PluginName.BeaconQueue);}// Device mode destinations related plugins
831
+ if(getNonCloudDestinations(state.nativeDestinations.configuredDestinations.value??[]).length===0){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>![PluginName.DeviceModeDestinations,PluginName.DeviceModeTransformation,PluginName.NativeDestinationQueue].includes(pluginName));}// Consent Management related plugins
832
+ const supportedConsentManagerPlugins=Object.values(ConsentManagersToPluginNameMap);pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!(pluginName!==state.consents.activeConsentManagerPluginName.value&&supportedConsentManagerPlugins.includes(pluginName)));// Storage encryption related plugins
833
+ const supportedStorageEncryptionPlugins=Object.values(StorageEncryptionVersionsToPluginNameMap);pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!(pluginName!==state.storage.encryptionPluginName.value&&supportedStorageEncryptionPlugins.includes(pluginName)));// Storage migrator related plugins
834
+ if(!state.storage.migrate.value){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!==PluginName.StorageMigrator);}return [...Object.keys(getMandatoryPluginsMap()),...pluginsToLoadFromConfig];}/**
835
+ * Determine the list of plugins that should be activated
836
+ */setActivePlugins(){const pluginsToLoad=this.getPluginsToLoadBasedOnConfig();// Merging available mandatory and optional plugin name list
837
+ const availablePlugins=[...Object.keys(pluginsInventory),...remotePluginNames];const activePlugins=[];const failedPlugins=[];pluginsToLoad.forEach(pluginName=>{if(availablePlugins.includes(pluginName)){activePlugins.push(pluginName);}else {failedPlugins.push(pluginName);}});if(failedPlugins.length>0){this.onError(new Error(`Ignoring loading of unknown plugins: ${failedPlugins.join(',')}. Mandatory plugins: ${Object.keys(getMandatoryPluginsMap()).join(',')}. Load option plugins: ${state.plugins.pluginsToLoadFromConfig.value.join(',')}`));}o(()=>{state.plugins.totalPluginsToLoad.value=pluginsToLoad.length;state.plugins.activePlugins.value=activePlugins;state.plugins.failedPlugins.value=failedPlugins;});}/**
838
+ * Register plugins that are direct imports to PluginEngine
839
+ */registerLocalPlugins(){Object.values(pluginsInventory).forEach(localPlugin=>{if(state.plugins.activePlugins.value.includes(localPlugin().name)){this.register([localPlugin()]);}});}/**
840
+ * Register plugins that are dynamic imports to PluginEngine
841
+ */registerRemotePlugins(){const remotePluginsList=remotePluginsInventory(state.plugins.activePlugins.value);Promise.all(Object.keys(remotePluginsList).map(async remotePluginKey=>{await remotePluginsList[remotePluginKey]().then(remotePluginModule=>this.register([remotePluginModule.default()])).catch(err=>{// TODO: add retry here if dynamic import fails
842
+ state.plugins.failedPlugins.value=[...state.plugins.failedPlugins.value,remotePluginKey];this.onError(err,remotePluginKey);});})).catch(err=>{this.onError(err);});}/**
843
+ * Extension point invoke that allows multiple plugins to be registered to it with error handling
844
+ */invokeMultiple(extPoint,...args){try{return this.engine.invokeMultiple(extPoint,...args);}catch(e){this.onError(e,extPoint);return [];}}/**
845
+ * Extension point invoke that allows a single plugin to be registered to it with error handling
846
+ */invokeSingle(extPoint,...args){try{return this.engine.invokeSingle(extPoint,...args);}catch(e){this.onError(e,extPoint);return null;}}/**
847
+ * Plugin engine register with error handling
848
+ */register(plugins){plugins.forEach(plugin=>{try{this.engine.register(plugin,state);}catch(e){state.plugins.failedPlugins.value=[...state.plugins.failedPlugins.value,plugin.name];this.onError(e);}});}// TODO: Implement reset API instead
849
+ unregisterLocalPlugins(){Object.values(pluginsInventory).forEach(localPlugin=>{try{this.engine.unregister(localPlugin().name);}catch(e){this.onError(e);}});}/**
850
+ * Handle errors
851
+ */onError(error,customMessage){if(this.errorHandler){this.errorHandler.onError(error,PLUGINS_MANAGER,customMessage);}else {throw error;}}}
852
+
853
+ /**
854
+ * Get mutated error with issue prepended to error message
855
+ * @param err Original error
856
+ * @param issue Issue to prepend to error message
857
+ * @returns Instance of Error with message prepended with issue
858
+ */const getMutatedError=(err,issue)=>{let finalError=err;if(!isTypeOfError(err)){finalError=new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}else {finalError.message=`${issue}: ${err.message}`;}return finalError;};
859
+
860
+ /**
861
+ * Utility to parse XHR JSON response
862
+ */const responseTextToJson=(responseText,onError)=>{try{return JSON.parse(responseText||'');}catch(err){const error=getMutatedError(err,'Failed to parse response data');if(onError&&isFunction(onError)){onError(error);}else {throw error;}}return undefined;};
863
+
864
+ const DEFAULT_XHR_REQUEST_OPTIONS={headers:{Accept:'application/json','Content-Type':'application/json;charset=UTF-8'},method:'GET'};/**
865
+ * Utility to create request configuration based on default options
866
+ */const createXhrRequestOptions=(url,options,basicAuthHeader)=>{const requestOptions=mergeDeepRight(DEFAULT_XHR_REQUEST_OPTIONS,options||{});if(basicAuthHeader){requestOptions.headers=mergeDeepRight(requestOptions.headers,{Authorization:basicAuthHeader});}requestOptions.url=url;return requestOptions;};/**
867
+ * Utility implementation of XHR, fetch cannot be used as it requires explicit
868
+ * origin allowed values and not wildcard for CORS requests with credentials and
869
+ * this is not supported by our sourceConfig API
870
+ */const xhrRequest=(options,timeout=DEFAULT_XHR_TIMEOUT,logger)=>new Promise((resolve,reject)=>{let payload;if(options.sendRawData===true){payload=options.data;}else {payload=stringifyWithoutCircular(options.data,false,[],logger);if(isNull(payload)){reject({error:new Error(XHR_PAYLOAD_PREP_ERROR),undefined,options});// return and don't process further if the payload could not be stringified
871
+ return;}}const xhr=new XMLHttpRequest();// eslint-disable-next-line @typescript-eslint/no-unused-vars
872
+ const xhrReject=e=>{reject({error:new Error(XHR_DELIVERY_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,xhr.status,xhr.statusText,options.url)),xhr,options});};const xhrError=e=>{reject({error:new Error(XHR_REQUEST_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,e,options.url)),xhr,options});};xhr.ontimeout=xhrError;xhr.onerror=xhrError;xhr.onload=()=>{if(xhr.status>=200&&xhr.status<400){resolve({response:xhr.responseText,xhr,options});}else {xhrReject();}};xhr.open(options.method,options.url);// The timeout property may be set only in the time interval between a call to the open method
873
+ // and the first call to the send method in legacy browsers
874
+ xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options.headers[headerName]){xhr.setRequestHeader(headerName,options.headers[headerName]);}});try{xhr.send(payload);}catch(err){reject({error:getMutatedError(err,XHR_SEND_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,options.url)),xhr,options});}});
875
+
876
+ /**
877
+ * Service to handle data communication with APIs
878
+ */class HttpClient{hasErrorHandler=false;constructor(errorHandler,logger){this.errorHandler=errorHandler;this.logger=logger;this.hasErrorHandler=Boolean(this.errorHandler);this.onError=this.onError.bind(this);}/**
879
+ * Implement requests in a blocking way
880
+ */async getData(config){const{url,options,timeout,isRawResponse}=config;try{const data=await xhrRequest(createXhrRequestOptions(url,options,this.basicAuthHeader),timeout,this.logger);return {data:isRawResponse?data.response:responseTextToJson(data.response,this.onError),details:data};}catch(reason){this.onError(reason.error??reason);return {data:undefined,details:reason};}}/**
881
+ * Implement requests in a non-blocking way
882
+ */getAsyncData(config){const{callback,url,options,timeout,isRawResponse}=config;const isFireAndForget=!(callback&&isFunction(callback));xhrRequest(createXhrRequestOptions(url,options,this.basicAuthHeader),timeout,this.logger).then(data=>{if(!isFireAndForget){callback(isRawResponse?data.response:responseTextToJson(data.response,this.onError),data);}}).catch(data=>{this.onError(data.error??data);if(!isFireAndForget){callback(undefined,data);}});}/**
883
+ * Handle errors
884
+ */onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,HTTP_CLIENT);}else {throw error;}}/**
885
+ * Set basic authentication header (eg writekey)
886
+ */setAuthHeader(value,noBtoa=false){const authVal=noBtoa?value:toBase64(`${value}:`);this.basicAuthHeader=`Basic ${authVal}`;}/**
887
+ * Clear basic authentication header
888
+ */resetAuthHeader(){this.basicAuthHeader=undefined;}}const defaultHttpClient=new HttpClient(defaultErrorHandler,defaultLogger);
889
+
890
+ const DEFAULT_EXT_SRC_LOAD_TIMEOUT=10*1000;// 10 seconds
891
+
892
+ const EXTERNAL_SOURCE_LOAD_ORIGIN='RS_JS_SDK';
893
+
894
+ /**
895
+ * Create the DOM element to load a script marked as RS SDK originated
896
+ *
897
+ * @param {*} url The URL of the script to be loaded
898
+ * @param {*} id ID for the script tag
899
+ * @param {*} async Whether to load the script in async mode. Defaults to `true` [optional]
900
+ * @param {*} onload callback to invoke onload [optional]
901
+ * @param {*} onerror callback to invoke onerror [optional]
902
+ * @param {*} extraAttributes key/value pair with html attributes to add in html tag [optional]
903
+ *
904
+ * @returns HTMLScriptElement
905
+ */const createScriptElement=(url,id,async=true,onload=null,onerror=null,extraAttributes={})=>{const scriptElement=document.createElement('script');scriptElement.type='text/javascript';scriptElement.onload=onload;scriptElement.onerror=onerror;scriptElement.src=url;scriptElement.id=id;scriptElement.async=async;scriptElement.setAttribute('data-append-origin',EXTERNAL_SOURCE_LOAD_ORIGIN);Object.keys(extraAttributes).forEach(attributeName=>{scriptElement.setAttribute(attributeName,extraAttributes[attributeName]);});return scriptElement;};/**
906
+ * Add script DOM element to DOM
907
+ *
908
+ * @param {*} newScriptElement the script element to add
909
+ *
910
+ * @returns
911
+ */const insertScript=newScriptElement=>{// First try to add it to the head
912
+ const headElements=document.getElementsByTagName('head');if(headElements.length>0){headElements[0].insertBefore(newScriptElement,headElements[0].firstChild);return;}// Else wise add it before the first script tag
913
+ const scriptElements=document.getElementsByTagName('script');if(scriptElements.length>0&&scriptElements[0].parentNode){scriptElements[0].parentNode.insertBefore(newScriptElement,scriptElements[0]);return;}// Create a new head element and add the script as fallback
914
+ const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement.insertBefore(headElement,htmlElement.firstChild);};/**
915
+ * Loads external js file as a script html tag
916
+ *
917
+ * @param {*} url The URL of the script to be loaded
918
+ * @param {*} id ID for the script tag
919
+ * @param {*} timeout loading timeout
920
+ * @param {*} async Whether to load the script in async mode. Defaults to `true` [optional]
921
+ * @param {*} extraAttributes key/value pair with html attributes to add in html tag [optional]
922
+ *
923
+ * @returns
924
+ */const jsFileLoader=(url,id,timeout,async=true,extraAttributes)=>new Promise((resolve,reject)=>{const scriptExists=document.getElementById(id);if(scriptExists){reject(new Error(SCRIPT_ALREADY_EXISTS_ERROR(id)));}try{let timeoutID;const onload=()=>{globalThis.clearTimeout(timeoutID);resolve(id);};const onerror=()=>{globalThis.clearTimeout(timeoutID);reject(new Error(SCRIPT_LOAD_ERROR(id,url)));};// Create the DOM element to load the script and add it to the DOM
925
+ insertScript(createScriptElement(url,id,async,onload,onerror,extraAttributes));// Reject on timeout
926
+ timeoutID=globalThis.setTimeout(()=>{reject(new Error(SCRIPT_LOAD_TIMEOUT_ERROR(id,url,timeout)));},timeout);}catch(err){reject(getMutatedError(err,SCRIPT_LOAD_ERROR(id,url)));}});
927
+
928
+ /**
929
+ * Service to load external resources/files
930
+ */class ExternalSrcLoader{hasErrorHandler=false;constructor(errorHandler,logger,timeout=DEFAULT_EXT_SRC_LOAD_TIMEOUT){this.errorHandler=errorHandler;this.logger=logger;this.timeout=timeout;this.hasErrorHandler=Boolean(this.errorHandler);this.onError=this.onError.bind(this);}/**
931
+ * Load external resource of type javascript
932
+ */loadJSFile(config){const{url,id,timeout,async,callback,extraAttributes}=config;const isFireAndForget=!(callback&&isFunction(callback));jsFileLoader(url,id,timeout||this.timeout,async,extraAttributes).then(id=>{if(!isFireAndForget){callback(id);}}).catch(err=>{this.onError(err);if(!isFireAndForget){callback();}});}/**
933
+ * Handle errors
934
+ */onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,EXTERNAL_SRC_LOADER);}else {throw error;}}}
935
+
936
+ const COOKIE_STORAGE='cookieStorage';const LOCAL_STORAGE='localStorage';const SESSION_STORAGE='sessionStorage';const MEMORY_STORAGE='memoryStorage';
937
+
938
+ const STORAGE_TEST_COOKIE='test_rudder_cookie';const STORAGE_TEST_LOCAL_STORAGE='test_rudder_ls';const STORAGE_TEST_SESSION_STORAGE='test_rudder_ss';const STORAGE_TEST_TOP_LEVEL_DOMAIN='__tld__';const CLIENT_DATA_STORE_NAME='clientData';
939
+
940
+ const detectAdBlockers=(errorHandler,logger)=>{// Apparently, '?view=ad' is a query param that is blocked by majority of adblockers
941
+ // Use source config URL here as it is very unlikely to be blocked by adblockers
942
+ // Only the extra query param should make it vulnerable to adblockers
943
+ // This will work even if the users proxies it.
944
+ // The edge case where this doesn't work is when HEAD method is not allowed by the server (user's)
945
+ const baseUrl=new URL(state.lifecycle.sourceConfigUrl.value);const url=`${baseUrl.origin}${baseUrl.pathname}?view=ad`;const httpClient=new HttpClient(errorHandler,logger);httpClient.setAuthHeader(state.lifecycle.writeKey.value);httpClient.getAsyncData({url,options:{// We actually don't need the response from the request, so we are using HEAD
946
+ method:'HEAD',headers:{'Content-Type':undefined}},isRawResponse:true,callback:(result,details)=>{// not ad blocked if the request is successful or it is not internally redirected on the client side
947
+ // Often adblockers instead of blocking the request, they redirect it to an internal URL
948
+ state.capabilities.isAdBlocked.value=details?.error!==undefined||details?.xhr?.responseURL!==url;}});};
949
+
950
+ const hasCrypto$1=()=>!isNullOrUndefined(globalThis.crypto)&&isFunction(globalThis.crypto.getRandomValues);const hasUAClientHints=()=>!isNullOrUndefined(globalThis.navigator.userAgentData);const hasBeacon=()=>!isNullOrUndefined(globalThis.navigator.sendBeacon)&&isFunction(globalThis.navigator.sendBeacon);const isIE11=()=>Boolean(globalThis.navigator.userAgent.match(/Trident.*rv:11\./));
951
+
952
+ const getUserAgentClientHint=(callback,level='none')=>{if(level==='none'){callback(undefined);}if(level==='default'){callback(navigator.userAgentData);}if(level==='full'){navigator.userAgentData?.getHighEntropyValues(['architecture','bitness','brands','mobile','model','platform','platformVersion','uaFullVersion','fullVersionList','wow64']).then(ua=>{callback(ua);}).catch(()=>{callback();});}};
953
+
954
+ const isDatasetAvailable=()=>{const testElement=document.createElement('div');testElement.setAttribute('data-a-b','c');return testElement.dataset?testElement.dataset.aB==='c':false;};const legacyJSEngineRequiredPolyfills={URLSearchParams:()=>!globalThis.URLSearchParams,URL:()=>!isFunction(globalThis.URL),MutationObserver:()=>isUndefined(MutationObserver),Promise:()=>isUndefined(Promise),'Number.isNaN':()=>!Number.isNaN,'Number.isInteger':()=>!Number.isInteger,'Array.from':()=>!Array.from,'Array.prototype.find':()=>!Array.prototype.find,'Array.prototype.includes':()=>!Array.prototype.includes,'String.prototype.endsWith':()=>!String.prototype.endsWith,'String.prototype.startsWith':()=>!String.prototype.startsWith,'String.prototype.includes':()=>!String.prototype.includes,'Object.entries':()=>!Object.entries,'Object.values':()=>!Object.values,'Element.prototype.dataset':()=>!isDatasetAvailable(),'String.prototype.replaceAll':()=>!String.prototype.replaceAll,TextEncoder:()=>isUndefined(TextEncoder),TextDecoder:()=>isUndefined(TextDecoder),'String.fromCodePoint':()=>!String.fromCodePoint};const isLegacyJSEngine=()=>{const requiredCapabilitiesList=Object.keys(legacyJSEngineRequiredPolyfills);let needsPolyfill=false;/* eslint-disable-next-line unicorn/no-for-loop */for(let i=0;i<requiredCapabilitiesList.length;i++){const isCapabilityMissing=legacyJSEngineRequiredPolyfills[requiredCapabilitiesList[i]];if(isCapabilityMissing()){needsPolyfill=true;}}return needsPolyfill;};
955
+
956
+ const getScreenDetails=()=>{let screenDetails={density:0,width:0,height:0,innerWidth:0,innerHeight:0};screenDetails={width:globalThis.screen.width,height:globalThis.screen.height,density:globalThis.devicePixelRatio,innerWidth:globalThis.innerWidth,innerHeight:globalThis.innerHeight};return screenDetails;};
957
+
958
+ const isStorageQuotaExceeded=e=>{const matchingNames=['QuotaExceededError','NS_ERROR_DOM_QUOTA_REACHED'];// [everything except Firefox, Firefox]
959
+ const matchingCodes=[22,1014];// [everything except Firefox, Firefox]
960
+ const isQuotaExceededError=matchingNames.includes(e.name)||matchingCodes.includes(e.code);return e instanceof DOMException&&isQuotaExceededError;};// TODO: also check for SecurityErrors
961
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#exceptions
962
+ const isStorageAvailable=(type=LOCAL_STORAGE,storageInstance,logger)=>{let storage;let testData;try{switch(type){case MEMORY_STORAGE:return true;case COOKIE_STORAGE:storage=storageInstance;testData=STORAGE_TEST_COOKIE;break;case LOCAL_STORAGE:storage=storageInstance??globalThis.localStorage;testData=STORAGE_TEST_LOCAL_STORAGE;// was STORAGE_TEST_LOCAL_STORAGE in ours and generateUUID() in segment retry one
963
+ break;case SESSION_STORAGE:storage=storageInstance??globalThis.sessionStorage;testData=STORAGE_TEST_SESSION_STORAGE;break;default:return false;}if(!storage){return false;}storage.setItem(testData,'true');if(storage.getItem(testData)){storage.removeItem(testData);return true;}return false;}catch(err){const msgPrefix=STORAGE_UNAVAILABILITY_ERROR_PREFIX(CAPABILITIES_MANAGER,type);let reason='unavailable';if(isStorageQuotaExceeded(err)){reason='full';}logger?.error(`${msgPrefix}${reason}.`,err);return false;}};
964
+
965
+ /**
966
+ * To get the current timestamp in ISO string format
967
+ * @returns ISO formatted timestamp string
968
+ */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
969
+
970
+ function random(len){return crypto.getRandomValues(new Uint8Array(len));}
971
+
972
+ var SIZE=4096,HEX$1=[],IDX$1=0,BUFFER$1;for(;IDX$1<256;IDX$1++){HEX$1[IDX$1]=(IDX$1+256).toString(16).substring(1);}function v4$1(){if(!BUFFER$1||IDX$1+16>SIZE){BUFFER$1=random(SIZE);IDX$1=0;}var i=0,tmp,out='';for(;i<16;i++){tmp=BUFFER$1[IDX$1+i];if(i==6)out+=HEX$1[tmp&15|64];else if(i==8)out+=HEX$1[tmp&63|128];else out+=HEX$1[tmp];if(i&1&&i>1&&i<11)out+='-';}IDX$1+=16;return out;}
973
+
974
+ var IDX=256,HEX=[],BUFFER;while(IDX--)HEX[IDX]=(IDX+256).toString(16).substring(1);function v4(){var i=0,num,out='';if(!BUFFER||IDX+16>256){BUFFER=Array(i=256);while(i--)BUFFER[i]=256*Math.random()|0;i=IDX=0;}for(;i<16;i++){num=BUFFER[IDX+i];if(i==6)out+=HEX[num&15|64];else if(i==8)out+=HEX[num&63|128];else out+=HEX[num];if(i&1&&i>1&&i<11)out+='-';}IDX++;return out;}
975
+
976
+ const hasCrypto=()=>!isNullOrUndefined(globalThis.crypto)&&isFunction(globalThis.crypto.getRandomValues);
977
+
978
+ const generateUUID=()=>{if(hasCrypto()){return v4$1();}return v4();};
979
+
980
+ /**
981
+ * Encode.
982
+ */const encode=value=>encodeURIComponent(value);/**
983
+ * Decode
984
+ */const decode=value=>decodeURIComponent(value);/**
985
+ * Parse cookie `str`
986
+ */const parse=str=>{const obj={};const pairs=str.split(/\s*;\s*/);let pair;if(!pairs[0]){return obj;}pairs.forEach(pairItem=>{pair=pairItem.split('=');obj[decode(pair[0])]=decode(pair[1]);});return obj;};/**
987
+ * Set cookie `name` to `value`
988
+ */const set=(name,value,optionsConfig)=>{const options={...optionsConfig}||{};let cookieString=`${encode(name)}=${encode(value)}`;if(isNull(value)){options.maxage=-1;}if(options.maxage){options.expires=new Date(+new Date()+options.maxage);}if(options.path){cookieString+=`; path=${options.path}`;}if(options.domain){cookieString+=`; domain=${options.domain}`;}if(options.expires){cookieString+=`; expires=${options.expires.toUTCString()}`;}if(options.samesite){cookieString+=`; samesite=${options.samesite}`;}if(options.secure){cookieString+=`; secure`;}globalThis.document.cookie=cookieString;};/**
989
+ * Return all cookies
990
+ */const all=()=>{const cookieStringValue=globalThis.document.cookie;return parse(cookieStringValue);};/**
991
+ * Get cookie `name`
992
+ */const get=name=>all()[name];/**
993
+ * Set or get cookie `name` with `value` and `options` object
994
+ */ // eslint-disable-next-line func-names
995
+ const cookie=function(name,value,options){switch(arguments.length){case 3:case 2:return set(name,value,options);case 1:if(name){return get(name);}return all();default:return all();}};
996
+
997
+ const legacyGetHostname=href=>{const l=document.createElement('a');l.href=href;return l.hostname;};/**
998
+ * Levels returns all levels of the given url
999
+ *
1000
+ * The method returns an empty array when the hostname is an ip.
1001
+ */const levelsFunc=url=>{// This is called before the polyfills load thus new URL cannot be used
1002
+ const host=typeof globalThis.URL!=='function'?legacyGetHostname(url):new URL(url).hostname;const parts=host?.split('.')??[];const last=parts[parts.length-1];const levels=[];// Ip address.
1003
+ if(parts.length===4&&last===parseInt(last,10).toString()){return levels;}// Localhost.
1004
+ if(parts.length<=1){// Fix to support localhost
1005
+ if(parts[0].indexOf('localhost')!==-1){return ['localhost'];}return levels;}// Create levels.
1006
+ for(let i=parts.length-2;i>=0;i-=1){levels.push(parts.slice(i).join('.'));}return levels;};/**
1007
+ * Get the top domain.
1008
+ *
1009
+ * The function constructs the levels of domain and attempts to set a global
1010
+ * cookie on each one when it succeeds it returns the top level domain.
1011
+ *
1012
+ * The method returns an empty string when the hostname is an ip.
1013
+ */const domain=url=>{const levels=levelsFunc(url);// Lookup the real top level one.
1014
+ // eslint-disable-next-line unicorn/no-for-loop
1015
+ for(let i=0;i<levels.length;i+=1){const domain=levels[i];const cname=STORAGE_TEST_TOP_LEVEL_DOMAIN;const opts={domain:`${domain.indexOf('localhost')!==-1?'':'.'}${domain}`};// Set cookie on domain
1016
+ cookie(cname,1,opts);// If successful
1017
+ if(cookie(cname)){// Remove cookie from domain
1018
+ cookie(cname,null,opts);return domain;}}return '';};
1019
+
1020
+ const getDefaultCookieOptions=()=>{const topDomain=domain(globalThis.location.href);return {maxage:DEFAULT_COOKIE_MAX_AGE,path:'/',domain:!topDomain||topDomain==='.'?undefined:topDomain,samesite:CookieSameSite.Lax,enabled:true};};const getDefaultLocalStorageOptions=()=>({enabled:true});const getDefaultInMemoryStorageOptions=()=>({enabled:true});
1021
+
1022
+ /**
1023
+ * A storage utility to persist values in cookies via Storage interface
1024
+ */class CookieStorage{static globalSingleton=null;isSupportAvailable=true;isEnabled=true;length=0;constructor(options={},logger){if(CookieStorage.globalSingleton){// eslint-disable-next-line no-constructor-return
1025
+ return CookieStorage.globalSingleton;}this.options=getDefaultCookieOptions();this.logger=logger;this.configure(options);CookieStorage.globalSingleton=this;}configure(options){this.options=mergeDeepRight(this.options??{},options);this.isSupportAvailable=isStorageAvailable(COOKIE_STORAGE,this,this.logger);this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){cookie(key,value,this.options);this.length=Object.keys(cookie()).length;return true;}// eslint-disable-next-line class-methods-use-this
1026
+ getItem(key){const value=cookie(key);return isUndefined(value)?null:value;}removeItem(key){const result=this.setItem(key,null);this.length=Object.keys(cookie()).length;return result;}// eslint-disable-next-line class-methods-use-this
1027
+ clear(){// Not implemented
1028
+ // getting a list of all cookie storage keys and remove all values
1029
+ // sounds risky to do as it will take on all top domain cookies
1030
+ // better to explicitly clear specific ones if needed
1031
+ }// This cannot be implemented for cookies
1032
+ // eslint-disable-next-line class-methods-use-this
1033
+ key(index){const cookies=cookie();const cookieNames=Object.keys(cookies);return isUndefined(cookieNames[index])?null:cookieNames[index];}}
1034
+
1035
+ /**
1036
+ * A storage utility to retain values in memory via Storage interface
1037
+ */class InMemoryStorage{isEnabled=true;length=0;data={};constructor(options,logger){this.options=getDefaultInMemoryStorageOptions();this.logger=logger;this.configure(options??{});}configure(options){this.options=mergeDeepRight(this.options,options);this.isEnabled=Boolean(this.options.enabled);return this.options;}setItem(key,value){this.data[key]=value;this.length=Object.keys(this.data).length;return value;}getItem(key){if(key in this.data){return this.data[key];}return null;}removeItem(key){if(key in this.data){delete this.data[key];}this.length=Object.keys(this.data).length;return null;}clear(){this.data={};this.length=0;}key(index){return Object.keys(this.data)[index];}}const defaultInMemoryStorage=new InMemoryStorage({},defaultLogger);
1038
+
1039
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
1040
+
1041
+ function getDefaultExportFromCjs (x) {
1042
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1043
+ }
1044
+
1045
+ var store$1 = {exports: {}};
1046
+
1047
+ (function(module,exports){(function(global,factory){module.exports=factory();})(commonjsGlobal,function(){function isJSON(obj){obj=JSON.stringify(obj);if(!/^\{[\s\S]*\}$/.test(obj)){return false;}return true;}function stringify(val){return val===undefined||typeof val==="function"?val+'':JSON.stringify(val);}function deserialize(value){if(typeof value!=='string'){return undefined;}try{return JSON.parse(value);}catch(e){return value;}}function isFunction(value){return {}.toString.call(value)==="[object Function]";}function isArray(value){return Object.prototype.toString.call(value)==="[object Array]";}// https://github.com/jaywcjlove/store.js/pull/8
1048
+ // Error: QuotaExceededError
1049
+ function dealIncognito(storage){var _KEY='_Is_Incognit',_VALUE='yes';try{// NOTE: set default storage when not passed in
1050
+ if(!storage){storage=window.localStorage;}storage.setItem(_KEY,_VALUE);storage.removeItem(_KEY);}catch(e){var inMemoryStorage={};inMemoryStorage._data={};inMemoryStorage.setItem=function(id,val){return inMemoryStorage._data[id]=String(val);};inMemoryStorage.getItem=function(id){return inMemoryStorage._data.hasOwnProperty(id)?inMemoryStorage._data[id]:undefined;};inMemoryStorage.removeItem=function(id){return delete inMemoryStorage._data[id];};inMemoryStorage.clear=function(){return inMemoryStorage._data={};};storage=inMemoryStorage;}finally{if(storage.getItem(_KEY)===_VALUE)storage.removeItem(_KEY);}return storage;}// deal QuotaExceededError if user use incognito mode in browser
1051
+ var storage=dealIncognito();function Store(){if(!(this instanceof Store)){return new Store();}}Store.prototype={set:function set(key,val){if(key&&!isJSON(key)){storage.setItem(key,stringify(val));}else if(isJSON(key)){for(var a in key)this.set(a,key[a]);}return this;},get:function get(key){if(!key){var ret={};this.forEach(function(key,val){return ret[key]=val;});return ret;}if(key.charAt(0)==='?'){return this.has(key.substr(1));}var args=arguments;if(args.length>1){var dt={};for(var i=0,len=args.length;i<len;i++){var value=deserialize(storage.getItem(args[i]));if(this.has(args[i])){dt[args[i]]=value;}}return dt;}return deserialize(storage.getItem(key));},clear:function clear(){storage.clear();return this;},remove:function remove(key){var val=this.get(key);storage.removeItem(key);return val;},has:function has(key){return {}.hasOwnProperty.call(this.get(),key);},keys:function keys(){var d=[];this.forEach(function(k){d.push(k);});return d;},forEach:function forEach(callback){for(var i=0,len=storage.length;i<len;i++){var key=storage.key(i);callback(key,this.get(key));}return this;},search:function search(str){var arr=this.keys(),dt={};for(var i=0,len=arr.length;i<len;i++){if(arr[i].indexOf(str)>-1)dt[arr[i]]=this.get(arr[i]);}return dt;}};var _Store=null;function store(key,data){var argm=arguments;var dt=null;if(!_Store)_Store=Store();if(argm.length===0)return _Store.get();if(argm.length===1){if(typeof key==="string")return _Store.get(key);if(isJSON(key))return _Store.set(key);}if(argm.length===2&&typeof key==="string"){if(!data)return _Store.remove(key);if(data&&typeof data==="string")return _Store.set(key,data);if(data&&isFunction(data)){dt=null;dt=data(key,_Store.get(key));store.set(key,dt);}}if(argm.length===2&&isArray(key)&&isFunction(data)){for(var i=0,len=key.length;i<len;i++){dt=data(key[i],_Store.get(key[i]));store.set(key[i],dt);}}return store;}for(var a in Store.prototype)store[a]=Store.prototype[a];return store;});})(store$1);var storeExports=store$1.exports;const store = /*@__PURE__*/getDefaultExportFromCjs(storeExports);
1052
+
1053
+ // check if the get, set overloads and search methods are used at all
1054
+ // if we do, ensure we provide types to support overloads as per storejs docs
1055
+ // https://www.npmjs.com/package/storejs
1056
+ /**
1057
+ * A storage utility to persist values in localstorage via Storage interface
1058
+ */class LocalStorage{isSupportAvailable=true;isEnabled=true;length=0;constructor(options={},logger){this.options=getDefaultLocalStorageOptions();this.logger=logger;this.configure(options);}configure(options){this.options=mergeDeepRight(this.options,options);this.isSupportAvailable=isStorageAvailable(LOCAL_STORAGE,this,this.logger);this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){store.set(key,value);this.length=store.keys().length;}// eslint-disable-next-line class-methods-use-this
1059
+ getItem(key){const value=store.get(key);return isUndefined(value)?null:value;}removeItem(key){store.remove(key);this.length=store.keys().length;}clear(){store.clear();this.length=0;}// eslint-disable-next-line class-methods-use-this
1060
+ key(index){return store.keys()[index];}}const defaultLocalStorage=new LocalStorage({},defaultLogger);
1061
+
1062
+ /**
1063
+ * A utility to retrieve the storage singleton instance by type
1064
+ */const getStorageEngine=type=>{switch(type){case LOCAL_STORAGE:return defaultLocalStorage;case SESSION_STORAGE:return globalThis.sessionStorage;case MEMORY_STORAGE:return defaultInMemoryStorage;case COOKIE_STORAGE:return new CookieStorage({},defaultLogger);default:return defaultInMemoryStorage;}};/**
1065
+ * Configure cookie storage singleton
1066
+ */const configureCookieStorageEngine=options=>{new CookieStorage({},defaultLogger).configure(options);};/**
1067
+ * Configure local storage singleton
1068
+ */const configureLocalStorageEngine=options=>{defaultLocalStorage.configure(options);};/**
1069
+ * Configure in memory storage singleton
1070
+ */const configureInMemoryStorageEngine=options=>{defaultInMemoryStorage.configure(options);};/**
1071
+ * Configure all storage singleton instances
1072
+ */const configureStorageEngines=(cookieOptions={},localStorageOptions={},inMemoryStorageOptions={})=>{configureCookieStorageEngine(cookieOptions);configureLocalStorageEngine(localStorageOptions);configureInMemoryStorageEngine(inMemoryStorageOptions);};
1073
+
1074
+ /**
1075
+ * Store Implementation with dedicated storage
1076
+ */class Store{hasErrorHandler=false;constructor(config,engine,pluginsManager){this.id=config.id;this.name=config.name;this.isEncrypted=config.isEncrypted??false;this.validKeys=config.validKeys??{};this.engine=engine??getStorageEngine(LOCAL_STORAGE);this.noKeyValidation=Object.keys(this.validKeys).length===0;this.noCompoundKey=config.noCompoundKey;this.originalEngine=this.engine;this.errorHandler=config.errorHandler??defaultErrorHandler;this.hasErrorHandler=Boolean(this.errorHandler);this.logger=config.logger??defaultLogger;this.pluginsManager=pluginsManager;}/**
1077
+ * Ensure the key is valid and with correct format
1078
+ */createValidKey(key){const{name,id,validKeys,noKeyValidation,noCompoundKey}=this;if(noKeyValidation){return noCompoundKey?key:[name,id,key].join('.');}// validate and return undefined if invalid key
1079
+ let compoundKey;Object.values(validKeys).forEach(validKeyName=>{if(validKeyName===key){compoundKey=noCompoundKey?key:[name,id,key].join('.');}});return compoundKey;}/**
1080
+ * Switch to inMemoryEngine, bringing any existing data with.
1081
+ */swapQueueStoreToInMemoryEngine(){const{name,id,validKeys,noCompoundKey}=this;const inMemoryStorage=getStorageEngine(MEMORY_STORAGE);// grab existing data, but only for this page's queue instance, not all
1082
+ // better to keep other queues in localstorage to be flushed later
1083
+ // than to pull them into memory and remove them from durable storage
1084
+ Object.keys(validKeys).forEach(key=>{const value=this.get(validKeys[key]);const validKey=noCompoundKey?key:[name,id,key].join('.');inMemoryStorage.setItem(validKey,value);// TODO: are we sure we want to drop clientData
1085
+ // if cookies are not available and localstorage is full?
1086
+ this.remove(key);});this.engine=inMemoryStorage;}/**
1087
+ * Set value by key.
1088
+ */set(key,value){const validKey=this.createValidKey(key);if(!validKey){return;}try{// storejs that is used in localstorage engine already stringifies json
1089
+ this.engine.setItem(validKey,this.encrypt(stringifyWithoutCircular(value,false,[],this.logger)));}catch(err){if(isStorageQuotaExceeded(err)){this.logger?.warn(STORAGE_QUOTA_EXCEEDED_WARNING(STORE_MANAGER));// switch to inMemory engine
1090
+ this.swapQueueStoreToInMemoryEngine();// and save it there
1091
+ this.set(key,value);}else {this.onError(getMutatedError(err,STORE_DATA_SAVE_ERROR(key)));}}}/**
1092
+ * Get by Key.
1093
+ */get(key){const validKey=this.createValidKey(key);try{if(!validKey){return null;}const str=this.decrypt(this.engine.getItem(validKey));if(isNullOrUndefined(str)){return null;}// storejs that is used in localstorage engine already deserializes json strings but swallows errors
1094
+ return JSON.parse(str);}catch(err){this.onError(new Error(`${STORE_DATA_FETCH_ERROR(key)}: ${err.message}`));return null;}}/**
1095
+ * Remove by Key.
1096
+ */remove(key){const validKey=this.createValidKey(key);if(validKey){this.engine.removeItem(validKey);}}/**
1097
+ * Get original engine
1098
+ */getOriginalEngine(){return this.originalEngine;}/**
1099
+ * Decrypt values
1100
+ */decrypt(value){if(isNullOrUndefined(value)){return null;}return this.crypto(value,'decrypt');}/**
1101
+ * Encrypt value
1102
+ */encrypt(value){return this.crypto(value,'encrypt');}/**
1103
+ * Extension point to use with encryption plugins
1104
+ */crypto(value,mode){const noEncryption=!this.isEncrypted||!value||typeof value!=='string'||trim(value)==='';if(noEncryption){return value;}const extensionPointName=`storage.${mode}`;const formattedValue=this.pluginsManager?this.pluginsManager.invokeSingle(extensionPointName,value):value;return typeof formattedValue==='undefined'?value:formattedValue??'';}/**
1105
+ * Handle errors
1106
+ */onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,`Store ${this.id}`);}else {throw error;}}}
1107
+
1108
+ /**
1109
+ * A service to manage stores & available storage client configurations
1110
+ */class StoreManager{stores={};isInitialized=false;hasErrorHandler=false;constructor(pluginsManager,errorHandler,logger){this.errorHandler=errorHandler;this.logger=logger;this.hasErrorHandler=Boolean(this.errorHandler);this.pluginsManager=pluginsManager;this.onError=this.onError.bind(this);}/**
1111
+ * Configure available storage client instances
1112
+ */init(){if(this.isInitialized){return;}const config={cookieOptions:{samesite:state.loadOptions.value.sameSiteCookie,secure:state.loadOptions.value.secureCookie,domain:state.loadOptions.value.setCookieDomain,enabled:true},localStorageOptions:{enabled:true},inMemoryStorageOptions:{enabled:true}};configureStorageEngines(removeUndefinedValues(config.cookieOptions),removeUndefinedValues(config.localStorageOptions),removeUndefinedValues(config.inMemoryStorageOptions));this.initClientDataStore();this.isInitialized=true;}/**
1113
+ * Create store to persist data used by the SDK like session, used details etc
1114
+ */initClientDataStore(){let storageType='';// First try setting the storage to cookie else to localstorage
1115
+ if(getStorageEngine(COOKIE_STORAGE)?.isEnabled){storageType=COOKIE_STORAGE;}else if(getStorageEngine(LOCAL_STORAGE)?.isEnabled){storageType=LOCAL_STORAGE;}// TODO: fallback to in-memory storage if not other storage is available
1116
+ // TODO: should we fallback to session storage instead so we retain values on page refresh, navigation etc?
1117
+ if(!storageType){this.logger?.error(STORAGE_UNAVAILABLE_ERROR(STORE_MANAGER));return;}// TODO: fill in extra config values and bring them in from StoreManagerOptions if needed
1118
+ // TODO: should we pass the keys for all in order to validate or leave free as v1.1?
1119
+ this.setStore({id:CLIENT_DATA_STORE_NAME,name:CLIENT_DATA_STORE_NAME,isEncrypted:true,noCompoundKey:true,type:storageType});}/**
1120
+ * Create a new store
1121
+ */setStore(storeConfig){const storageEngine=getStorageEngine(storeConfig.type);this.stores[storeConfig.id]=new Store(storeConfig,storageEngine,this.pluginsManager);return this.stores[storeConfig.id];}/**
1122
+ * Retrieve a store
1123
+ */getStore(id){return this.stores[id];}/**
1124
+ * Handle errors
1125
+ */onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,STORE_MANAGER);}else {throw error;}}}
1126
+
1127
+ /**
1128
+ * Removes trailing slash from url
1129
+ * @param url
1130
+ * @returns url
1131
+ */const removeTrailingSlashes=url=>url&&url.endsWith('/')?removeTrailingSlashes(url.substring(0,url.length-1)):url;/**
1132
+ * Checks if provided url is valid or not
1133
+ * @param url
1134
+ * @returns true if `url` is valid and false otherwise
1135
+ */const isValidUrl=url=>{try{const validUrl=new URL(url);return Boolean(validUrl);}catch(err){return false;}};/**
1136
+ * Get the referring domain from the referrer URL
1137
+ * @param referrer Page referrer
1138
+ * @returns Page referring domain
1139
+ */const getReferringDomain=referrer=>{let referringDomain='';try{const url=new URL(referrer);referringDomain=url.host;}catch(error){// Do nothing
1140
+ }return referringDomain;};/**
1141
+ * Extracts UTM parameters from the URL
1142
+ * @param url Page URL
1143
+ * @returns UTM parameters
1144
+ */const extractUTMParameters=url=>{const result={};try{const urlObj=new URL(url);const UTM_PREFIX='utm_';urlObj.searchParams.forEach((value,sParam)=>{if(sParam.startsWith(UTM_PREFIX)){let utmParam=sParam.substring(UTM_PREFIX.length);// Not sure why we're doing this
1145
+ if(utmParam==='campaign'){utmParam='name';}result[utmParam]=value;}});}catch(error){// Do nothing
1146
+ }return result;};/**
1147
+ * To get the URL until the hash
1148
+ * @param url The input URL
1149
+ * @returns URL until the hash
1150
+ */const getUrlWithoutHash=url=>{let urlWithoutHash=url;try{const urlObj=new URL(url);urlWithoutHash=urlObj.origin+urlObj.pathname+urlObj.search;}catch(error){// Do nothing
1151
+ }return urlWithoutHash;};
1152
+
1153
+ const validateWriteKey=writeKey=>{if(!writeKey||writeKey.trim().length===0){throw new Error(WRITE_KEY_VALIDATION_ERROR(writeKey));}};const validateDataPlaneUrl=dataPlaneUrl=>{if(dataPlaneUrl&&!isValidUrl(dataPlaneUrl)){throw new Error(DATA_PLANE_URL_VALIDATION_ERROR(dataPlaneUrl));}};const validateLoadArgs=(writeKey,dataPlaneUrl)=>{validateWriteKey(writeKey);validateDataPlaneUrl(dataPlaneUrl);};const isValidSourceConfig=res=>isObjectLiteralAndNotNull(res)&&isObjectLiteralAndNotNull(res.source)&&!isNullOrUndefined(res.source.id)&&isObjectLiteralAndNotNull(res.source.config)&&Array.isArray(res.source.destinations);
1154
+
1155
+ /**
1156
+ * A function to filter enabled destinations and map to required properties only
1157
+ * @param destinations
1158
+ *
1159
+ * @returns Destination[]
1160
+ */const filterEnabledDestination=destinations=>{const nativeDestinations=[];destinations.forEach(destination=>{if(destination.enabled&&!destination.deleted){nativeDestinations.push({id:destination.id,displayName:destination.destinationDefinition.displayName,config:destination.config,shouldApplyDeviceModeTransformation:destination.shouldApplyDeviceModeTransformation||false,propagateEventsUntransformedOnError:destination.propagateEventsUntransformedOnError||false,userFriendlyId:`${destination.destinationDefinition.displayName.replaceAll(' ','-')}___${destination.id}`});}});return nativeDestinations;};
1161
+
1162
+ const defaultOptionalPluginsList=[PluginName.Bugsnag,PluginName.DeviceModeDestinations,PluginName.ErrorReporting,PluginName.ExternalAnonymousId,PluginName.GoogleLinker,PluginName.NativeDestinationQueue,PluginName.StorageEncryption,PluginName.StorageEncryptionLegacy,PluginName.StorageMigrator,PluginName.XhrQueue,PluginName.OneTrustConsentManager,PluginName.KetchConsentManager,PluginName.BeaconQueue];
1163
+
1164
+ const normalizeLoadOptions=(loadOptionsFromState,loadOptions)=>{// TODO: add all the validations as per
1165
+ // https://github.com/rudderlabs/rudder-sdk-js/blob/a620e11f98e1438be34114ad40b325201b1d7a6e/src/core/analytics.js#L1156
1166
+ // TODO: Maybe add warnings for invalid values
1167
+ const normalizedLoadOpts=clone$1(loadOptions);normalizedLoadOpts.setCookieDomain=isDefined(normalizedLoadOpts.setCookieDomain)&&isString(normalizedLoadOpts.setCookieDomain)?normalizedLoadOpts.setCookieDomain:undefined;normalizedLoadOpts.secureCookie=normalizedLoadOpts.secureCookie===true;normalizedLoadOpts.sameSiteCookie=isDefined(normalizedLoadOpts.sameSiteCookie)&&Object.values(CookieSameSite).includes(normalizedLoadOpts.sameSiteCookie)?normalizedLoadOpts.sameSiteCookie:undefined;normalizedLoadOpts.plugins=normalizedLoadOpts.plugins??defaultOptionalPluginsList;normalizedLoadOpts.useGlobalIntegrationsConfigInEvents=normalizedLoadOpts.useGlobalIntegrationsConfigInEvents===true;normalizedLoadOpts.bufferDataPlaneEventsUntilReady=normalizedLoadOpts.bufferDataPlaneEventsUntilReady===true;normalizedLoadOpts.sendAdblockPage=normalizedLoadOpts.sendAdblockPage===true;normalizedLoadOpts.sendAdblockPageOptions=isObjectLiteralAndNotNull(normalizedLoadOpts.sendAdblockPageOptions)?normalizedLoadOpts.sendAdblockPageOptions:{};normalizedLoadOpts.storage=isObjectLiteralAndNotNull(normalizedLoadOpts.storage)?removeUndefinedAndNullValues(normalizedLoadOpts.storage):{};normalizedLoadOpts.storage.migrate=normalizedLoadOpts.storage?.migrate===true;normalizedLoadOpts.beaconQueueOptions=isObjectLiteralAndNotNull(normalizedLoadOpts.beaconQueueOptions)?removeUndefinedAndNullValues(normalizedLoadOpts.beaconQueueOptions):{};normalizedLoadOpts.destinationsQueueOptions=isObjectLiteralAndNotNull(normalizedLoadOpts.destinationsQueueOptions)?removeUndefinedAndNullValues(normalizedLoadOpts.destinationsQueueOptions):{};normalizedLoadOpts.queueOptions=isObjectLiteralAndNotNull(normalizedLoadOpts.queueOptions)?removeUndefinedAndNullValues(normalizedLoadOpts.queueOptions):{};const mergedLoadOptions=mergeDeepRight(loadOptionsFromState,normalizedLoadOpts);return mergedLoadOptions;};const getSourceConfigURL=(configUrlHost=DEFAULT_CONFIG_BE_URL)=>`${configUrlHost}/sourceConfig/?p=${MODULE_TYPE}&v=${APP_VERSION}&build=${BUILD_TYPE}`;
1168
+
1169
+ const DEFAULT_REGION='US';/**
1170
+ * A function to get url from source config response
1171
+ * @param {array} urls An array of objects containing urls
1172
+ * @returns
1173
+ */const getDefaultUrlOfRegion=urls=>{let url;if(Array.isArray(urls)&&urls.length>0){const obj=urls.find(elem=>elem.default===true);if(obj&&isValidUrl(obj.url)){return obj.url;}}return url;};const validateResidencyServerRegion=(residencyServerRegion,logger)=>{if(residencyServerRegion&&!Object.values(ResidencyServerRegion).includes(residencyServerRegion)){logger?.warn(UNSUPPORTED_RESIDENCY_SERVER_REGION_WARNING(CONFIG_MANAGER,residencyServerRegion,DEFAULT_REGION));return undefined;}return residencyServerRegion;};/**
1174
+ * A function to determine the dataPlaneUrl
1175
+ * @param {Object} dataplanes An object containing dataPlaneUrl for different region
1176
+ * @param {String} serverUrl dataPlaneUrl provided in the load call
1177
+ * @param {String} residencyServerRegion User provided residency server region
1178
+ * @param {Logger} logger logger instance
1179
+ * @returns The data plane URL string to use
1180
+ */const resolveDataPlaneUrl=(dataplanes,serverUrl,residencyServerRegion,logger)=>{// Check if dataPlanes object is present in source config
1181
+ if(dataplanes&&Object.keys(dataplanes).length>0){const region=validateResidencyServerRegion(residencyServerRegion,logger)??DEFAULT_REGION;const regionUrlArr=dataplanes[region]||dataplanes[DEFAULT_REGION];const defaultUrl=getDefaultUrlOfRegion(regionUrlArr);if(defaultUrl){return defaultUrl;}}// return the dataPlaneUrl provided in load API(if available)
1182
+ if(serverUrl){return serverUrl;}// return undefined if data plane url can not be determined
1183
+ return undefined;};
1184
+
1185
+ const isErrorReportingEnabled=sourceConfig=>sourceConfig?.statsCollection?.errors?.enabled===true;const getErrorReportingProviderNameFromConfig=sourceConfig=>sourceConfig?.statsCollection?.errors?.provider;const isMetricsReportingEnabled=sourceConfig=>sourceConfig?.statsCollection?.metrics?.enabled===true;
1186
+
1187
+ /**
1188
+ * Determines the SDK url
1189
+ * @returns sdkURL
1190
+ */const getSDKUrl=()=>{const scripts=document.getElementsByTagName('script');let sdkURL;const scriptList=Array.prototype.slice.call(scripts);scriptList.some(script=>{const curScriptSrc=removeTrailingSlashes(script.getAttribute('src'));if(curScriptSrc){const urlMatches=curScriptSrc.match(/^.*rsa?(\.min)?\.js$/);if(urlMatches){sdkURL=curScriptSrc;return true;}}return false;});// TODO: Return the URL object instead of the plain URL string
1191
+ return sdkURL;};/**
1192
+ * Updates the reporting state variables from the source config data
1193
+ * @param res Source config
1194
+ * @param logger Logger instance
1195
+ */const updateReportingState=(res,logger)=>{state.reporting.isErrorReportingEnabled.value=isErrorReportingEnabled(res.source.config);state.reporting.isMetricsReportingEnabled.value=isMetricsReportingEnabled(res.source.config);if(state.reporting.isErrorReportingEnabled.value){const errReportingProvider=getErrorReportingProviderNameFromConfig(res.source.config);// Get the corresponding plugin name of the selected error reporting provider from the supported error reporting providers
1196
+ const errReportingProviderPlugin=errReportingProvider?ErrorReportingProvidersToPluginNameMap[errReportingProvider]:undefined;if(!isUndefined(errReportingProvider)&&!errReportingProviderPlugin){// set the default error reporting provider
1197
+ logger?.warn(UNSUPPORTED_ERROR_REPORTING_PROVIDER_WARNING(CONFIG_MANAGER,errReportingProvider,ErrorReportingProvidersToPluginNameMap,DEFAULT_ERROR_REPORTING_PROVIDER));}state.reporting.errorReportingProviderPluginName.value=errReportingProviderPlugin??ErrorReportingProvidersToPluginNameMap[DEFAULT_ERROR_REPORTING_PROVIDER];}};const updateStorageState=logger=>{let storageEncryptionVersion=state.loadOptions.value.storage?.encryption?.version;const encryptionPluginName=storageEncryptionVersion&&StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];if(!isUndefined(storageEncryptionVersion)&&isUndefined(encryptionPluginName)){// set the default encryption plugin
1198
+ logger?.warn(UNSUPPORTED_STORAGE_ENCRYPTION_VERSION_WARNING(CONFIG_MANAGER,storageEncryptionVersion,StorageEncryptionVersionsToPluginNameMap,DEFAULT_STORAGE_ENCRYPTION_VERSION));storageEncryptionVersion=DEFAULT_STORAGE_ENCRYPTION_VERSION;}else if(isUndefined(storageEncryptionVersion)){storageEncryptionVersion=DEFAULT_STORAGE_ENCRYPTION_VERSION;}o(()=>{state.storage.encryptionPluginName.value=StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];// Allow migration only if the configured encryption version is the default encryption version
1199
+ const configuredMigrationValue=state.loadOptions.value.storage?.migrate;state.storage.migrate.value=configuredMigrationValue&&storageEncryptionVersion===DEFAULT_STORAGE_ENCRYPTION_VERSION;if(configuredMigrationValue===true&&state.storage.migrate.value!==configuredMigrationValue){logger?.warn(STORAGE_DATA_MIGRATION_OVERRIDE_WARNING(CONFIG_MANAGER,storageEncryptionVersion,DEFAULT_STORAGE_ENCRYPTION_VERSION));}});};
1200
+
1201
+ /**
1202
+ * A function that determines integration SDK loading path
1203
+ * @param requiredVersion
1204
+ * @param lockIntegrationsVersion
1205
+ * @param customIntegrationsCDNPath
1206
+ * @returns
1207
+ */const getIntegrationsCDNPath=(requiredVersion,lockIntegrationsVersion,customIntegrationsCDNPath)=>{let integrationsCDNPath='';// Get the CDN base URL from the user provided URL if any
1208
+ if(customIntegrationsCDNPath){integrationsCDNPath=removeTrailingSlashes(customIntegrationsCDNPath);if(!integrationsCDNPath||integrationsCDNPath&&!isValidUrl(integrationsCDNPath)){throw new Error(INTG_CDN_BASE_URL_ERROR);}return integrationsCDNPath;}// Get the base path from the SDK script tag src attribute or use the default path
1209
+ const sdkURL=getSDKUrl();integrationsCDNPath=sdkURL&&isString(sdkURL)?sdkURL.split('/').slice(0,-1).concat(CDN_INT_DIR).join('/'):DEST_SDK_BASE_URL;// If version is not locked it will always get the latest version of the integrations
1210
+ if(lockIntegrationsVersion){integrationsCDNPath=integrationsCDNPath.replace(CDN_ARCH_VERSION_DIR,requiredVersion);}return integrationsCDNPath;};/**
1211
+ * A function that determines plugins SDK loading path
1212
+ * @param customPluginsCDNPath
1213
+ * @returns
1214
+ */const getPluginsCDNPath=customPluginsCDNPath=>{let pluginsCDNPath='';// Get the CDN base URL from the user provided URL if any
1215
+ if(customPluginsCDNPath){pluginsCDNPath=removeTrailingSlashes(customPluginsCDNPath);if(!pluginsCDNPath||pluginsCDNPath&&!isValidUrl(pluginsCDNPath)){throw new Error(PLUGINS_CDN_BASE_URL_ERROR);}return pluginsCDNPath;}// Get the base path from the SDK script tag src attribute or use the default path
1216
+ const sdkURL=getSDKUrl();pluginsCDNPath=sdkURL&&isString(sdkURL)?sdkURL.split('/').slice(0,-1).concat(CDN_PLUGINS_DIR).join('/'):PLUGINS_BASE_URL;return pluginsCDNPath;};
1217
+
1218
+ /**
1219
+ * A function to get the name of the consent manager with enabled true set in the load options
1220
+ * @param cookieConsentOptions Input provided as load option
1221
+ * @returns string|undefined
1222
+ *
1223
+ * Example input: {
1224
+ * oneTrust:{
1225
+ * enabled: true
1226
+ * }
1227
+ * }
1228
+ *
1229
+ * Output: 'oneTrust'
1230
+ */const getUserSelectedConsentManager=cookieConsentOptions=>{if(!isNonEmptyObject(cookieConsentOptions)){return undefined;}const validCookieConsentOptions=cookieConsentOptions;return Object.keys(validCookieConsentOptions).find(e=>e&&validCookieConsentOptions[e].enabled===true);};
1231
+
1232
+ class ConfigManager{hasErrorHandler=false;constructor(httpClient,errorHandler,logger){this.errorHandler=errorHandler;this.logger=logger;this.httpClient=httpClient;this.hasErrorHandler=Boolean(this.errorHandler);this.onError=this.onError.bind(this);this.processConfig=this.processConfig.bind(this);}attachEffects(){b(()=>{this.logger?.setMinLogLevel(state.lifecycle.logLevel.value);});}/**
1233
+ * A function to validate, construct and store loadOption, lifecycle, source and destination
1234
+ * config related information in global state
1235
+ */init(){let consentManagerPluginName;this.attachEffects();validateLoadArgs(state.lifecycle.writeKey.value,state.lifecycle.dataPlaneUrl.value);const lockIntegrationsVersion=state.loadOptions.value.lockIntegrationsVersion===true;try{// determine the path to fetch integration SDK from
1236
+ const intgCdnUrl=getIntegrationsCDNPath(APP_VERSION,lockIntegrationsVersion,state.loadOptions.value.destSDKBaseURL);// determine the path to fetch remote plugins from
1237
+ const pluginsCDNPath=getPluginsCDNPath(state.loadOptions.value.pluginsSDKBaseURL);// Get the consent manager if provided as load option
1238
+ const selectedConsentManager=getUserSelectedConsentManager(state.loadOptions.value.cookieConsentManager);if(selectedConsentManager){// Get the corresponding plugin name of the selected consent manager from the supported consent managers
1239
+ consentManagerPluginName=ConsentManagersToPluginNameMap[selectedConsentManager];if(!consentManagerPluginName){this.logger?.error(UNSUPPORTED_CONSENT_MANAGER_ERROR(CONFIG_MANAGER,selectedConsentManager,ConsentManagersToPluginNameMap));}}updateStorageState(this.logger);// set application lifecycle state in global state
1240
+ o(()=>{state.lifecycle.integrationsCDNPath.value=intgCdnUrl;state.lifecycle.pluginsCDNPath.value=pluginsCDNPath;if(state.loadOptions.value.logLevel){state.lifecycle.logLevel.value=state.loadOptions.value.logLevel;}if(state.loadOptions.value.configUrl){state.lifecycle.sourceConfigUrl.value=new URL(`${getSourceConfigURL(state.loadOptions.value.configUrl)}&writeKey=${state.lifecycle.writeKey.value}&lockIntegrationsVersion=${lockIntegrationsVersion}`).toString();}// Set consent manager plugin name in state
1241
+ state.consents.activeConsentManagerPluginName.value=consentManagerPluginName;});}catch(err){const issue='Failed to load the SDK';this.onError(getMutatedError(err,issue));return;}this.getConfig();}/**
1242
+ * Handle errors
1243
+ */onError(error,customMessage,shouldAlwaysThrow){if(this.hasErrorHandler){this.errorHandler?.onError(error,CONFIG_MANAGER,customMessage,shouldAlwaysThrow);}else {throw error;}}/**
1244
+ * A callback function that is executed once we fetch the source config response.
1245
+ * Use to construct and store information that are dependent on the sourceConfig.
1246
+ */processConfig(response,details){// TODO: add retry logic with backoff based on rejectionDetails.xhr.status
1247
+ // We can use isErrRetryable utility method
1248
+ if(!response){this.onError(SOURCE_CONFIG_FETCH_ERROR(details?.error));return;}let res;const errMessage='Unable to process/parse source config';try{if(isString(response)){res=JSON.parse(response);}else {res=response;}}catch(e){this.onError(e,errMessage,true);return;}if(!isValidSourceConfig(res)){this.onError(new Error(errMessage),undefined,true);return;}// determine the dataPlane url
1249
+ const dataPlaneUrl=resolveDataPlaneUrl(res.source.dataplanes,state.lifecycle.dataPlaneUrl.value,state.loadOptions.value.residencyServer,this.logger);if(!dataPlaneUrl){this.onError(new Error(DATA_PLANE_URL_ERROR),undefined,true);return;}const nativeDestinations=res.source.destinations.length>0?filterEnabledDestination(res.source.destinations):[];// set in the state --> source, destination, lifecycle, reporting
1250
+ o(()=>{// set source related information in state
1251
+ state.source.value={config:res.source.config,id:res.source.id};// set device mode destination related information in state
1252
+ state.nativeDestinations.configuredDestinations.value=nativeDestinations;// set application lifecycle state
1253
+ // Cast to string as we are sure that the value is not undefined
1254
+ state.lifecycle.activeDataplaneUrl.value=removeTrailingSlashes(dataPlaneUrl);state.lifecycle.status.value=LifecycleStatus.Configured;// set the values in state for reporting slice
1255
+ updateReportingState(res,this.logger);// set the desired optional plugins
1256
+ state.plugins.pluginsToLoadFromConfig.value=state.loadOptions.value.plugins??[];// set application lifecycle state
1257
+ state.lifecycle.activeDataplaneUrl.value=dataPlaneUrl;state.lifecycle.status.value=LifecycleStatus.Configured;});}/**
1258
+ * A function to fetch source config either from /sourceConfig endpoint
1259
+ * or from getSourceConfig load option
1260
+ * @returns
1261
+ */getConfig(){const sourceConfigFunc=state.loadOptions.value.getSourceConfig;if(sourceConfigFunc){if(!isFunction(sourceConfigFunc)){throw new Error(SOURCE_CONFIG_OPTION_ERROR);}// fetch source config from the function
1262
+ const res=sourceConfigFunc();if(res instanceof Promise){res.then(pRes=>this.processConfig(pRes)).catch(err=>{this.onError(err,'SourceConfig');});}else {this.processConfig(res);}return;}// fetch source config from config url API
1263
+ this.httpClient.getAsyncData({url:state.lifecycle.sourceConfigUrl.value,options:{headers:{'Content-Type':undefined}},callback:this.processConfig});}}
1264
+
1265
+ /**
1266
+ * Get the referrer URL
1267
+ * @returns The referrer URL
1268
+ */const getReferrer=()=>document.referrer||'$direct';/**
1269
+ * To get the canonical URL of the page
1270
+ * @returns canonical URL
1271
+ */const getCanonicalUrl=()=>{const tags=document.getElementsByTagName('link');let canonicalUrl='';for(let i=0;tags[i];i+=1){const tag=tags[i];if(tag.getAttribute('rel')==='canonical'&&!canonicalUrl){canonicalUrl=tag.getAttribute('href')??'';break;}}return canonicalUrl;};const getUserAgent=()=>{if(isUndefined(globalThis.navigator)){return null;}let{userAgent}=globalThis.navigator;const{brave}=globalThis.navigator;// For supporting Brave browser detection,
1272
+ // add "Brave/<version>" to the user agent with the version value from the Chrome component
1273
+ if(brave&&Object.getPrototypeOf(brave).isBrave){// Example:
1274
+ // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36
1275
+ const matchedArr=userAgent.match(/(chrome)\/([\w.]+)/i);if(matchedArr){userAgent=`${userAgent} Brave/${matchedArr[2]}`;}}return userAgent;};const getLanguage=()=>{if(isUndefined(globalThis.navigator)){return null;}return globalThis.navigator.language??globalThis.navigator.browserLanguage;};/**
1276
+ * Default page properties
1277
+ * @returns Default page properties
1278
+ */const getDefaultPageProperties=()=>{const canonicalUrl=getCanonicalUrl();let path=globalThis.location.pathname;const{href:tabUrl}=globalThis.location;let pageUrl=tabUrl;const{search}=globalThis.location;// If valid canonical url is provided use this as page url.
1279
+ if(canonicalUrl){try{const urlObj=new URL(canonicalUrl);// If existing, query params of canonical url will be used instead of the location.search ones
1280
+ if(urlObj.search===''){pageUrl=canonicalUrl+search;}else {pageUrl=canonicalUrl;}path=urlObj.pathname;}catch(err){// Do nothing
1281
+ }}const url=getUrlWithoutHash(pageUrl);const{title}=document;const referrer=getReferrer();return {path,referrer,referring_domain:getReferringDomain(referrer),search,title,url,tab_url:tabUrl};};
1282
+
1283
+ const POLYFILL_URL=`https://polyfill.io/v3/polyfill.min.js?features=${Object.keys(legacyJSEngineRequiredPolyfills).join('%2C')}`;const POLYFILL_LOAD_TIMEOUT=10*1000;// 10 seconds
1284
+ const POLYFILL_SCRIPT_ID='rudderstackPolyfill';
1285
+
1286
+ class CapabilitiesManager{constructor(errorHandler,logger){this.logger=logger;this.errorHandler=errorHandler;this.externalSrcLoader=new ExternalSrcLoader(this.errorHandler,this.logger);this.onError=this.onError.bind(this);this.onReady=this.onReady.bind(this);}init(){try{this.prepareBrowserCapabilities();this.attachWindowListeners();}catch(e){this.onError(e);}}/**
1287
+ * Detect supported capabilities and set values in state
1288
+ */ // eslint-disable-next-line class-methods-use-this
1289
+ detectBrowserCapabilities(){o(()=>{// Storage related details
1290
+ state.capabilities.storage.isCookieStorageAvailable.value=isStorageAvailable(COOKIE_STORAGE,getStorageEngine(COOKIE_STORAGE),this.logger);state.capabilities.storage.isLocalStorageAvailable.value=isStorageAvailable(LOCAL_STORAGE,undefined,this.logger);state.capabilities.storage.isSessionStorageAvailable.value=isStorageAvailable(SESSION_STORAGE,undefined,this.logger);// Browser feature detection details
1291
+ state.capabilities.isBeaconAvailable.value=hasBeacon();state.capabilities.isUaCHAvailable.value=hasUAClientHints();state.capabilities.isCryptoAvailable.value=hasCrypto$1();state.capabilities.isIE11.value=isIE11();state.capabilities.isOnline.value=globalThis.navigator.onLine;// Get page context details
1292
+ state.context.userAgent.value=getUserAgent();state.context.locale.value=getLanguage();state.context.screen.value=getScreenDetails();state.context.campaign.value=extractUTMParameters(globalThis.location.href);if(hasUAClientHints()){getUserAgentClientHint(uach=>{state.context['ua-ch'].value=uach;},state.loadOptions.value.uaChTrackLevel);}// Get page properties details
1293
+ const pageProperties=getDefaultPageProperties();state.page.path.value=pageProperties.path;state.page.referrer.value=pageProperties.referrer;state.page.referring_domain.value=pageProperties.referring_domain;state.page.search.value=pageProperties.search;state.page.title.value=pageProperties.title;state.page.url.value=pageProperties.url;state.page.tab_url.value=pageProperties.tab_url;});// Ad blocker detection
1294
+ b(()=>{if(state.loadOptions.value.sendAdblockPage===true&&state.lifecycle.sourceConfigUrl.value!==undefined){detectAdBlockers(this.errorHandler,this.logger);}});}/**
1295
+ * Detect if polyfills are required and then load script from polyfill URL
1296
+ */prepareBrowserCapabilities(){state.capabilities.isLegacyDOM.value=isLegacyJSEngine();const polyfillUrl=state.loadOptions.value.polyfillURL??POLYFILL_URL;const shouldLoadPolyfill=state.loadOptions.value.polyfillIfRequired&&state.capabilities.isLegacyDOM.value&&Boolean(polyfillUrl);if(shouldLoadPolyfill){// TODO: check if polyfill has been evaluated via polling or
1297
+ // with the callback param in its url and an exposed function
1298
+ const onPolyfillLoad=scriptId=>Boolean(scriptId)&&this.onReady();this.externalSrcLoader?.loadJSFile({url:state.loadOptions.value.polyfillURL??POLYFILL_URL,id:POLYFILL_SCRIPT_ID,async:true,timeout:POLYFILL_LOAD_TIMEOUT,callback:onPolyfillLoad});}else {this.onReady();}}/**
1299
+ * Attach listeners to window to observe event that update capabilities state values
1300
+ */ // eslint-disable-next-line class-methods-use-this
1301
+ attachWindowListeners(){globalThis.addEventListener('offline',()=>{state.capabilities.isOnline.value=false;});globalThis.addEventListener('online',()=>{state.capabilities.isOnline.value=true;});// TODO: add debounched listener for globalThis.onResize event and update state.context.screen.value
1302
+ }/**
1303
+ * Set the lifecycle status to next phase
1304
+ */ // eslint-disable-next-line class-methods-use-this
1305
+ onReady(){this.detectBrowserCapabilities();state.lifecycle.status.value=LifecycleStatus.BrowserCapabilitiesReady;}/**
1306
+ * Handles error
1307
+ * @param error The error object
1308
+ */onError(error){if(this.errorHandler){this.errorHandler.onError(error,CAPABILITIES_MANAGER);}else {throw error;}}}
1309
+
1310
+ // TODO: should we take the types from IdentifyTrait instead of any string key?
1311
+ // https://www.rudderstack.com/docs/event-spec/standard-events/identify/#identify-traits
1312
+ /**
1313
+ * Represents the options parameter in the APIs
1314
+ */let RudderEventType=/*#__PURE__*/function(RudderEventType){RudderEventType["Page"]="page";RudderEventType["Track"]="track";RudderEventType["Identify"]="identify";RudderEventType["Alias"]="alias";RudderEventType["Group"]="group";return RudderEventType;}({});
1315
+
1316
+ const CHANNEL='web';// These are the top-level elements in the standard RudderStack event spec
1317
+ const TOP_LEVEL_ELEMENTS=['integrations','anonymousId','originalTimestamp'];// Reserved elements in the context of standard RudderStack event spec
1318
+ // Typically, these elements are not allowed to be overridden by the user
1319
+ const CONTEXT_RESERVED_ELEMENTS=['library','consentManagement','userAgent','ua-ch','screen'];// Reserved elements in the standard RudderStack event spec
1320
+ const RESERVED_ELEMENTS=['anonymousId','sentAt','receivedAt','timestamp','originalTimestamp','event','messageId','channel'];const DEFAULT_INTEGRATIONS_CONFIG={All:true};
1321
+
1322
+ /**
1323
+ * To get the page properties for context object
1324
+ * @param pageProps Page properties
1325
+ * @returns page properties object for context
1326
+ */const getContextPageProperties=pageProps=>{const ctxPageProps={};Object.keys(state.page).forEach(key=>{ctxPageProps[key]=pageProps?.[key]||state.page[key].value;});ctxPageProps.initial_referrer=pageProps?.initial_referrer||state.session.initialReferrer.value;ctxPageProps.initial_referring_domain=pageProps?.initial_referring_domain||state.session.initialReferringDomain.value;return ctxPageProps;};/**
1327
+ * Add any missing default page properties using values from options and defaults
1328
+ * @param properties Input page properties
1329
+ * @param options API options
1330
+ */const getUpdatedPageProperties=(properties,options)=>{const optionsPageProps=options?.page||{};const pageProps=properties;Object.keys(state.page).forEach(key=>{if(isUndefined(pageProps[key])){pageProps[key]=optionsPageProps[key]||state.page[key].value;}});if(isUndefined(pageProps.initial_referrer)){pageProps.initial_referrer=optionsPageProps.initial_referrer||state.session.initialReferrer.value;}if(isUndefined(pageProps.initial_referring_domain)){pageProps.initial_referring_domain=optionsPageProps.initial_referring_domain||state.session.initialReferringDomain.value;}return pageProps;};/**
1331
+ * Utility to check for reserved keys in the input object
1332
+ * @param obj Generic object
1333
+ * @param eventType Rudder event type
1334
+ * @param parentKeyPath Object's parent key path
1335
+ * @param logger Logger instance
1336
+ */const checkForReservedElementsInObject=(obj,parentKeyPath,logger)=>{if(isObjectLiteralAndNotNull(obj)){Object.keys(obj).forEach(property=>{if(RESERVED_ELEMENTS.includes(property)||RESERVED_ELEMENTS.includes(property.toLowerCase())){logger?.warn(RESERVED_KEYWORD_WARNING(EVENT_MANAGER,property,parentKeyPath,RESERVED_ELEMENTS));}});}};/**
1337
+ * Checks for reserved keys in traits, properties, and contextual traits
1338
+ * @param rudderEvent Generated rudder event
1339
+ * @param logger Logger instance
1340
+ */const checkForReservedElements=(rudderEvent,logger)=>{// properties, traits, contextualTraits are either undefined or object
1341
+ const{properties,traits,context}=rudderEvent;const{traits:contextualTraits}=context;checkForReservedElementsInObject(properties,'properties',logger);checkForReservedElementsInObject(traits,'traits',logger);checkForReservedElementsInObject(contextualTraits,'context.traits',logger);};/**
1342
+ * Overrides the top-level event properties with data from API options
1343
+ * @param rudderEvent Generated rudder event
1344
+ * @param options API options
1345
+ */const updateTopLevelEventElements=(rudderEvent,options)=>{if(options.anonymousId&&isString(options.anonymousId)){// eslint-disable-next-line no-param-reassign
1346
+ rudderEvent.anonymousId=options.anonymousId;}if(options.integrations&&isObjectLiteralAndNotNull(options.integrations)){// eslint-disable-next-line no-param-reassign
1347
+ rudderEvent.integrations=options.integrations;}if(options.originalTimestamp&&isString(options.originalTimestamp)){// eslint-disable-next-line no-param-reassign
1348
+ rudderEvent.originalTimestamp=options.originalTimestamp;}};/**
1349
+ * To merge the contextual information in API options with existing data
1350
+ * @param rudderContext Generated rudder event
1351
+ * @param options API options
1352
+ * @param logger Logger instance
1353
+ */const getMergedContext=(rudderContext,options,logger)=>{let context=rudderContext;Object.keys(options).forEach(key=>{if(!TOP_LEVEL_ELEMENTS.includes(key)&&!CONTEXT_RESERVED_ELEMENTS.includes(key)){if(key!=='context'){context=mergeDeepRight(context,{[key]:options[key]});}else if(!isUndefined(options[key])&&isObjectLiteralAndNotNull(options[key])){const tempContext={};Object.keys(options[key]).forEach(e=>{if(!CONTEXT_RESERVED_ELEMENTS.includes(e)){tempContext[e]=options[key][e];}});context=mergeDeepRight(context,{...tempContext});}else {logger?.warn(INVALID_CONTEXT_OBJECT_WARNING(EVENT_MANAGER));}}});return context;};/**
1354
+ * A function to determine whether SDK should use the integration option provided in load call
1355
+ * @returns boolean
1356
+ */const shouldUseGlobalIntegrationsConfigInEvents=()=>state.loadOptions.value.useGlobalIntegrationsConfigInEvents&&isObjectLiteralAndNotNull(state.nativeDestinations.loadOnlyIntegrations.value);/**
1357
+ * Updates rudder event object with data from the API options
1358
+ * @param rudderEvent Generated rudder event
1359
+ * @param options API options
1360
+ */const processOptions=(rudderEvent,options)=>{// Only allow object type for options
1361
+ if(!isNullOrUndefined(options)&&isObjectLiteralAndNotNull(options)){updateTopLevelEventElements(rudderEvent,options);// eslint-disable-next-line no-param-reassign
1362
+ rudderEvent.context=getMergedContext(rudderEvent.context,options);}};/**
1363
+ * Returns the final integrations config for the event based on the global config and event's config
1364
+ * @param integrationsConfig Event's integrations config
1365
+ * @returns Final integrations config
1366
+ */const getEventIntegrationsConfig=integrationsConfig=>{let finalIntgConfig;if(shouldUseGlobalIntegrationsConfigInEvents()){finalIntgConfig=state.nativeDestinations.loadOnlyIntegrations.value;}else if(isObjectLiteralAndNotNull(integrationsConfig)){finalIntgConfig=integrationsConfig;}else {finalIntgConfig=DEFAULT_INTEGRATIONS_CONFIG;}return finalIntgConfig;};/**
1367
+ * Enrich the base event object with data from state and the API options
1368
+ * @param rudderEvent RudderEvent object
1369
+ * @param options API options
1370
+ * @param pageProps Page properties
1371
+ * @param logger logger
1372
+ * @returns Enriched RudderEvent object
1373
+ */const getEnrichedEvent=(rudderEvent,options,pageProps,logger)=>{const commonEventData={// Type casting to string as the user session manager will take care of initializing the value
1374
+ anonymousId:state.session.anonymousUserId.value,channel:CHANNEL,context:{traits:clone$1(state.session.userTraits.value),sessionId:state.session.sessionInfo.value.id,sessionStart:state.session.sessionInfo.value.sessionStart||undefined,consentManagement:{deniedConsentIds:clone$1(state.consents.data.value.deniedConsentIds)},'ua-ch':state.context['ua-ch'].value,app:state.context.app.value,library:state.context.library.value,userAgent:state.context.userAgent.value,os:state.context.os.value,locale:state.context.locale.value,screen:state.context.screen.value,campaign:clone$1(state.context.campaign.value),page:getContextPageProperties(pageProps)},originalTimestamp:getCurrentTimeFormatted(),integrations:DEFAULT_INTEGRATIONS_CONFIG,messageId:generateUUID(),userId:state.session.userId.value};if(rudderEvent.type===RudderEventType.Group){commonEventData.groupId=state.session.groupId.value;commonEventData.traits=clone$1(state.session.groupTraits.value);}const processedEvent=mergeDeepRight(rudderEvent,commonEventData);// Set the default values for the event properties
1375
+ // matching with v1.1 payload
1376
+ if(processedEvent.event===undefined){processedEvent.event=null;}if(processedEvent.properties===undefined){processedEvent.properties=null;}processOptions(processedEvent,options);// TODO: We might not need this check altogether
1377
+ checkForReservedElements(processedEvent,logger);// Update the integrations config for the event
1378
+ processedEvent.integrations=getEventIntegrationsConfig(processedEvent.integrations);return processedEvent;};
1379
+
1380
+ class RudderEventFactory{constructor(logger){this.logger=logger;}/**
1381
+ * Generate a 'page' event based on the user-input fields
1382
+ * @param category Page's category
1383
+ * @param name Page name
1384
+ * @param properties Page properties
1385
+ * @param options API options
1386
+ */generatePageEvent(category,name,properties,options){let props=properties??{};props.name=name;props.category=category;props=getUpdatedPageProperties(props,options);const pageEvent={properties:props,name,category,type:RudderEventType.Page};return getEnrichedEvent(pageEvent,options,props,this.logger);}/**
1387
+ * Generate a 'track' event based on the user-input fields
1388
+ * @param event The event name
1389
+ * @param properties Event properties
1390
+ * @param options API options
1391
+ */generateTrackEvent(event,properties,options){const trackEvent={properties,event,type:RudderEventType.Track};return getEnrichedEvent(trackEvent,options,undefined,this.logger);}/**
1392
+ * Generate an 'identify' event based on the user-input fields
1393
+ * @param options API options
1394
+ */generateIdentifyEvent(options){const identifyEvent={type:RudderEventType.Identify};return getEnrichedEvent(identifyEvent,options,undefined,this.logger);}/**
1395
+ * Generate an 'alias' event based on the user-input fields
1396
+ * @param to New user ID
1397
+ * @param from Old user ID
1398
+ * @param options API options
1399
+ */generateAliasEvent(to,from,options){const aliasEvent={previousId:from,type:RudderEventType.Alias};const enrichedEvent=getEnrichedEvent(aliasEvent,options,undefined,this.logger);// override the User ID from the API inputs
1400
+ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
1401
+ * Generate a 'group' event based on the user-input fields
1402
+ * @param options API options
1403
+ */generateGroupEvent(options){const groupEvent={type:RudderEventType.Group};return getEnrichedEvent(groupEvent,options,undefined,this.logger);}/**
1404
+ * Generates a new RudderEvent object based on the user-input fields
1405
+ * @param event API event parameters object
1406
+ * @returns A RudderEvent object
1407
+ */create(event){let eventObj;switch(event.type){case RudderEventType.Page:eventObj=this.generatePageEvent(event.category,event.name,event.properties,event.options);break;case RudderEventType.Track:eventObj=this.generateTrackEvent(event.name,event.properties,event.options);break;case RudderEventType.Identify:eventObj=this.generateIdentifyEvent(event.options);break;case RudderEventType.Alias:eventObj=this.generateAliasEvent(event.to,event.from,event.options);break;case RudderEventType.Group:eventObj=this.generateGroupEvent(event.options);break;}return eventObj;}}
1408
+
1409
+ /**
1410
+ * A service to generate valid event payloads and queue them for processing
1411
+ */class EventManager{/**
1412
+ *
1413
+ * @param eventRepository Event repository instance
1414
+ * @param userSessionManager UserSession Manager instance
1415
+ * @param errorHandler Error handler object
1416
+ * @param logger Logger object
1417
+ */constructor(eventRepository,userSessionManager,errorHandler,logger){this.eventRepository=eventRepository;this.userSessionManager=userSessionManager;this.errorHandler=errorHandler;this.logger=logger;this.eventFactory=new RudderEventFactory(this.logger);this.onError=this.onError.bind(this);}/**
1418
+ * Initializes the event manager
1419
+ */init(){this.eventRepository.init();state.lifecycle.status.value=LifecycleStatus.Initialized;}/**
1420
+ * Consumes a new incoming event
1421
+ * @param event Incoming event data
1422
+ */addEvent(event){this.userSessionManager.refreshSession();const rudderEvent=this.eventFactory.create(event);if(rudderEvent){this.eventRepository.enqueue(rudderEvent,event.callback);}else {this.onError(new Error(EVENT_OBJECT_GENERATION_ERROR));}}/**
1423
+ * Handles error
1424
+ * @param error The error object
1425
+ */onError(error,customMessage,shouldAlwaysThrow){if(this.errorHandler){this.errorHandler.onError(error,EVENT_MANAGER,customMessage,shouldAlwaysThrow);}else {throw error;}}}
1426
+
1427
+ /**
1428
+ * A function to check given value is a number or not
1429
+ * @param num input value
1430
+ * @returns boolean
1431
+ */const isNumber=num=>typeof num==='number'&&!Number.isNaN(num);/**
1432
+ * A function to check given number has minimum length or not
1433
+ * @param minimumLength minimum length
1434
+ * @param num input number
1435
+ * @returns boolean
1436
+ */const hasMinLength=(minimumLength,num)=>num.toString().length>=minimumLength;/**
1437
+ * A function to check given value is a positive integer or not
1438
+ * @param num input value
1439
+ * @returns boolean
1440
+ */const isPositiveInteger=num=>isNumber(num)&&num>=0&&Number.isInteger(num);
1441
+
1442
+ const MIN_SESSION_ID_LENGTH=10;/**
1443
+ * A function to validate current session and return true/false depending on that
1444
+ * @returns boolean
1445
+ */const hasSessionExpired=expiresAt=>{const timestamp=Date.now();return Boolean(!expiresAt||timestamp>expiresAt);};/**
1446
+ * A function to generate session id
1447
+ * @returns number
1448
+ */const generateSessionId=()=>Date.now();/**
1449
+ * Function to validate user provided sessionId
1450
+ * @param {number} sessionId
1451
+ * @returns
1452
+ */const isManualSessionIdValid=(sessionId,logger)=>{if(!sessionId||!isPositiveInteger(sessionId)||!hasMinLength(MIN_SESSION_ID_LENGTH,sessionId)){logger?.warn(INVALID_SESSION_ID_WARNING(USER_SESSION_MANAGER,sessionId,MIN_SESSION_ID_LENGTH));return false;}return true;};/**
1453
+ * A function to generate new auto tracking session
1454
+ * @param sessionTimeout current timestamp
1455
+ * @returns SessionInfo
1456
+ */const generateAutoTrackingSession=sessionTimeout=>{const timestamp=Date.now();const timeout=sessionTimeout||DEFAULT_SESSION_TIMEOUT;return {id:timestamp,// set the current timestamp
1457
+ expiresAt:timestamp+timeout,// set the expiry time of the session
1458
+ timeout,sessionStart:undefined,autoTrack:true};};/**
1459
+ * A function to generate new manual tracking session
1460
+ * @param id Provided sessionId
1461
+ * @param logger Logger module
1462
+ * @returns SessionInfo
1463
+ */const generateManualTrackingSession=(id,logger)=>{const sessionId=isManualSessionIdValid(id,logger)?id:generateSessionId();return {id:sessionId,sessionStart:undefined,manualTrack:true};};
1464
+
1465
+ const userSessionStorageKeys={userId:'rl_user_id',userTraits:'rl_trait',anonymousUserId:'rl_anonymous_id',groupId:'rl_group_id',groupTraits:'rl_group_trait',initialReferrer:'rl_page_init_referrer',initialReferringDomain:'rl_page_init_referring_domain',sessionInfo:'rl_session'};
1466
+
1467
+ class UserSessionManager{constructor(errorHandler,logger,pluginsManager,store){this.store=store;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.onError=this.onError.bind(this);}/**
1468
+ * Initialize User session with values from storage
1469
+ * @param store Selected store
1470
+ */init(store){this.store=store;this.migrateStorageIfNeeded();// get the values from storage and set it again
1471
+ this.setUserId(this.getUserId()??'');this.setUserTraits(this.getUserTraits()??{});this.setGroupId(this.getGroupId()??'');this.setGroupTraits(this.getGroupTraits()??{});this.setAnonymousId(this.getAnonymousId(state.loadOptions.value.anonymousIdOptions));const initialReferrer=this.getInitialReferrer();const initialReferringDomain=this.getInitialReferringDomain();if(initialReferrer&&initialReferringDomain){this.setInitialReferrer(initialReferrer);this.setInitialReferringDomain(initialReferringDomain);}else {if(initialReferrer){this.setInitialReferrer(initialReferrer);this.setInitialReferringDomain(getReferringDomain(initialReferrer));}const referrer=getReferrer();this.setInitialReferrer(referrer);this.setInitialReferringDomain(getReferringDomain(referrer));}// Initialize session tracking
1472
+ this.initializeSessionTracking();// Register the effect to sync with storage
1473
+ this.registerEffects();}migrateStorageIfNeeded(){if(!state.storage.migrate.value){return;}Object.values(userSessionStorageKeys).forEach(storageEntry=>{const migratedVal=this.pluginsManager?.invokeSingle('storage.migrate',storageEntry,this.store?.engine,this.logger);this.syncValueToStorage(storageEntry,migratedVal);});}/**
1474
+ * A function to initialize sessionTracking
1475
+ */initializeSessionTracking(){const sessionInfo=this.getSessionFromStorage()??defaultSessionInfo;let finalAutoTrackingStatus=!(state.loadOptions.value.sessions.autoTrack===false||sessionInfo.manualTrack===true);let sessionTimeout;const configuredSessionTimeout=state.loadOptions.value.sessions.timeout;if(!isPositiveInteger(configuredSessionTimeout)){this.logger?.warn(TIMEOUT_NOT_NUMBER_WARNING(USER_SESSION_MANAGER,configuredSessionTimeout,DEFAULT_SESSION_TIMEOUT));sessionTimeout=DEFAULT_SESSION_TIMEOUT;}else {sessionTimeout=configuredSessionTimeout;}if(sessionTimeout===0){this.logger?.warn(TIMEOUT_ZERO_WARNING(USER_SESSION_MANAGER));finalAutoTrackingStatus=false;}// In case user provides a timeout value greater than 0 but less than 10 seconds SDK will show a warning
1476
+ // and will proceed with it
1477
+ if(sessionTimeout>0&&sessionTimeout<MIN_SESSION_TIMEOUT){this.logger?.warn(TIMEOUT_NOT_RECOMMENDED_WARNING(USER_SESSION_MANAGER,sessionTimeout,MIN_SESSION_TIMEOUT));}state.session.sessionInfo.value={...sessionInfo,timeout:sessionTimeout,autoTrack:finalAutoTrackingStatus};// If auto session tracking is enabled start the session tracking
1478
+ if(state.session.sessionInfo.value.autoTrack){this.startOrRenewAutoTracking();}}/**
1479
+ * Handles error
1480
+ * @param error The error object
1481
+ */onError(error){if(this.errorHandler){this.errorHandler.onError(error,USER_SESSION_MANAGER);}else {throw error;}}/**
1482
+ * A function to sync values in storage
1483
+ * @param key
1484
+ * @param value
1485
+ */syncValueToStorage(key,value){if(value&&isString(value)||isNonEmptyObject(value)){this.store?.set(key,value);}else {this.store?.remove(key);}}/**
1486
+ * Function to update storage whenever state value changes
1487
+ */registerEffects(){/**
1488
+ * Update userId in storage automatically when userId is updated in state
1489
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.userId,state.session.userId.value);});/**
1490
+ * Update user traits in storage automatically when it is updated in state
1491
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.userTraits,state.session.userTraits.value);});/**
1492
+ * Update group id in storage automatically when it is updated in state
1493
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.groupId,state.session.groupId.value);});/**
1494
+ * Update group traits in storage automatically when it is updated in state
1495
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.groupTraits,state.session.groupTraits.value);});/**
1496
+ * Update anonymous user id in storage automatically when it is updated in state
1497
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.anonymousUserId,state.session.anonymousUserId.value);});/**
1498
+ * Update initial referrer in storage automatically when it is updated in state
1499
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.initialReferrer,state.session.initialReferrer.value);});/**
1500
+ * Update initial referring domain in storage automatically when it is updated in state
1501
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.initialReferringDomain,state.session.initialReferringDomain.value);});/**
1502
+ * Update session tracking info in storage automatically when it is updated in state
1503
+ */b(()=>{this.syncValueToStorage(userSessionStorageKeys.sessionInfo,state.session.sessionInfo.value);});}/**
1504
+ * Sets anonymous id in the following precedence:
1505
+ *
1506
+ * 1. anonymousId: Id directly provided to the function.
1507
+ * 2. rudderAmpLinkerParam: value generated from linker query parm (rudderstack)
1508
+ * using parseLinker util.
1509
+ * 3. generateUUID: A new unique id is generated and assigned.
1510
+ */setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;if(!finalAnonymousId&&rudderAmpLinkerParam){const linkerPluginsResult=this.pluginsManager?.invokeMultiple('userSession.anonymousIdGoogleLinker',rudderAmpLinkerParam);finalAnonymousId=linkerPluginsResult?.[0];}state.session.anonymousUserId.value=finalAnonymousId||this.generateAnonymousId();}/**
1511
+ * Generate a new anonymousId
1512
+ * @returns string anonymousID
1513
+ */generateAnonymousId(){return generateUUID();}/**
1514
+ * Fetches anonymousId
1515
+ * @param options option to fetch it from external source
1516
+ * @returns anonymousId
1517
+ */getAnonymousId(options){// fetch the anonymousUserId from storage
1518
+ let persistedAnonymousId=this.store?.get(userSessionStorageKeys.anonymousUserId);if(!persistedAnonymousId&&options){// fetch anonymousId from external source
1519
+ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnonymousId',getStorageEngine,options);persistedAnonymousId=autoCapturedAnonymousId;}state.session.anonymousUserId.value=persistedAnonymousId||this.generateAnonymousId();return state.session.anonymousUserId.value;}/**
1520
+ * Fetches User Id
1521
+ * @returns
1522
+ */getUserId(){return this.store?.get(userSessionStorageKeys.userId)??null;}/**
1523
+ * Fetches User Traits
1524
+ * @returns
1525
+ */getUserTraits(){return this.store?.get(userSessionStorageKeys.userTraits)??null;}/**
1526
+ * Fetches Group Id
1527
+ * @returns
1528
+ */getGroupId(){return this.store?.get(userSessionStorageKeys.groupId)??null;}/**
1529
+ * Fetches Group Traits
1530
+ * @returns
1531
+ */getGroupTraits(){return this.store?.get(userSessionStorageKeys.groupTraits)??null;}/**
1532
+ * Fetches Initial Referrer
1533
+ * @returns
1534
+ */getInitialReferrer(){return this.store?.get(userSessionStorageKeys.initialReferrer)??null;}/**
1535
+ * Fetches Initial Referring domain
1536
+ * @returns
1537
+ */getInitialReferringDomain(){return this.store?.get(userSessionStorageKeys.initialReferringDomain)??null;}/**
1538
+ * Fetches session tracking information from storage
1539
+ * @returns
1540
+ */getSessionFromStorage(){return this.store?.get(userSessionStorageKeys.sessionInfo)??null;}/**
1541
+ * A function to update current session info after each event call
1542
+ */refreshSession(){if(state.session.sessionInfo.value.autoTrack||state.session.sessionInfo.value.manualTrack){if(state.session.sessionInfo.value.autoTrack){this.startOrRenewAutoTracking();}if(state.session.sessionInfo.value.sessionStart===undefined){state.session.sessionInfo.value={...state.session.sessionInfo.value,sessionStart:true};}else if(state.session.sessionInfo.value.sessionStart){state.session.sessionInfo.value={...state.session.sessionInfo.value,sessionStart:false};}}}/**
1543
+ * Reset state values
1544
+ * @param resetAnonymousId
1545
+ * @param noNewSessionStart
1546
+ * @returns
1547
+ */reset(resetAnonymousId,noNewSessionStart){const{manualTrack,autoTrack}=state.session.sessionInfo.value;o(()=>{state.session.userId.value='';state.session.userTraits.value={};state.session.groupId.value='';state.session.groupTraits.value={};if(resetAnonymousId){state.session.anonymousUserId.value='';}if(noNewSessionStart){return;}if(autoTrack){state.session.sessionInfo.value={};this.startOrRenewAutoTracking();}else if(manualTrack){this.startManualTrackingInternal();}});}/**
1548
+ * Set user Id
1549
+ * @param userId
1550
+ */setUserId(userId){state.session.userId.value=userId;}/**
1551
+ * Set user traits
1552
+ * @param traits
1553
+ */setUserTraits(traits){if(traits){state.session.userTraits.value=mergeDeepRight(state.session.userTraits.value??{},traits);}}/**
1554
+ * Set group Id
1555
+ * @param groupId
1556
+ */setGroupId(groupId){state.session.groupId.value=groupId;}/**
1557
+ * Set group traits
1558
+ * @param traits
1559
+ */setGroupTraits(traits){if(traits){state.session.groupTraits.value=mergeDeepRight(state.session.groupTraits.value??{},traits);}}/**
1560
+ * Set initial referrer
1561
+ * @param referrer
1562
+ */setInitialReferrer(referrer){state.session.initialReferrer.value=referrer;}/**
1563
+ * Set initial referring domain
1564
+ * @param referrer
1565
+ */setInitialReferringDomain(referrer){state.session.initialReferringDomain.value=referrer;}/**
1566
+ * A function to check for existing session details and depending on that create a new session.
1567
+ */startOrRenewAutoTracking(){if(hasSessionExpired(state.session.sessionInfo.value.expiresAt)){state.session.sessionInfo.value=generateAutoTrackingSession(state.session.sessionInfo.value.timeout);}else {const timestamp=Date.now();const timeout=state.session.sessionInfo.value.timeout;state.session.sessionInfo.value=mergeDeepRight(state.session.sessionInfo.value,{expiresAt:timestamp+timeout// set the expiry time of the session
1568
+ });}}/**
1569
+ * A function method to start a manual session
1570
+ * @param {number} id session identifier
1571
+ * @returns
1572
+ */start(id){state.session.sessionInfo.value=generateManualTrackingSession(id,this.logger);}/**
1573
+ * An internal function to start manual session
1574
+ */startManualTrackingInternal(){this.start(Date.now());}/**
1575
+ * A public method to end an ongoing session.
1576
+ */end(){state.session.sessionInfo.value={};}/**
1577
+ * Clear storage
1578
+ * @param resetAnonymousId
1579
+ */clearUserSessionStorage(resetAnonymousId){this.store?.remove(userSessionStorageKeys.userId);this.store?.remove(userSessionStorageKeys.userTraits);this.store?.remove(userSessionStorageKeys.groupId);this.store?.remove(userSessionStorageKeys.groupTraits);if(resetAnonymousId){this.store?.remove(userSessionStorageKeys.anonymousUserId);}}}
1580
+
1581
+ /**
1582
+ * A buffer queue to serve as a store for any type of data
1583
+ */class BufferQueue{constructor(){this.items=[];}enqueue(item){this.items.push(item);}dequeue(){if(this.items.length===0){return null;}return this.items.shift();}isEmpty(){return this.items.length===0;}size(){return this.items.length;}clear(){this.items=[];}}
1584
+
1585
+ const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATIONS_QUEUE_EXT_POINT_PREFIX='destinationsEventsQueue';
1586
+
1587
+ /**
1588
+ * Event repository class responsible for queuing events for further processing and delivery
1589
+ */class EventRepository{/**
1590
+ *
1591
+ * @param pluginsManager Plugins manager instance
1592
+ * @param storeManager Store Manager instance
1593
+ * @param errorHandler Error handler object
1594
+ * @param logger Logger object
1595
+ */constructor(pluginsManager,storeManager,errorHandler,logger){this.pluginsManager=pluginsManager;this.errorHandler=errorHandler;this.logger=logger;this.httpClient=new HttpClient(errorHandler,logger);this.storeManager=storeManager;this.onError=this.onError.bind(this);}/**
1596
+ * Initializes the event repository
1597
+ */init(){this.dataplaneEventsQueue=this.pluginsManager.invokeSingle(`${DATA_PLANE_QUEUE_EXT_POINT_PREFIX}.init`,state,this.httpClient,this.storeManager,this.errorHandler,this.logger);this.destinationsEventsQueue=this.pluginsManager.invokeSingle(`${DESTINATIONS_QUEUE_EXT_POINT_PREFIX}.init`,state,this.pluginsManager,this.storeManager,this.errorHandler,this.logger);// Start the queue once the client destinations are ready
1598
+ b(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){this.destinationsEventsQueue.start();}});}/**
1599
+ * Enqueues the event for processing
1600
+ * @param event RudderEvent object
1601
+ * @param callback API callback function
1602
+ */enqueue(event,callback){// Start the queue processing only when the destinations are ready or hybrid mode destinations exist
1603
+ // However, events will be enqueued for now.
1604
+ // At the time of processing the events, the integrations config data from destinations
1605
+ // is merged into the event object
1606
+ b(()=>{const shouldBufferDpEvents=state.loadOptions.value.bufferDataPlaneEventsUntilReady===true&&state.nativeDestinations.clientDestinationsReady.value===false;const hybridDestExist=state.nativeDestinations.activeDestinations.value.some(dest=>isHybridModeDestination(dest));if(hybridDestExist===false||shouldBufferDpEvents===false&&this.dataplaneEventsQueue?.running!==true){this.dataplaneEventsQueue?.start();}});const dpQEvent=clone$1(event);this.pluginsManager.invokeSingle(`${DATA_PLANE_QUEUE_EXT_POINT_PREFIX}.enqueue`,state,this.dataplaneEventsQueue,dpQEvent,this.errorHandler,this.logger);const dQEvent=clone$1(event);this.pluginsManager.invokeSingle(`${DESTINATIONS_QUEUE_EXT_POINT_PREFIX}.enqueue`,state,this.destinationsEventsQueue,dQEvent,this.errorHandler,this.logger);// Invoke the callback if it exists
1607
+ try{// Using the event sent to the data plane queue here
1608
+ // to ensure the mutated (if any) event is sent to the callback
1609
+ callback?.(dpQEvent);}catch(error){this.onError(error,'API Callback Invocation Failed');}}/**
1610
+ * Handles error
1611
+ * @param error The error object
1612
+ * @param customMessage a message
1613
+ * @param shouldAlwaysThrow if it should throw or use logger
1614
+ */onError(error,customMessage,shouldAlwaysThrow){if(this.errorHandler){this.errorHandler.onError(error,EVENT_REPOSITORY,customMessage,shouldAlwaysThrow);}else {throw error;}}}
1615
+
1616
+ /*
1617
+ * Analytics class with lifecycle based on state ad user triggered events
1618
+ */class Analytics{preloadBuffer=new BufferQueue();/**
1619
+ * Initialize services and components or use default ones if singletons
1620
+ */constructor(){this.initialized=false;this.errorHandler=defaultErrorHandler;this.logger=defaultLogger;this.externalSrcLoader=new ExternalSrcLoader(this.errorHandler,this.logger);this.capabilitiesManager=new CapabilitiesManager(this.errorHandler,this.logger);this.httpClient=defaultHttpClient;this.load=this.load.bind(this);this.startLifecycle=this.startLifecycle.bind(this);this.prepareBrowserCapabilities=this.prepareBrowserCapabilities.bind(this);this.enqueuePreloadBufferEvents=this.enqueuePreloadBufferEvents.bind(this);this.processDataInPreloadBuffer=this.processDataInPreloadBuffer.bind(this);this.prepareInternalServices=this.prepareInternalServices.bind(this);this.loadConfig=this.loadConfig.bind(this);this.init=this.init.bind(this);this.loadPlugins=this.loadPlugins.bind(this);this.onLoaded=this.onLoaded.bind(this);this.processBufferedEvents=this.processBufferedEvents.bind(this);this.loadIntegrations=this.loadIntegrations.bind(this);this.onReady=this.onReady.bind(this);this.ready=this.ready.bind(this);this.page=this.page.bind(this);this.track=this.track.bind(this);this.identify=this.identify.bind(this);this.alias=this.alias.bind(this);this.group=this.group.bind(this);this.reset=this.reset.bind(this);this.getAnonymousId=this.getAnonymousId.bind(this);this.setAnonymousId=this.setAnonymousId.bind(this);this.getUserId=this.getUserId.bind(this);this.getUserTraits=this.getUserTraits.bind(this);this.getGroupId=this.getGroupId.bind(this);this.getGroupTraits=this.getGroupTraits.bind(this);this.startSession=this.startSession.bind(this);this.endSession=this.endSession.bind(this);this.getSessionId=this.getSessionId.bind(this);}/**
1621
+ * Start application lifecycle if not already started
1622
+ */load(writeKey,dataPlaneUrl,loadOptions={}){if(state.lifecycle.status.value){return;}let clonedDataPlaneUrl=clone$1(dataPlaneUrl);let clonedLoadOptions=clone$1(loadOptions);// dataPlaneUrl is not provided
1623
+ if(isObjectAndNotNull(dataPlaneUrl)){clonedLoadOptions=dataPlaneUrl;clonedDataPlaneUrl=undefined;}// Set initial state values
1624
+ o(()=>{state.lifecycle.writeKey.value=writeKey;state.lifecycle.dataPlaneUrl.value=clonedDataPlaneUrl;state.loadOptions.value=normalizeLoadOptions(state.loadOptions.value,clonedLoadOptions);state.lifecycle.status.value=LifecycleStatus.Mounted;});// Expose state to global objects
1625
+ setExposedGlobal('state',state,writeKey);// Configure initial config of any services or components here
1626
+ // State application lifecycle
1627
+ this.startLifecycle();}// Start lifecycle methods
1628
+ /**
1629
+ * Orchestrate the lifecycle of the application phases/status
1630
+ */startLifecycle(){b(()=>{switch(state.lifecycle.status.value){case LifecycleStatus.Mounted:this.prepareBrowserCapabilities();break;case LifecycleStatus.BrowserCapabilitiesReady:// initialize the preloaded events enqueuing
1631
+ retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig();break;case LifecycleStatus.Configured:this.loadPlugins();break;case LifecycleStatus.PluginsLoading:break;case LifecycleStatus.PluginsReady:this.init();break;case LifecycleStatus.Initialized:this.onLoaded();break;case LifecycleStatus.Loaded:this.loadIntegrations();this.processBufferedEvents();break;case LifecycleStatus.DestinationsLoading:break;case LifecycleStatus.DestinationsReady:this.onReady();break;case LifecycleStatus.Ready:break;}});}/**
1632
+ * Load browser polyfill if required
1633
+ */prepareBrowserCapabilities(){this.capabilitiesManager.init();}/**
1634
+ * Enqueue in SDK preload buffer events, used from preloadBuffer component
1635
+ */enqueuePreloadBufferEvents(bufferedEvents){if(Array.isArray(bufferedEvents)){bufferedEvents.forEach(bufferedEvent=>this.preloadBuffer.enqueue(clone$1(bufferedEvent)));}}/**
1636
+ * Process the buffer preloaded events by passing their arguments to the respective facade methods
1637
+ */processDataInPreloadBuffer(){while(this.preloadBuffer.size()>0){const eventToProcess=this.preloadBuffer.dequeue();if(eventToProcess){consumePreloadBufferedEvent([...eventToProcess],this);}}}prepareInternalServices(){this.pluginsManager=new PluginsManager(defaultPluginEngine,this.errorHandler,this.logger);this.storeManager=new StoreManager(this.pluginsManager,this.errorHandler,this.logger);this.configManager=new ConfigManager(this.httpClient,this.errorHandler,this.logger);this.userSessionManager=new UserSessionManager(this.errorHandler,this.logger,this.pluginsManager);this.eventRepository=new EventRepository(this.pluginsManager,this.storeManager,this.errorHandler,this.logger);this.eventManager=new EventManager(this.eventRepository,this.userSessionManager,this.errorHandler,this.logger);}/**
1638
+ * Load configuration
1639
+ */loadConfig(){if(!state.lifecycle.writeKey.value){this.errorHandler.onError(new Error('A write key is required to load the SDK. Please provide a valid write key.'),LOAD_CONFIGURATION);return;}this.httpClient.setAuthHeader(state.lifecycle.writeKey.value);this.configManager?.init();}/**
1640
+ * Initialize the storage and event queue
1641
+ */init(){this.errorHandler.init(this.externalSrcLoader);// Initialize storage
1642
+ this.storeManager?.init();this.clientDataStore=this.storeManager?.getStore(CLIENT_DATA_STORE_NAME);this.userSessionManager?.init(this.clientDataStore);// Initialize consent manager
1643
+ if(state.consents.activeConsentManagerPluginName.value){this.pluginsManager?.invokeSingle(`consentManager.init`,state,this.storeManager,this.logger);}// Initialize event manager
1644
+ this.eventManager?.init();}/**
1645
+ * Load plugins
1646
+ */loadPlugins(){this.pluginsManager?.init();// TODO: are we going to enable custom plugins to be passed as load options?
1647
+ // registerCustomPlugins(state.loadOptions.value.customPlugins);
1648
+ }/**
1649
+ * Trigger onLoaded callback if any is provided in config
1650
+ */onLoaded(){// Process any preloaded events
1651
+ this.processDataInPreloadBuffer();// Set lifecycle state
1652
+ o(()=>{state.lifecycle.loaded.value=true;state.lifecycle.status.value=LifecycleStatus.Loaded;});// Execute onLoaded callback if provided in load options
1653
+ if(state.loadOptions.value.onLoaded&&isFunction(state.loadOptions.value.onLoaded)){state.loadOptions.value.onLoaded(this);}}/**
1654
+ * Consume preloaded events buffer
1655
+ */processBufferedEvents(){// Process buffered events
1656
+ state.eventBuffer.toBeProcessedArray.value.forEach(bufferedItem=>{const methodName=bufferedItem[0];if(isFunction(this[methodName])){this[methodName](...bufferedItem.slice(1));}});state.eventBuffer.toBeProcessedArray.value=[];}/**
1657
+ * Load device mode integrations
1658
+ */loadIntegrations(){// Set in state the desired activeIntegrations to inject in DOM
1659
+ this.pluginsManager?.invokeSingle('nativeDestinations.setActiveDestinations',state,this.pluginsManager,this.logger);const totalDestinationsToLoad=state.nativeDestinations.activeDestinations.value.length;if(totalDestinationsToLoad===0){state.lifecycle.status.value=LifecycleStatus.DestinationsReady;return;}// Start loading native integration scripts and create instances
1660
+ state.lifecycle.status.value=LifecycleStatus.DestinationsLoading;this.pluginsManager?.invokeSingle('nativeDestinations.load',state,this.externalSrcLoader,this.logger);// Progress to next lifecycle phase if all native integrations are initialized or failed
1661
+ b(()=>{const areAllDestinationsReady=totalDestinationsToLoad===0||state.nativeDestinations.initializedDestinations.value.length+state.nativeDestinations.failedDestinations.value.length===totalDestinationsToLoad;if(areAllDestinationsReady){o(()=>{state.lifecycle.status.value=LifecycleStatus.DestinationsReady;state.nativeDestinations.clientDestinationsReady.value=true;});}});}/**
1662
+ * Invoke the ready callbacks if any exist
1663
+ */ // eslint-disable-next-line class-methods-use-this
1664
+ onReady(){state.eventBuffer.readyCallbacksArray.value.forEach(callback=>callback());state.lifecycle.status.value=LifecycleStatus.Ready;}// End lifecycle methods
1665
+ // Start consumer exposed methods
1666
+ ready(callback){const type='ready';this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);if(!isFunction(callback)){this.logger.error(READY_API_CALLBACK_ERROR(READY_API));return;}if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,callback]);return;}/**
1667
+ * If integrations are loaded or no integration is available for loading
1668
+ * execute the callback immediately else push the callbacks to a queue that
1669
+ * will be executed after loading completes
1670
+ */if(state.lifecycle.status.value===LifecycleStatus.Ready){callback();}else {state.eventBuffer.readyCallbacksArray.value.push(callback);}}page(payload){const type='page';this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,payload]);return;}this.eventManager?.addEvent({type:RudderEventType.Page,category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
1671
+ // Send automatic ad blocked page event if adblockers are detected on the page
1672
+ if(state.capabilities.isAdBlocked.value===true&&payload.category!==ADBLOCK_PAGE_CATEGORY){const pageCallArgs={category:ADBLOCK_PAGE_CATEGORY,name:ADBLOCK_PAGE_NAME,properties:{// 'title' is intentionally omitted as it does not make sense
1673
+ // in v3 implementation
1674
+ path:ADBLOCK_PAGE_PATH},options:state.loadOptions.value.sendAdblockPageOptions};this.page(pageCallArgs);}}track(payload){const type='track';this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,payload]);return;}this.eventManager?.addEvent({type:RudderEventType.Track,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});}identify(payload){const type='identify';this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,payload]);return;}const shouldResetSession=Boolean(payload.userId&&state.session.userId.value&&payload.userId!==state.session.userId.value);if(shouldResetSession){this.reset();}this.userSessionManager?.setUserId(payload.userId);this.userSessionManager?.setUserTraits(payload.traits);this.eventManager?.addEvent({type:RudderEventType.Identify,userId:payload.userId,traits:payload.traits,options:payload.options,callback:payload.callback});}alias(payload){const type='alias';this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,payload]);return;}const previousId=payload.from??this.userSessionManager?.getUserId()??this.userSessionManager?.getAnonymousId();this.eventManager?.addEvent({type:RudderEventType.Alias,to:payload.to,from:previousId,options:payload.options,callback:payload.callback});}group(payload){const type='group';this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,payload]);return;}this.userSessionManager?.setGroupId(payload.groupId);this.userSessionManager?.setGroupTraits(payload.traits);this.eventManager?.addEvent({type:RudderEventType.Group,groupId:payload.groupId,traits:payload.traits,options:payload.options,callback:payload.callback});}reset(resetAnonymousId){const type='reset';this.errorHandler.leaveBreadcrumb(`New ${type} invocation, resetAnonymousId: ${resetAnonymousId}`);if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,resetAnonymousId]);return;}this.userSessionManager?.reset(resetAnonymousId);}getAnonymousId(options){return this.userSessionManager?.getAnonymousId(options);}setAnonymousId(anonymousId,rudderAmpLinkerParam){this.userSessionManager?.setAnonymousId(anonymousId,rudderAmpLinkerParam);}// eslint-disable-next-line class-methods-use-this
1675
+ getUserId(){return state.session.userId.value;}// eslint-disable-next-line class-methods-use-this
1676
+ getUserTraits(){return state.session.userTraits.value;}// eslint-disable-next-line class-methods-use-this
1677
+ getGroupId(){return state.session.groupId.value;}// eslint-disable-next-line class-methods-use-this
1678
+ getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId){this.userSessionManager?.start(sessionId);}endSession(){this.userSessionManager?.end();}// eslint-disable-next-line class-methods-use-this
1679
+ getSessionId(){this.userSessionManager?.refreshSession();return state.session.sessionInfo.value?.id??null;}// End consumer exposed methods
1680
+ }
1681
+
1682
+ /*
1683
+ * RudderAnalytics facade singleton that is exposed as global object and will:
1684
+ * expose overloaded methods
1685
+ * handle multiple Analytics instances
1686
+ * consume SDK preload event buffer
1687
+ */class RudderAnalytics{static globalSingleton=null;analyticsInstances={};defaultAnalyticsKey='';// Singleton with constructor bind methods
1688
+ constructor(){if(RudderAnalytics.globalSingleton){// eslint-disable-next-line no-constructor-return
1689
+ return RudderAnalytics.globalSingleton;}this.setDefaultInstanceKey=this.setDefaultInstanceKey.bind(this);this.getAnalyticsInstance=this.getAnalyticsInstance.bind(this);this.load=this.load.bind(this);this.ready=this.ready.bind(this);this.getPreloadBuffer=this.getPreloadBuffer.bind(this);this.triggerBufferedLoadEvent=this.triggerBufferedLoadEvent.bind(this);this.page=this.page.bind(this);this.track=this.track.bind(this);this.identify=this.identify.bind(this);this.alias=this.alias.bind(this);this.group=this.group.bind(this);this.reset=this.reset.bind(this);this.getAnonymousId=this.getAnonymousId.bind(this);this.setAnonymousId=this.setAnonymousId.bind(this);this.getUserId=this.getUserId.bind(this);this.getUserTraits=this.getUserTraits.bind(this);this.getGroupId=this.getGroupId.bind(this);this.getGroupTraits=this.getGroupTraits.bind(this);this.startSession=this.startSession.bind(this);this.endSession=this.endSession.bind(this);this.getSessionId=this.getSessionId.bind(this);RudderAnalytics.globalSingleton=this;// get the preloaded events before replacing global object
1690
+ this.getPreloadBuffer();// start loading if a load event was buffered or wait for explicit load call
1691
+ this.triggerBufferedLoadEvent();// eslint-disable-next-line no-constructor-return
1692
+ return this;}/**
1693
+ * Set instance to use if no specific writeKey is provided in methods
1694
+ * automatically for the first created instance
1695
+ * TODO: to support multiple analytics instances in the near future
1696
+ */setDefaultInstanceKey(writeKey){if(isEmpty$1(this.analyticsInstances)){this.defaultAnalyticsKey=writeKey;}}/**
1697
+ * Retrieve an existing analytics instance
1698
+ */getAnalyticsInstance(writeKey){const instanceId=writeKey||this.defaultAnalyticsKey;const analyticsInstanceExists=Boolean(this.analyticsInstances[instanceId]);if(!analyticsInstanceExists){this.analyticsInstances[instanceId]=new Analytics();}return this.analyticsInstances[instanceId];}/**
1699
+ * Create new analytics instance and trigger application lifecycle start
1700
+ */load(writeKey,dataPlaneUrl,loadOptions){const shouldSkipLoad=!isString(writeKey)||Boolean(this.analyticsInstances[writeKey]);if(shouldSkipLoad){return;}this.setDefaultInstanceKey(writeKey);this.analyticsInstances[writeKey]=new Analytics();this.getAnalyticsInstance(writeKey).load(writeKey,dataPlaneUrl,loadOptions);}/**
1701
+ * Get preloaded events in buffer queue if exists
1702
+ */ // eslint-disable-next-line class-methods-use-this
1703
+ getPreloadBuffer(){const preloadedEventsArray=Array.isArray(globalThis.rudderanalytics)?globalThis.rudderanalytics:[];// Expose buffer to global objects
1704
+ setExposedGlobal(GLOBAL_PRELOAD_BUFFER,clone$1(preloadedEventsArray));}/**
1705
+ * Trigger load event in buffer queue if exists
1706
+ */triggerBufferedLoadEvent(){const preloadedEventsArray=Array.isArray(globalThis.rudderanalytics)?globalThis.rudderanalytics:[];// Get any load method call that is buffered if any
1707
+ const loadEvent=getPreloadedLoadEvent(preloadedEventsArray);// Process load method if present in the buffered requests
1708
+ if(loadEvent.length>0){// Remove the event name from the Buffered Event array and keep only arguments
1709
+ loadEvent.shift();// eslint-disable-next-line @typescript-eslint/ban-ts-comment
1710
+ // @ts-ignore
1711
+ this.load.apply(null,loadEvent);}}/**
1712
+ * Get ready callback arguments and forward to ready call
1713
+ */ready(callback){this.getAnalyticsInstance().ready(callback);}/**
1714
+ * Process page arguments and forward to page call
1715
+ */page(category,name,properties,options,callback){this.getAnalyticsInstance().page(pageArgumentsToCallOptions(category,name,properties,options,callback));}/**
1716
+ * Process track arguments and forward to page call
1717
+ */track(event,properties,options,callback){this.getAnalyticsInstance().track(trackArgumentsToCallOptions(event,properties,options,callback));}/**
1718
+ * Process identify arguments and forward to page call
1719
+ */identify(userId,traits,options,callback){this.getAnalyticsInstance().identify(identifyArgumentsToCallOptions(userId,traits,options,callback));}/**
1720
+ * Process alias arguments and forward to page call
1721
+ */alias(to,from,options,callback){this.getAnalyticsInstance().alias(aliasArgumentsToCallOptions(to,from,options,callback));}/**
1722
+ * Process group arguments and forward to page call
1723
+ */group(groupId,traits,options,callback){this.getAnalyticsInstance().group(groupArgumentsToCallOptions(groupId,traits,options,callback));}reset(resetAnonymousId){this.getAnalyticsInstance().reset(resetAnonymousId);}getAnonymousId(options){return this.getAnalyticsInstance().getAnonymousId(options);}setAnonymousId(anonymousId,rudderAmpLinkerParam){this.getAnalyticsInstance().setAnonymousId(anonymousId,rudderAmpLinkerParam);}getUserId(){return this.getAnalyticsInstance().getUserId();}getUserTraits(){return this.getAnalyticsInstance().getUserTraits();}getGroupId(){return this.getAnalyticsInstance().getGroupId();}getGroupTraits(){return this.getAnalyticsInstance().getGroupTraits();}startSession(sessionId){return this.getAnalyticsInstance().startSession(sessionId);}endSession(){return this.getAnalyticsInstance().endSession();}getSessionId(){return this.getAnalyticsInstance().getSessionId();}}
1724
+
1725
+ exports.CookieSameSite = CookieSameSite;
1726
+ exports.LogLevel = LogLevel;
1727
+ exports.PluginName = PluginName;
1728
+ exports.ResidencyServerRegion = ResidencyServerRegion;
1729
+ exports.RudderAnalytics = RudderAnalytics;
1730
+ exports.UaChTrackLevel = UaChTrackLevel;
1731
+
1732
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1733
+
1734
+ }));