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