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