@rudderstack/analytics-js 3.0.0-beta.12 → 3.0.0-beta.14
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.
- package/CHANGELOG.md +36 -0
- package/README.md +57 -10
- package/dist/npm/index.d.ts +224 -90
- package/dist/npm/legacy/cjs/index.js +217 -147
- package/dist/npm/legacy/esm/index.js +217 -147
- package/dist/npm/legacy/umd/index.js +217 -147
- package/dist/npm/modern/bundled/cjs/index.js +207 -137
- package/dist/npm/modern/bundled/esm/index.js +207 -137
- package/dist/npm/modern/bundled/umd/index.js +207 -137
- package/dist/npm/modern/cjs/index.js +144 -98
- package/dist/npm/modern/esm/index.js +144 -98
- package/dist/npm/modern/umd/index.js +144 -98
- package/package.json +2 -2
@@ -52,8 +52,9 @@ function _has(prop,obj){return Object.prototype.hasOwnProperty.call(obj,prop);}
|
|
52
52
|
* R.type([]); //=> "Array"
|
53
53
|
* R.type(/[A-z]/); //=> "RegExp"
|
54
54
|
* R.type(() => {}); //=> "Function"
|
55
|
+
* R.type(async () => {}); //=> "AsyncFunction"
|
55
56
|
* R.type(undefined); //=> "Undefined"
|
56
|
-
*/var type=/*#__PURE__*/_curry1(function type(val){return val===null?'Null':val===undefined?'Undefined':Object.prototype.toString.call(val).slice(8,-1);});
|
57
|
+
*/var type=/*#__PURE__*/_curry1(function type(val){return val===null?'Null':val===undefined?'Undefined':Object.prototype.toString.call(val).slice(8,-1);});const type$1 = type;
|
57
58
|
|
58
59
|
function _isObject(x){return Object.prototype.toString.call(x)==='[object Object]';}
|
59
60
|
|
@@ -93,7 +94,7 @@ function _isString(x){return Object.prototype.toString.call(x)==='[object String
|
|
93
94
|
* @symb R.nth(-1, [a, b, c]) = c
|
94
95
|
* @symb R.nth(0, [a, b, c]) = a
|
95
96
|
* @symb R.nth(1, [a, b, c]) = b
|
96
|
-
*/var nth=/*#__PURE__*/_curry2(function nth(offset,list){var idx=offset<0?list.length+offset:offset;return _isString(list)?list.charAt(idx):list[idx];});
|
97
|
+
*/var nth=/*#__PURE__*/_curry2(function nth(offset,list){var idx=offset<0?list.length+offset:offset;return _isString(list)?list.charAt(idx):list[idx];});const nth$1 = nth;
|
97
98
|
|
98
99
|
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':''));}
|
99
100
|
|
@@ -106,7 +107,7 @@ function _cloneRegExp(pattern){return new RegExp(pattern.source,pattern.flags?pa
|
|
106
107
|
* @return {*} The copied value.
|
107
108
|
*/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.
|
108
109
|
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.
|
109
|
-
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){/**
|
110
|
+
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$1(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){/**
|
110
111
|
* 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,
|
111
112
|
* on my tests this number is 180, anything above that using the hash function is faster.
|
112
113
|
*/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;}();
|
@@ -156,7 +157,7 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
156
157
|
*
|
157
158
|
* R.paths([['a', 'b'], ['p', 0, 'q']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, 3]
|
158
159
|
* R.paths([['a', 'b'], ['p', 'r']], {a: {b: 2}, p: [{q: 3}]}); //=> [2, undefined]
|
159
|
-
*/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;});});
|
160
|
+
*/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$1(p,val):val[p];idx+=1;}return val;});});const paths$1 = paths;
|
160
161
|
|
161
162
|
/**
|
162
163
|
* Retrieves the value at a given path. The nodes of the path can be arbitrary strings or non-negative integers.
|
@@ -181,7 +182,7 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
181
182
|
* R.path(['a', 'b', -2], {a: {b: [1, 2, 3]}}); //=> 2
|
182
183
|
* R.path([2], {'2': 2}); //=> 2
|
183
184
|
* R.path([-2], {'-2': 'a'}); //=> undefined
|
184
|
-
*/var path=/*#__PURE__*/_curry2(function path(pathAr,obj){return paths([pathAr],obj)[0];});const path$1 = path;
|
185
|
+
*/var path=/*#__PURE__*/_curry2(function path(pathAr,obj){return paths$1([pathAr],obj)[0];});const path$1 = path;
|
185
186
|
|
186
187
|
/**
|
187
188
|
* Creates a new object with the own properties of the two provided objects. If
|
@@ -207,7 +208,7 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
207
208
|
* { b: true, thing: 'bar', values: [15, 35] });
|
208
209
|
* //=> { a: true, b: true, thing: 'bar', values: [10, 20, 15, 35] }
|
209
210
|
* @symb R.mergeWithKey(f, { x: 1, y: 2 }, { y: 5, z: 3 }) = { x: 1, y: f('y', 2, 5), z: 3 }
|
210
|
-
*/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;});
|
211
|
+
*/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;});const mergeWithKey$1 = mergeWithKey;
|
211
212
|
|
212
213
|
/**
|
213
214
|
* Creates a new object with the own properties of the two provided objects.
|
@@ -236,7 +237,7 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
236
237
|
* { a: true, c: { thing: 'foo', values: [10, 20] }},
|
237
238
|
* { b: true, c: { thing: 'bar', values: [15, 35] }});
|
238
239
|
* //=> { a: true, b: true, c: { thing: 'bar', values: [10, 20, 15, 35] }}
|
239
|
-
*/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);});
|
240
|
+
*/var mergeDeepWithKey=/*#__PURE__*/_curry3(function mergeDeepWithKey(fn,lObj,rObj){return mergeWithKey$1(function(k,lVal,rVal){if(_isObject(lVal)&&_isObject(rVal)){return mergeDeepWithKey(fn,lVal,rVal);}else {return fn(k,lVal,rVal);}},lObj,rObj);});const mergeDeepWithKey$1 = mergeDeepWithKey;
|
240
241
|
|
241
242
|
/**
|
242
243
|
* Creates a new object with the own properties of the two provided objects.
|
@@ -264,7 +265,7 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
264
265
|
* { a: true, c: { values: [10, 20] }},
|
265
266
|
* { b: true, c: { values: [15, 35] }});
|
266
267
|
* //=> { a: true, b: true, c: { values: [10, 20, 15, 35] }}
|
267
|
-
*/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;
|
268
|
+
*/var mergeDeepWith=/*#__PURE__*/_curry3(function mergeDeepWith(fn,lObj,rObj){return mergeDeepWithKey$1(function(k,lVal,rVal){return fn(lVal,rVal);},lObj,rObj);});const mergeDeepWith$1 = mergeDeepWith;
|
268
269
|
|
269
270
|
/**
|
270
271
|
* Returns a partial copy of an object containing only the keys that satisfy
|
@@ -291,7 +292,8 @@ var cachedCopy=map.get(value);if(cachedCopy){return cachedCopy;}map.set(value,co
|
|
291
292
|
* A function to check given value is a function
|
292
293
|
* @param value input value
|
293
294
|
* @returns boolean
|
294
|
-
*/
|
295
|
+
*/ // eslint-disable-next-line @typescript-eslint/ban-types
|
296
|
+
const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&value.call&&value.apply);/**
|
295
297
|
* A function to check given value is a string
|
296
298
|
* @param value input value
|
297
299
|
* @returns boolean
|
@@ -409,9 +411,9 @@ payload.groupId=null;payload.traits=groupId;payload.options=!isFunction(traits)?
|
|
409
411
|
// Also, to clone the incoming object type arguments
|
410
412
|
if(isDefined(payload.groupId)){payload.groupId=tryStringify(payload.groupId);}else {delete payload.groupId;}payload.traits=isObjectLiteralAndNotNull(payload.traits)?clone$1(payload.traits):{};if(isDefined(payload.options)){payload.options=clone$1(payload.options);}else {delete payload.options;}return payload;};
|
411
413
|
|
412
|
-
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
|
414
|
+
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 EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';const RS_APP='RudderStackApplication';const ANALYTICS_CORE='AnalyticsCore';
|
413
415
|
|
414
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.
|
416
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.14';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';
|
415
417
|
|
416
418
|
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';
|
417
419
|
|
@@ -495,9 +497,9 @@ const EXTERNAL_SOURCE_LOAD_ORIGIN='RS_JS_SDK';
|
|
495
497
|
*
|
496
498
|
* @returns
|
497
499
|
*/const insertScript=newScriptElement=>{// First try to add it to the head
|
498
|
-
const headElements=document.getElementsByTagName('head');if(headElements.length>0){headElements[0]
|
499
|
-
const scriptElements=document.getElementsByTagName('script');if(scriptElements.length>0&&scriptElements[0]
|
500
|
-
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement
|
500
|
+
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
|
501
|
+
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
|
502
|
+
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement?.insertBefore(headElement,htmlElement.firstChild);};/**
|
501
503
|
* Loads external js file as a script html tag
|
502
504
|
*
|
503
505
|
* @param {*} url The URL of the script to be loaded
|
@@ -515,7 +517,7 @@ timeoutID=globalThis.setTimeout(()=>{reject(new Error(SCRIPT_LOAD_TIMEOUT_ERROR(
|
|
515
517
|
* Service to load external resources/files
|
516
518
|
*/class ExternalSrcLoader{hasErrorHandler=false;constructor(errorHandler,logger,timeout=DEFAULT_EXT_SRC_LOAD_TIMEOUT_MS){this.errorHandler=errorHandler;this.logger=logger;this.timeout=timeout;this.hasErrorHandler=Boolean(this.errorHandler);this.onError=this.onError.bind(this);}/**
|
517
519
|
* Load external resource of type javascript
|
518
|
-
*/loadJSFile(config){const{url,id,timeout,async,callback,extraAttributes}=config;const isFireAndForget=!
|
520
|
+
*/loadJSFile(config){const{url,id,timeout,async,callback,extraAttributes}=config;const isFireAndForget=!isFunction(callback);jsFileLoader(url,id,timeout||this.timeout,async,extraAttributes).then(id=>{if(!isFireAndForget){callback(id);}}).catch(err=>{this.onError(err);if(!isFireAndForget){callback();}});}/**
|
519
521
|
* Handle errors
|
520
522
|
*/onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,EXTERNAL_SRC_LOADER);}else {throw error;}}}
|
521
523
|
|
@@ -551,13 +553,13 @@ const BUILD_TYPE='modern';const SDK_CDN_BASE_URL='https://cdn.rudderlabs.com';co
|
|
551
553
|
// const PLUGINS_BASE_URL = `${SDK_CDN_BASE_URL}/latest/${CDN_ARCH_VERSION_DIR}/${BUILD_TYPE}/${CDN_PLUGINS_DIR}`;
|
552
554
|
const DEFAULT_CONFIG_BE_URL='https://api.rudderstack.com';
|
553
555
|
|
554
|
-
const DEFAULT_ERROR_REPORTING_PROVIDER='bugsnag';const DEFAULT_STORAGE_ENCRYPTION_VERSION='v3';const ConsentManagersToPluginNameMap={oneTrust:'OneTrustConsentManager',ketch:'KetchConsentManager'};const ErrorReportingProvidersToPluginNameMap={[DEFAULT_ERROR_REPORTING_PROVIDER]:'Bugsnag'};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:'StorageEncryption',legacy:'StorageEncryptionLegacy'};
|
556
|
+
const DEFAULT_ERROR_REPORTING_PROVIDER='bugsnag';const DEFAULT_STORAGE_ENCRYPTION_VERSION='v3';const ConsentManagersToPluginNameMap={oneTrust:'OneTrustConsentManager',ketch:'KetchConsentManager',custom:'CustomConsentManager'};const ErrorReportingProvidersToPluginNameMap={[DEFAULT_ERROR_REPORTING_PROVIDER]:'Bugsnag'};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:'StorageEncryption',legacy:'StorageEncryptionLegacy'};
|
555
557
|
|
556
558
|
const defaultLoadOptions={logLevel:'ERROR',configUrl:DEFAULT_CONFIG_BE_URL,loadIntegration:true,sessions:{autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS},sameSiteCookie:'Lax',polyfillIfRequired:true,integrations:{All:true},useBeacon:false,beaconQueueOptions:{},destinationsQueueOptions:{},queueOptions:{},lockIntegrationsVersion:false,uaChTrackLevel:'none',plugins:[],useGlobalIntegrationsConfigInEvents:false,bufferDataPlaneEventsUntilReady:false,dataPlaneEventsBufferTimeout:DEFAULT_DATA_PLANE_EVENTS_BUFFER_TIMEOUT_MS,storage:{encryption:{version:DEFAULT_STORAGE_ENCRYPTION_VERSION},migrate:false},sendAdblockPageOptions:{}};const loadOptionsState=a(clone$1(defaultLoadOptions));
|
557
559
|
|
558
|
-
const userSessionStorageKeys={userId:'rl_user_id',userTraits:'rl_trait',anonymousId:'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'};const defaultUserSessionValues={userId:'',userTraits:{},anonymousId:'',groupId:'',groupTraits:{},initialReferrer:'',initialReferringDomain:'',sessionInfo:{}};
|
560
|
+
const userSessionStorageKeys={userId:'rl_user_id',userTraits:'rl_trait',anonymousId:'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',authToken:'rl_auth_token'};const defaultUserSessionValues={userId:'',userTraits:{},anonymousId:'',groupId:'',groupTraits:{},initialReferrer:'',initialReferringDomain:'',sessionInfo:{},authToken:null};
|
559
561
|
|
560
|
-
const defaultSessionInfo={autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS};const sessionState={userId:a(defaultUserSessionValues.userId),userTraits:a(defaultUserSessionValues.userTraits),anonymousId:a(defaultUserSessionValues.anonymousId),groupId:a(defaultUserSessionValues.groupId),groupTraits:a(defaultUserSessionValues.groupTraits),initialReferrer:a(defaultUserSessionValues.initialReferrer),initialReferringDomain:a(defaultUserSessionValues.initialReferringDomain),sessionInfo:a(defaultUserSessionValues.sessionInfo)};
|
562
|
+
const defaultSessionInfo={autoTrack:true,timeout:DEFAULT_SESSION_TIMEOUT_MS};const sessionState={userId:a(defaultUserSessionValues.userId),userTraits:a(defaultUserSessionValues.userTraits),anonymousId:a(defaultUserSessionValues.anonymousId),groupId:a(defaultUserSessionValues.groupId),groupTraits:a(defaultUserSessionValues.groupTraits),initialReferrer:a(defaultUserSessionValues.initialReferrer),initialReferringDomain:a(defaultUserSessionValues.initialReferringDomain),sessionInfo:a(defaultUserSessionValues.sessionInfo),authToken:a(defaultUserSessionValues.authToken)};
|
561
563
|
|
562
564
|
const capabilitiesState={isOnline:a(true),storage:{isLocalStorageAvailable:a(false),isCookieStorageAvailable:a(false),isSessionStorageAvailable:a(false)},isBeaconAvailable:a(false),isLegacyDOM:a(false),isUaCHAvailable:a(false),isCryptoAvailable:a(false),isIE11:a(false),isAdBlocked:a(false)};
|
563
565
|
|
@@ -567,11 +569,11 @@ const sourceConfigState=a(undefined);
|
|
567
569
|
|
568
570
|
const lifecycleState={activeDataplaneUrl:a(undefined),integrationsCDNPath:a(DEST_SDK_BASE_URL),pluginsCDNPath:a(PLUGINS_BASE_URL),sourceConfigUrl:a(undefined),status:a(undefined),initialized:a(false),logLevel:a('ERROR'),loaded:a(false),readyCallbacks:a([]),writeKey:a(undefined),dataPlaneUrl:a(undefined)};
|
569
571
|
|
570
|
-
const consentsState={
|
572
|
+
const consentsState={enabled:a(false),initialized:a(false),data:a({}),activeConsentManagerPluginName:a(undefined),preConsent:a({enabled:false}),postConsent:a({})};
|
571
573
|
|
572
574
|
const metricsState={retries:a(0),dropped:a(0),sent:a(0),queued:a(0),triggered:a(0)};
|
573
575
|
|
574
|
-
const contextState={app:a({name:APP_NAME,namespace:APP_NAMESPACE,version:APP_VERSION}),traits:a(null),library:a({name:APP_NAME,version:APP_VERSION}),userAgent:a(''),device:a(null),network:a(null),os:a({name:'',version:''}),locale:a(null),screen:a({density:0,width:0,height:0,innerWidth:0,innerHeight:0}),'ua-ch':a(undefined)};
|
576
|
+
const contextState={app:a({name:APP_NAME,namespace:APP_NAMESPACE,version:APP_VERSION}),traits:a(null),library:a({name:APP_NAME,version:APP_VERSION}),userAgent:a(''),device:a(null),network:a(null),os:a({name:'',version:''}),locale:a(null),screen:a({density:0,width:0,height:0,innerWidth:0,innerHeight:0}),'ua-ch':a(undefined),timezone:a(undefined)};
|
575
577
|
|
576
578
|
const nativeDestinationsState={configuredDestinations:a([]),activeDestinations:a([]),loadOnlyIntegrations:a({}),failedDestinations:a([]),loadIntegration:a(true),initializedDestinations:a([]),clientDestinationsReady:a(false),integrationsConfig:a({})};
|
577
579
|
|
@@ -586,7 +588,7 @@ const defaultStateValues={capabilities:capabilitiesState,consents:consentsState,
|
|
586
588
|
// to next or return the value if it is the last one instead of an array per
|
587
589
|
// plugin that is the normal invoke
|
588
590
|
// TODO: add invoke method for extension point that we know only one plugin can be used. add invokeMultiple and invokeSingle methods
|
589
|
-
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(
|
591
|
+
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(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.
|
590
592
|
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
|
591
593
|
// do some unified pre-process before application starts.
|
592
594
|
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
|
@@ -636,7 +638,7 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
|
|
636
638
|
|
637
639
|
/**
|
638
640
|
* List of plugin names that are loaded as dynamic imports in modern builds
|
639
|
-
*/const pluginNamesList=['BeaconQueue','Bugsnag','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
|
641
|
+
*/const pluginNamesList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
|
640
642
|
|
641
643
|
const COOKIE_STORAGE='cookieStorage';const LOCAL_STORAGE='localStorage';const SESSION_STORAGE='sessionStorage';const MEMORY_STORAGE='memoryStorage';const NO_STORAGE='none';
|
642
644
|
|
@@ -667,7 +669,7 @@ const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${
|
|
667
669
|
* @param event RudderEvent object
|
668
670
|
* @param logger Logger instance
|
669
671
|
* @returns stringified event payload. Empty string if error occurs.
|
670
|
-
*/const getDeliveryPayload=(event,logger)=>stringifyWithoutCircular(event,true,undefined,logger);/**
|
672
|
+
*/const getDeliveryPayload=(event,logger)=>stringifyWithoutCircular(event,true,undefined,logger);const getDMTDeliveryPayload=(dmtRequestPayload,logger)=>stringifyWithoutCircular(dmtRequestPayload,true,undefined,logger);/**
|
671
673
|
* Utility to validate final payload size before sending to server
|
672
674
|
* @param event RudderEvent object
|
673
675
|
* @param logger Logger instance
|
@@ -688,7 +690,7 @@ const BEACON_PLUGIN_EVENTS_QUEUE_DEBUG=context=>`${context}${LOG_CONTEXT_SEPARAT
|
|
688
690
|
const DEFAULT_BEACON_QUEUE_MAX_SIZE=10;const DEFAULT_BEACON_QUEUE_FLUSH_INTERVAL_MS=10*60*1000;// 10 minutes
|
689
691
|
// Limit of the Beacon transfer mechanism on the browsers
|
690
692
|
const MAX_BATCH_PAYLOAD_SIZE_BYTES=64*1024;// 64 KB
|
691
|
-
const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flushQueueInterval:DEFAULT_BEACON_QUEUE_FLUSH_INTERVAL_MS};const DATA_PLANE_API_VERSION$1='v1';const QUEUE_NAME$
|
693
|
+
const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flushQueueInterval:DEFAULT_BEACON_QUEUE_FLUSH_INTERVAL_MS};const DATA_PLANE_API_VERSION$1='v1';const QUEUE_NAME$3='rudder_beacon';const BEACON_QUEUE_PLUGIN='BeaconQueuePlugin';
|
692
694
|
|
693
695
|
/**
|
694
696
|
* Utility to get the stringified event payload as Blob
|
@@ -715,11 +717,11 @@ const sortByTime=(a,b)=>a.time-b.time;const RETRY_QUEUE='RetryQueue';/**
|
|
715
717
|
* @param {QueueProcessCallback} fn The function to call in order to process an item added to the queue
|
716
718
|
*/class RetryQueue{constructor(name,options,queueProcessCb,storeManager,storageType=LOCAL_STORAGE,logger,queueBatchItemsSizeCalculatorCb){this.storeManager=storeManager;this.logger=logger;this.name=name;this.id=generateUUID();this.processQueueCb=queueProcessCb;this.batchSizeCalcCb=queueBatchItemsSizeCalculatorCb;this.maxItems=options.maxItems||DEFAULT_MAX_ITEMS;this.maxAttempts=options.maxAttempts||DEFAULT_MAX_RETRY_ATTEMPTS;this.batch={enabled:false};this.configureBatchMode(options);this.backoff={minRetryDelay:options.minRetryDelay||DEFAULT_MIN_RETRY_DELAY_MS,maxRetryDelay:options.maxRetryDelay||DEFAULT_MAX_RETRY_DELAY_MS,factor:options.backoffFactor||DEFAULT_BACKOFF_FACTOR,jitter:options.backoffJitter||DEFAULT_BACKOFF_JITTER};// painstakingly tuned. that's why they're not "easily" configurable
|
717
719
|
this.timeouts={ackTimer:DEFAULT_ACK_TIMER_MS,reclaimTimer:DEFAULT_RECLAIM_TIMER_MS,reclaimTimeout:DEFAULT_RECLAIM_TIMEOUT_MS,reclaimWait:DEFAULT_RECLAIM_WAIT_MS};this.schedule=new Schedule();this.processId='0';// Set up our empty queues
|
718
|
-
this.store=this.storeManager.setStore({id:this.id,name:this.name,validKeys:QueueStatuses,type:storageType});this.
|
720
|
+
this.store=this.storeManager.setStore({id:this.id,name:this.name,validKeys:QueueStatuses,type:storageType});this.setDefaultQueueEntries();// bind recurring tasks for ease of use
|
719
721
|
this.ack=this.ack.bind(this);this.checkReclaim=this.checkReclaim.bind(this);this.processHead=this.processHead.bind(this);this.flushBatch=this.flushBatch.bind(this);// Attach visibility change listener to flush the queue
|
720
|
-
this.attachListeners();this.scheduleTimeoutActive=false;}configureBatchMode(options){this.batchingInProgress=false;if(!isObjectLiteralAndNotNull(options.batch)){return;}const batchOptions=options.batch;this.batch.enabled=batchOptions.enabled===true;if(this.batch.enabled){// Set upper cap on the batch payload size
|
721
|
-
this.batch.maxSize=Math.min(batchOptions.maxSize??DEFAULT_MAX_BATCH_SIZE_BYTES,DEFAULT_MAX_BATCH_SIZE_BYTES);this.batch.maxItems=batchOptions.maxItems??DEFAULT_MAX_BATCH_ITEMS;this.batch.flushInterval=batchOptions.flushInterval??DEFAULT_BATCH_FLUSH_INTERVAL_MS;}}attachListeners(){if(this.batch.enabled){globalThis.addEventListener('visibilitychange',()=>{if(document.visibilityState==='hidden'){this.flushBatch();}});}}
|
722
|
-
|
722
|
+
this.attachListeners();this.scheduleTimeoutActive=false;}setDefaultQueueEntries(){this.setStorageEntry(QueueStatuses.IN_PROGRESS,{});this.setStorageEntry(QueueStatuses.QUEUE,[]);this.setStorageEntry(QueueStatuses.BATCH_QUEUE,[]);}configureBatchMode(options){this.batchingInProgress=false;if(!isObjectLiteralAndNotNull(options.batch)){return;}const batchOptions=options.batch;this.batch.enabled=batchOptions.enabled===true;if(this.batch.enabled){// Set upper cap on the batch payload size
|
723
|
+
this.batch.maxSize=Math.min(batchOptions.maxSize??DEFAULT_MAX_BATCH_SIZE_BYTES,DEFAULT_MAX_BATCH_SIZE_BYTES);this.batch.maxItems=batchOptions.maxItems??DEFAULT_MAX_BATCH_ITEMS;this.batch.flushInterval=batchOptions.flushInterval??DEFAULT_BATCH_FLUSH_INTERVAL_MS;}}attachListeners(){if(this.batch.enabled){globalThis.addEventListener('visibilitychange',()=>{if(document.visibilityState==='hidden'){this.flushBatch();}});}}getStorageEntry(name){return this.store.get(name??this.name);}// TODO: fix the type of different queues to be the same if possible
|
724
|
+
setStorageEntry(name,value){this.store.set(name??this.name,value??[]);}/**
|
723
725
|
* Stops processing the queue
|
724
726
|
*/stop(){this.schedule.cancelAll();this.scheduleTimeoutActive=false;}/**
|
725
727
|
* Starts processing the queue
|
@@ -727,7 +729,7 @@ setQueue(name,value){this.store.set(name??this.name,value??[]);}/**
|
|
727
729
|
* Configures the timeout handler for flushing the batch queue
|
728
730
|
*/scheduleFlushBatch(){if(this.batch.enabled&&this.batch?.flushInterval){if(this.flushBatchTaskId){this.schedule.cancel(this.flushBatchTaskId);}this.flushBatchTaskId=this.schedule.run(this.flushBatch,this.batch.flushInterval,ScheduleModes.ASAP);}}/**
|
729
731
|
* Flushes the batch queue
|
730
|
-
*/flushBatch(){if(!this.batchingInProgress){this.batchingInProgress=true;let batchQueue=this.
|
732
|
+
*/flushBatch(){if(!this.batchingInProgress){this.batchingInProgress=true;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)??[];if(batchQueue.length>0){batchQueue=batchQueue.slice(-batchQueue.length);const batchEntry=this.genQueueItem(batchQueue.map(queueItem=>queueItem.item));this.setStorageEntry(QueueStatuses.BATCH_QUEUE,[]);this.pushToMainQueue(batchEntry);}this.batchingInProgress=false;// Re-schedule the flush task
|
731
733
|
this.scheduleFlushBatch();}}/**
|
732
734
|
* Decides whether to retry. Overridable.
|
733
735
|
*
|
@@ -744,10 +746,10 @@ if(curEntry){this.pushToMainQueue(curEntry);}}/**
|
|
744
746
|
* Handles a new item added to the retry queue when batching is enabled
|
745
747
|
* @param entry New item added to the retry queue
|
746
748
|
* @returns Undefined or batch entry object
|
747
|
-
*/handleNewItemForBatch(entry){let curEntry;let batchQueue=this.
|
749
|
+
*/handleNewItemForBatch(entry){let curEntry;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)??[];if(!this.batchingInProgress){this.batchingInProgress=true;batchQueue=batchQueue.slice(-batchQueue.length);batchQueue.push(entry);const batchDispatchInfo=this.getBatchDispInfo(batchQueue);// if batch criteria is met, queue the batch events to the main queue and clear batch queue
|
748
750
|
if(batchDispatchInfo.criteriaMet||batchDispatchInfo.criteriaExceeded){let batchItems;if(batchDispatchInfo.criteriaExceeded){batchItems=batchQueue.slice(0,batchQueue.length-1).map(queueItem=>queueItem.item);batchQueue=[entry];}else {batchItems=batchQueue.map(queueItem=>queueItem.item);batchQueue=[];}curEntry=this.genQueueItem(batchItems);// re-attach the timeout handler
|
749
751
|
this.scheduleFlushBatch();}this.batchingInProgress=false;}else {batchQueue.push(entry);}// update the batch queue
|
750
|
-
this.
|
752
|
+
this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}pushToMainQueue(curEntry){let queue=this.getStorageEntry(QueueStatuses.QUEUE)??[];queue=queue.slice(-(this.maxItems-1));queue.push(curEntry);queue=queue.sort(sortByTime);this.setStorageEntry(QueueStatuses.QUEUE,queue);if(this.scheduleTimeoutActive){this.processHead();}}/**
|
751
753
|
* Adds an item to the queue
|
752
754
|
*
|
753
755
|
* @param {Object} itemData The item to process
|
@@ -768,28 +770,28 @@ this.setQueue(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}pushToMainQ
|
|
768
770
|
* @returns Batch dispatch info
|
769
771
|
*/getBatchDispInfo(batchItems){let lengthCriteriaMet=false;let lengthCriteriaExceeded=false;const configuredBatchMaxItems=this.batch?.maxItems;if(isDefined(configuredBatchMaxItems)){lengthCriteriaMet=batchItems.length===configuredBatchMaxItems;lengthCriteriaExceeded=batchItems.length>configuredBatchMaxItems;}if(lengthCriteriaMet||lengthCriteriaExceeded){return {criteriaMet:lengthCriteriaMet,criteriaExceeded:lengthCriteriaExceeded};}let sizeCriteriaMet=false;let sizeCriteriaExceeded=false;const configuredBatchMaxSize=this.batch?.maxSize;if(isDefined(configuredBatchMaxSize)&&isDefined(this.batchSizeCalcCb)){const curBatchSize=this.batchSizeCalcCb(batchItems.map(queueItem=>queueItem.item));sizeCriteriaMet=curBatchSize===configuredBatchMaxSize;sizeCriteriaExceeded=curBatchSize>configuredBatchMaxSize;}return {criteriaMet:sizeCriteriaMet,criteriaExceeded:sizeCriteriaExceeded};}processHead(){// cancel the scheduled task if it exists
|
770
772
|
this.schedule.cancel(this.processId);// Pop the head off the queue
|
771
|
-
let queue=this.
|
772
|
-
const processItemCallback=(el,id)=>(err,res)=>{const inProgress=this.
|
773
|
+
let queue=this.getStorageEntry(QueueStatuses.QUEUE)??[];const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)??{};const now=this.schedule.now();const toRun=[];// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
774
|
+
const processItemCallback=(el,id)=>(err,res)=>{const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)??{};delete inProgress[id];this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);if(err){this.requeue(el.item,el.attemptNumber+1,err,el.id);}};const enqueueItem=(el,id)=>{toRun.push({item:el.item,done:processItemCallback(el,id),attemptNumber:el.attemptNumber});};let inProgressSize=Object.keys(inProgress).length;// eslint-disable-next-line no-plusplus
|
773
775
|
while(queue.length>0&&queue[0].time<=now&&inProgressSize++<this.maxItems){const el=queue.shift();if(el){const id=generateUUID();// Save this to the in progress map
|
774
|
-
inProgress[id]={item:el.item,attemptNumber:el.attemptNumber,time:this.schedule.now()};enqueueItem(el,id);}}this.
|
776
|
+
inProgress[id]={item:el.item,attemptNumber:el.attemptNumber,time:this.schedule.now()};enqueueItem(el,id);}}this.setStorageEntry(QueueStatuses.QUEUE,queue);this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);toRun.forEach(el=>{// TODO: handle processQueueCb timeout
|
775
777
|
try{const willBeRetried=this.shouldRetry(el.item,el.attemptNumber+1);this.processQueueCb(el.item,el.done,el.attemptNumber,this.maxAttempts,willBeRetried);}catch(err){this.logger?.error(RETRY_QUEUE_PROCESS_ERROR(RETRY_QUEUE),err);}});// re-read the queue in case the process function finished immediately or added another item
|
776
|
-
queue=this.
|
777
|
-
ack(){this.
|
778
|
+
queue=this.getStorageEntry(QueueStatuses.QUEUE)??[];this.schedule.cancel(this.processId);if(queue.length>0){const nextProcessExecutionTime=queue[0].time-now;this.processId=this.schedule.run(this.processHead,nextProcessExecutionTime,ScheduleModes.ASAP);}}// Ack continuously to prevent other tabs from claiming our queue
|
779
|
+
ack(){this.setStorageEntry(QueueStatuses.ACK,this.schedule.now());this.setStorageEntry(QueueStatuses.RECLAIM_START,null);this.setStorageEntry(QueueStatuses.RECLAIM_END,null);this.schedule.run(this.ack,this.timeouts.ackTimer,ScheduleModes.ASAP);}reclaim(id){const other=this.storeManager.setStore({id,name:this.name,validKeys:QueueStatuses,type:LOCAL_STORAGE});const our={queue:this.getStorageEntry(QueueStatuses.QUEUE)??[]};const their={inProgress:other.get(QueueStatuses.IN_PROGRESS)??{},batchQueue:other.get(QueueStatuses.BATCH_QUEUE)??[],queue:other.get(QueueStatuses.QUEUE)??[]};const trackMessageIds=[];const addConcatQueue=(queue,incrementAttemptNumberBy)=>{const concatIterator=el=>{const id=el.id??generateUUID();if(trackMessageIds.includes(id));else {our.queue.push({item:el.item,attemptNumber:el.attemptNumber+incrementAttemptNumberBy,time:this.schedule.now(),id});trackMessageIds.push(id);}};if(Array.isArray(queue)){queue.forEach(concatIterator);}else if(queue){Object.values(queue).forEach(concatIterator);}};// add their queue to ours, resetting run-time to immediate and copying the attempt#
|
778
780
|
addConcatQueue(their.queue,0);// Process batch queue items
|
779
781
|
if(this.batch.enabled){their.batchQueue.forEach(el=>{const id=el.id??generateUUID();if(trackMessageIds.includes(id));else {this.enqueue(el);trackMessageIds.push(id);}});}else {// if batching is not enabled in the current instance, add those items to the main queue directly
|
780
782
|
addConcatQueue(their.batchQueue,0);}// if the queue is abandoned, all the in-progress are failed. retry them immediately and increment the attempt#
|
781
|
-
addConcatQueue(their.inProgress,1);our.queue=our.queue.sort(sortByTime);this.
|
782
|
-
this.
|
783
|
+
addConcatQueue(their.inProgress,1);our.queue=our.queue.sort(sortByTime);this.setStorageEntry(QueueStatuses.QUEUE,our.queue);// remove all keys one by on next tick to avoid NS_ERROR_STORAGE_BUSY error
|
784
|
+
this.clearQueueEntries(other,1);// process the new items we claimed
|
783
785
|
this.processHead();}// eslint-disable-next-line class-methods-use-this
|
784
|
-
|
786
|
+
clearQueueEntries(other,localStorageBackoff){this.removeStorageEntry(other,0,localStorageBackoff);}removeStorageEntry(store,entryIdx,backoff,attempt=1){const maxAttempts=2;globalThis.setTimeout(()=>{const queueEntryKeys=Object.keys(QueueStatuses);const entry=QueueStatuses[queueEntryKeys[entryIdx]];try{store.remove(entry);// clear the next entry
|
785
787
|
if(entryIdx+1<queueEntryKeys.length){this.removeStorageEntry(store,entryIdx+1,backoff);}}catch(err){const storageBusyErr='NS_ERROR_STORAGE_BUSY';const isLocalStorageBusy=err.name===storageBusyErr||err.code===storageBusyErr||err.code===0x80630001;if(isLocalStorageBusy&&attempt<maxAttempts){// Try clearing the same entry again with some extra delay
|
786
788
|
this.removeStorageEntry(store,entryIdx,backoff+40,attempt+1);}else {this.logger?.error(RETRY_QUEUE_ENTRY_REMOVE_ERROR(RETRY_QUEUE,entry,attempt),err);}// clear the next entry
|
787
789
|
if(attempt===maxAttempts&&entryIdx+1<queueEntryKeys.length){this.removeStorageEntry(store,entryIdx+1,backoff);}}},backoff);}checkReclaim(){const createReclaimStartTask=store=>()=>{if(store.get(QueueStatuses.RECLAIM_END)!==this.id){return;}if(store.get(QueueStatuses.RECLAIM_START)!==this.id){return;}this.reclaim(store.id);};const createReclaimEndTask=store=>()=>{if(store.get(QueueStatuses.RECLAIM_START)!==this.id){return;}store.set(QueueStatuses.RECLAIM_END,this.id);this.schedule.run(createReclaimStartTask(store),this.timeouts.reclaimWait,ScheduleModes.ABANDON);};const tryReclaim=store=>{store.set(QueueStatuses.RECLAIM_START,this.id);store.set(QueueStatuses.ACK,this.schedule.now());this.schedule.run(createReclaimEndTask(store),this.timeouts.reclaimWait,ScheduleModes.ABANDON);};const findOtherQueues=name=>{const res=[];const storage=this.store.getOriginalEngine();for(let i=0;i<storage.length;i++){const k=storage.key(i);const parts=k?k.split('.'):[];if(parts.length!==3){// eslint-disable-next-line no-continue
|
788
790
|
continue;}if(parts[0]!==name){// eslint-disable-next-line no-continue
|
789
791
|
continue;}if(parts[2]!==QueueStatuses.ACK){// eslint-disable-next-line no-continue
|
790
|
-
continue;}res.push(this.storeManager.setStore({id:parts[1],name,validKeys:QueueStatuses,type:LOCAL_STORAGE}));}return res;};findOtherQueues(this.name).forEach(store=>{if(store.id===this.id){return;}if(this.schedule.now()-store.get(QueueStatuses.ACK)<this.timeouts.reclaimTimeout){return;}tryReclaim(store);});this.schedule.run(this.checkReclaim,this.timeouts.reclaimTimer,ScheduleModes.RESCHEDULE);}}
|
792
|
+
continue;}res.push(this.storeManager.setStore({id:parts[1],name,validKeys:QueueStatuses,type:LOCAL_STORAGE}));}return res;};findOtherQueues(this.name).forEach(store=>{if(store.id===this.id){return;}if(this.schedule.now()-store.get(QueueStatuses.ACK)<this.timeouts.reclaimTimeout){return;}tryReclaim(store);});this.schedule.run(this.checkReclaim,this.timeouts.reclaimTimer,ScheduleModes.RESCHEDULE);}clear(){this.schedule.cancelAll();this.setDefaultQueueEntries();}}
|
791
793
|
|
792
|
-
const pluginName$
|
794
|
+
const pluginName$e='BeaconQueue';const BeaconQueue=()=>({name:pluginName$e,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$e];},dataplaneEventsQueue:{/**
|
793
795
|
* Initialize the queue for delivery
|
794
796
|
* @param state Application state
|
795
797
|
* @param httpClient http client instance
|
@@ -799,7 +801,7 @@ const pluginName$d='BeaconQueue';const BeaconQueue=()=>({name:pluginName$d,deps:
|
|
799
801
|
* @returns BeaconItemsQueue instance
|
800
802
|
*/init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));const data=getBatchDeliveryPayload$1(finalEvents,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
|
801
803
|
done(null);}}else {// Mark the item as done so that it can be removed from the queue
|
802
|
-
done(null);}};const eventsQueue=new RetryQueue(`${QUEUE_NAME$
|
804
|
+
done(null);}};const eventsQueue=new RetryQueue(`${QUEUE_NAME$3}_${writeKey}`,{batch:{enabled:true,flushInterval:finalQOpts.flushQueueInterval,maxSize:MAX_BATCH_PAYLOAD_SIZE_BYTES,// set the hard limit
|
803
805
|
maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
|
804
806
|
return getBatchDeliveryPayload$1(events,logger).size;});return eventsQueue;},/**
|
805
807
|
* Add event to the queue for delivery
|
@@ -840,16 +842,24 @@ event.context='Script load failures';}// eslint-disable-next-line no-param-reass
|
|
840
842
|
event.severity='error';};const onError=state=>{const metadataSource=state.source.value?.id;return event=>{try{// Discard the event if it's not originated at the SDK
|
841
843
|
if(!isRudderSDKError(event)){return false;}enhanceErrorEventMutator(event,metadataSource);return true;}catch{// Drop the error event if it couldn't be filtered as
|
842
844
|
// it is most likely a non-SDK error
|
843
|
-
return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.
|
845
|
+
return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.14',// Set SDK version as the app version from build config
|
844
846
|
metaData:{SDK:{name:'JS',installType:'npm'}},beforeSend:onError(state),autoCaptureSessions:false,// auto capture sessions is disabled
|
845
847
|
collectUserIp:false,// collecting user's IP is disabled
|
846
848
|
// enabledBreadcrumbTypes: ['error', 'log', 'user'], // for v7 and above
|
847
849
|
maxEvents:100,maxBreadcrumbs:40,releaseStage:getReleaseStage(),user:{id:state.lifecycle.writeKey.value},logger,networkBreadcrumbsEnabled:false};const client=globalBugsnagLibInstance(clientConfig);return client;};const isApiKeyValid=apiKey=>{const isAPIKeyValid=!(apiKey.startsWith('{{')||apiKey.endsWith('}}')||apiKey.length===0);return isAPIKeyValid;};const loadBugsnagSDK=(externalSrcLoader,logger)=>{const isNotLoaded=GLOBAL_LIBRARY_OBJECT_NAMES.every(globalKeyName=>!globalThis[globalKeyName]);if(!isNotLoaded){return;}externalSrcLoader.loadJSFile({url:BUGSNAG_CDN_URL,id:ERROR_REPORT_PROVIDER_NAME_BUGSNAG,callback:id=>{if(!id){logger?.error(BUGSNAG_SDK_LOAD_ERROR(BUGSNAG_PLUGIN));}}});};const initBugsnagClient=(state,promiseResolve,promiseReject,logger,time=0)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();if(typeof globalBugsnagLibInstance==='function'){if(isValidVersion(globalBugsnagLibInstance)){const client=getNewClient(state,logger);promiseResolve(client);}}else if(time>=MAX_WAIT_FOR_SDK_LOAD_MS){promiseReject(new Error(BUGSNAG_SDK_LOAD_TIMEOUT_ERROR(MAX_WAIT_FOR_SDK_LOAD_MS)));}else {// Try to initialize the client after a delay
|
848
850
|
globalThis.setTimeout(initBugsnagClient,SDK_LOAD_POLL_INTERVAL_MS,state,promiseResolve,promiseReject,logger,time+SDK_LOAD_POLL_INTERVAL_MS);}};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):undefined;};
|
849
851
|
|
850
|
-
const pluginName$
|
852
|
+
const pluginName$d='Bugsnag';const Bugsnag=()=>({name:pluginName$d,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$d];},errorReportingProvider:{init:(state,externalSrcLoader,logger)=>new Promise((resolve,reject)=>{// If API key token is not parsed or invalid, don't proceed to initialize the client
|
851
853
|
if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
|
852
854
|
|
855
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable no-param-reassign */const pluginName$c='CustomConsentManager';const CustomConsentManager=()=>({name:pluginName$c,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$c];},consentManager:{init(state,logger){// Nothing to initialize
|
856
|
+
},updateConsentsInfo(state,storeManager,logger){// Nothing to update. Already provided by the user
|
857
|
+
},isDestinationConsented(state,destConfig,errorHandler,logger){// if (!state.consents.initialized.value) {
|
858
|
+
// return true;
|
859
|
+
// }
|
860
|
+
// TODO: Implement this
|
861
|
+
return true;}}});
|
862
|
+
|
853
863
|
const DIR_NAME$19='AdobeAnalytics';const DISPLAY_NAME$19='Adobe Analytics';
|
854
864
|
|
855
865
|
const DIR_NAME$18='Amplitude';const DISPLAY_NAME$18='Amplitude';
|
@@ -1038,11 +1048,23 @@ state.nativeDestinations.loadOnlyIntegrations.value=clone$1(state.loadOptions.va
|
|
1038
1048
|
const configSupportedDestinations=state.nativeDestinations.configuredDestinations.value.filter(configDest=>{if(destDisplayNamesToFileNamesMap[configDest.displayName]){return true;}errorHandler?.onError(new Error(DESTINATION_NOT_SUPPORTED_ERROR(configDest.userFriendlyId)),DEVICE_MODE_DESTINATIONS_PLUGIN);return false;});// Filter destinations that are disabled through load options
|
1039
1049
|
const destinationsToLoad=filterDestinations(state.nativeDestinations.loadOnlyIntegrations.value,configSupportedDestinations);const consentedDestinations=destinationsToLoad.filter(dest=>// if consent manager is not configured, then default to load the destination
|
1040
1050
|
pluginsManager.invokeSingle(`consentManager.isDestinationConsented`,state,dest.config,errorHandler,logger)??true);state.nativeDestinations.activeDestinations.value=consentedDestinations;},load(state,externalSrcLoader,errorHandler,logger,externalScriptOnLoad){const integrationsCDNPath=state.lifecycle.integrationsCDNPath.value;const activeDestinations=state.nativeDestinations.activeDestinations.value;activeDestinations.forEach(dest=>{const sdkName=destDisplayNamesToFileNamesMap[dest.displayName];const destSDKIdentifier=`${sdkName}_RS`;// this is the name of the object loaded on the window
|
1041
|
-
const sdkTypeName=sdkName;if(
|
1051
|
+
const sdkTypeName=sdkName;if(sdkTypeName&&!isDestinationSDKMounted(destSDKIdentifier,sdkTypeName)){const destSdkURL=`${integrationsCDNPath}/${sdkName}.min.js`;externalSrcLoader.loadJSFile({url:destSdkURL,id:dest.userFriendlyId,callback:externalScriptOnLoad??(id=>{if(!id){logger?.error(DESTINATION_SDK_LOAD_ERROR(DEVICE_MODE_DESTINATIONS_PLUGIN,dest.userFriendlyId));state.nativeDestinations.failedDestinations.value=[...state.nativeDestinations.failedDestinations.value,dest];}else {initializeDestination(dest,state,destSDKIdentifier,sdkTypeName,errorHandler,logger);}}),timeout:SCRIPT_LOAD_TIMEOUT_MS});}else if(sdkTypeName){initializeDestination(dest,state,destSDKIdentifier,sdkTypeName,errorHandler,logger);}else {logger?.error(DESTINATION_SDK_LOAD_ERROR(DEVICE_MODE_DESTINATIONS_PLUGIN,dest.displayName));}});}}});
|
1052
|
+
|
1053
|
+
const DEFAULT_TRANSFORMATION_QUEUE_OPTIONS={minRetryDelay:500,backoffFactor:2,maxAttempts:3};const REQUEST_TIMEOUT_MS$1=10*1000;// 10 seconds
|
1054
|
+
const QUEUE_NAME$2='rudder';const DMT_PLUGIN='DeviceModeTransformationPlugin';
|
1055
|
+
|
1056
|
+
const DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR=(context,displayName,reason,action)=>`${context}${LOG_CONTEXT_SEPARATOR}Event transformation unsuccessful for destination "${displayName}". Reason: ${reason}. ${action}.`;const DMT_REQUEST_FAILED_ERROR=(context,displayName,status,action)=>`${context}${LOG_CONTEXT_SEPARATOR}[Destination: ${displayName}].Transformation request failed with status: ${status}. Retries exhausted. ${action}.`;const DMT_EXCEPTION=displayName=>`[Destination:${displayName}].`;const DMT_SERVER_ACCESS_DENIED_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}Transformation server access is denied. The configuration data seems to be out of sync. Sending untransformed event to the destination.`;
|
1057
|
+
|
1058
|
+
/**
|
1059
|
+
* A helper function that will take rudderEvent and generate
|
1060
|
+
* a batch payload that will be sent to transformation server
|
1061
|
+
*
|
1062
|
+
*/const createPayload=(event,destinationIds,token)=>{const orderNo=Date.now();const payload={metadata:{'Custom-Authorization':token},batch:[{orderNo,destinationIds,event}]};return payload;};const sendTransformedEventToDestinations=(state,pluginsManager,destinationIds,result,status,event,errorHandler,logger)=>{const NATIVE_DEST_EXT_POINT='destinationsEventsQueue.enqueueEventToDestination';const ACTION_TO_SEND_UNTRANSFORMED_EVENT='Sending untransformed event';const ACTION_TO_DROP_EVENT='Dropping the event';const destinations=state.nativeDestinations.initializedDestinations.value.filter(d=>d&&destinationIds.includes(d.id));destinations.forEach(dest=>{try{const eventsToSend=[];switch(status){case 200:{const response=JSON.parse(result);const destTransformedResult=response.transformedBatch.find(e=>e.id===dest.id);destTransformedResult?.payload.forEach(tEvent=>{if(tEvent.status==='200'){eventsToSend.push(tEvent.event);}else {let reason='Unknown';if(tEvent.status==='410'){reason='Transformation is not available';}let action=ACTION_TO_DROP_EVENT;if(dest.propagateEventsUntransformedOnError===true){action=ACTION_TO_SEND_UNTRANSFORMED_EVENT;eventsToSend.push(event);logger?.warn(DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR(DMT_PLUGIN,dest.displayName,reason,action));}else {logger?.error(DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR(DMT_PLUGIN,dest.displayName,reason,action));}}});break;}// Transformation server access denied
|
1063
|
+
case 404:{logger?.warn(DMT_SERVER_ACCESS_DENIED_WARNING(DMT_PLUGIN));eventsToSend.push(event);break;}default:{if(dest.propagateEventsUntransformedOnError===true){logger?.warn(DMT_REQUEST_FAILED_ERROR(DMT_PLUGIN,dest.displayName,status,ACTION_TO_SEND_UNTRANSFORMED_EVENT));eventsToSend.push(event);}else {logger?.error(DMT_REQUEST_FAILED_ERROR(DMT_PLUGIN,dest.displayName,status,ACTION_TO_DROP_EVENT));}break;}}eventsToSend?.forEach(tEvent=>{if(isNonEmptyObject(tEvent)){pluginsManager.invokeSingle(NATIVE_DEST_EXT_POINT,state,tEvent,dest,errorHandler,logger);}});}catch(e){errorHandler?.onError(e,DMT_PLUGIN,DMT_EXCEPTION(dest.displayName));}});};
|
1042
1064
|
|
1043
|
-
|
1044
|
-
|
1045
|
-
pluginsManager.
|
1065
|
+
const pluginName$a='DeviceModeTransformation';const DeviceModeTransformation=()=>({name:pluginName$a,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$a];},transformEvent:{init(state,pluginsManager,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;httpClient.setAuthHeader(writeKey);const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
1066
|
+
`${QUEUE_NAME$2}_${writeKey}`,DEFAULT_TRANSFORMATION_QUEUE_OPTIONS,(item,done,attemptNumber,maxRetryAttempts)=>{const payload=createPayload(item.event,item.destinationIds,item.token);httpClient.getAsyncData({url:`${state.lifecycle.dataPlaneUrl.value}/transform`,options:{method:'POST',data:getDMTDeliveryPayload(payload),sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS$1,callback:(result,details)=>{// null means item will not be requeued
|
1067
|
+
const queueErrResp=isErrRetryable(details)?details:null;if(!queueErrResp||attemptNumber===maxRetryAttempts){sendTransformedEventToDestinations(state,pluginsManager,item.destinationIds,result,details?.xhr?.status,item.event,errorHandler,logger);}done(queueErrResp,result);}});},storeManager,MEMORY_STORAGE);return eventsQueue;},enqueue(state,eventsQueue,event,destinations){const destinationIds=destinations.map(d=>d.id);eventsQueue.addItem({event,destinationIds,token:state.session.authToken.value});}}});
|
1046
1068
|
|
1047
1069
|
const INVALID_SOURCE_CONFIG_ERROR=`Invalid source configuration or source id.`;
|
1048
1070
|
|
@@ -1071,7 +1093,9 @@ const AMP_LINKER_ANONYMOUS_ID_KEY='rs_amp_id';
|
|
1071
1093
|
*
|
1072
1094
|
* @param {string} str
|
1073
1095
|
* @returns {number} crc32
|
1074
|
-
*/const crc32=str=>{const crcTable=makeCRCTable();let crc=0^-1;for(let i=0;i<str.length;i++){
|
1096
|
+
*/const crc32=str=>{const crcTable=makeCRCTable();let crc=0^-1;for(let i=0;i<str.length;i++){// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
1097
|
+
// @ts-ignore
|
1098
|
+
crc=crc>>>8^crcTable[(crc^str.charCodeAt(i))&0xff];}return (crc^-1)>>>0;};
|
1075
1099
|
|
1076
1100
|
/**
|
1077
1101
|
* An interface to fetch user device details.
|
@@ -1111,7 +1135,7 @@ return null;}const version=Number(parts.shift());if(version!==VALID_VERSION){ret
|
|
1111
1135
|
* @param {string} serializedIds
|
1112
1136
|
*
|
1113
1137
|
* @return {!Object<string, string>}
|
1114
|
-
*/const deserialize=serializedIds=>{const keyValuePairs={};const params=serializedIds.split(DELIMITER);for(let i=0;i<params.length;i+=2){const key=params[i];const valid=KEY_VALIDATOR.test(key);if(valid){keyValuePairs[key]=decode$1(params[i+1]);}}return keyValuePairs;};/**
|
1138
|
+
*/const deserialize=serializedIds=>{if(!serializedIds){return {};}const keyValuePairs={};const params=serializedIds.split(DELIMITER);for(let i=0;i<params.length;i+=2){const key=params[i];const valid=KEY_VALIDATOR.test(key);if(valid){keyValuePairs[key]=decode$1(params[i+1]);}}return keyValuePairs;};/**
|
1115
1139
|
* Generates a semi-unique value for page visitor.
|
1116
1140
|
*
|
1117
1141
|
* @return {string}
|
@@ -1143,7 +1167,7 @@ return crc.toString(36);};/**
|
|
1143
1167
|
* @param {string} value
|
1144
1168
|
*
|
1145
1169
|
* @return {?Object<string, string>}
|
1146
|
-
*/const parseLinker=value=>{const linkerObj=parseLinkerParamValue(value);if(!linkerObj){return null;}const{checksum,serializedIds}=linkerObj;if(!isCheckSumValid(serializedIds,checksum)){return null;}return deserialize(serializedIds);};
|
1170
|
+
*/const parseLinker=value=>{const linkerObj=parseLinkerParamValue(value);if(!linkerObj){return null;}const{checksum,serializedIds}=linkerObj;if(!serializedIds||!checksum||!isCheckSumValid(serializedIds,checksum)){return null;}return deserialize(serializedIds);};
|
1147
1171
|
|
1148
1172
|
const pluginName$7='GoogleLinker';const GoogleLinker=()=>({name:pluginName$7,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$7];},userSession:{anonymousIdGoogleLinker(rudderAmpLinkerParam){if(!rudderAmpLinkerParam){return null;}const parsedAnonymousIdObj=rudderAmpLinkerParam?parseLinker(rudderAmpLinkerParam):null;return parsedAnonymousIdObj?parsedAnonymousIdObj[AMP_LINKER_ANONYMOUS_ID_KEY]:null;}}});
|
1149
1173
|
|
@@ -1163,18 +1187,18 @@ const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{cons
|
|
1163
1187
|
* Gets the consent data in the format expected by the application state
|
1164
1188
|
* @param ketchConsentData Consent data derived from the consent cookie
|
1165
1189
|
* @returns Consent data
|
1166
|
-
*/const getConsentData=ketchConsentData=>{const
|
1190
|
+
*/const getConsentData=ketchConsentData=>{const allowedConsentIds=[];const deniedConsentIds=[];if(ketchConsentData){Object.entries(ketchConsentData).forEach(e=>{const purposeCode=e[0];const isConsented=e[1];if(isConsented){allowedConsentIds.push(purposeCode);}else {deniedConsentIds.push(purposeCode);}});}return {allowedConsentIds,deniedConsentIds};};const updateConsentStateFromData=(state,ketchConsentData)=>{const consentData=getConsentData(ketchConsentData);state.consents.initialized.value=isDefined(ketchConsentData);state.consents.data.value=consentData;};
|
1167
1191
|
|
1168
|
-
const pluginName$6='KetchConsentManager';const KetchConsentManager=()=>({name:pluginName$6,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$6];},consentManager:{init(state,
|
1192
|
+
const pluginName$6='KetchConsentManager';const KetchConsentManager=()=>({name:pluginName$6,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$6];},consentManager:{init(state,logger){// getKetchUserConsentedPurposes returns current ketch opted-in purposes
|
1169
1193
|
// This will be helpful for debugging
|
1170
|
-
globalThis.getKetchUserConsentedPurposes=()=>state.consents.data.value.
|
1194
|
+
globalThis.getKetchUserConsentedPurposes=()=>state.consents.data.value.allowedConsentIds?.slice();// getKetchUserDeniedPurposes returns current ketch opted-out purposes
|
1171
1195
|
// This will be helpful for debugging
|
1172
1196
|
globalThis.getKetchUserDeniedPurposes=()=>state.consents.data.value.deniedConsentIds?.slice();// updateKetchConsent callback function to update current consent purpose state
|
1173
1197
|
// this will be called from ketch rudderstack plugin
|
1174
|
-
globalThis.updateKetchConsent=ketchConsentData=>{updateConsentStateFromData(state,ketchConsentData);}
|
1175
|
-
let ketchConsentData;if(!isUndefined(globalThis.ketchConsent)){ketchConsentData=globalThis.ketchConsent;}else {ketchConsentData=getKetchConsentData(storeManager,logger);}updateConsentStateFromData(state,ketchConsentData);},isDestinationConsented(state,destConfig,errorHandler,logger){
|
1198
|
+
globalThis.updateKetchConsent=ketchConsentData=>{updateConsentStateFromData(state,ketchConsentData);};},updateConsentsInfo(state,storeManager,logger){// retrieve consent data and update the state
|
1199
|
+
let ketchConsentData;if(!isUndefined(globalThis.ketchConsent)){ketchConsentData=globalThis.ketchConsent;}else {ketchConsentData=getKetchConsentData(storeManager,logger);}updateConsentStateFromData(state,ketchConsentData);},isDestinationConsented(state,destConfig,errorHandler,logger){if(!state.consents.initialized.value){return true;}const allowedConsentIds=state.consents.data.value.allowedConsentIds;try{const{ketchConsentPurposes}=destConfig;// If the destination do not have this mapping events will be sent.
|
1176
1200
|
if(!ketchConsentPurposes||ketchConsentPurposes.length===0){return true;}const purposes=ketchConsentPurposes.map(p=>p.purpose).filter(n=>n);// Check if any of the destination's mapped ketch purposes are consented by the user in the browser.
|
1177
|
-
const containsAnyOfConsent=purposes.some(element=>
|
1201
|
+
const containsAnyOfConsent=purposes.some(element=>allowedConsentIds.includes(element.trim()));return containsAnyOfConsent;}catch(err){errorHandler?.onError(err,KETCH_CONSENT_MANAGER_PLUGIN,DESTINATION_CONSENT_STATUS_ERROR$1);return true;}}}});
|
1178
1202
|
|
1179
1203
|
const DEFAULT_QUEUE_OPTIONS={maxItems:100};const QUEUE_NAME$1='rudder_destinations_events';const NATIVE_DESTINATION_QUEUE_PLUGIN='NativeDestinationQueuePlugin';
|
1180
1204
|
|
@@ -1194,8 +1218,9 @@ const pluginName$5='NativeDestinationQueue';const NativeDestinationQueue=()=>({n
|
|
1194
1218
|
* @param errorHandler Error handler instance
|
1195
1219
|
* @param logger Logger instance
|
1196
1220
|
* @returns IQueue instance
|
1197
|
-
*/init(state,pluginsManager,storeManager,errorHandler,logger){const finalQOpts=getNormalizedQueueOptions$1(state.loadOptions.value.destinationsQueueOptions);const writeKey=state.lifecycle.writeKey.value;const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
1198
|
-
`${QUEUE_NAME$1}_${writeKey}`,finalQOpts,(rudderEvent,done)=>{const destinationsToSend=filterDestinations(rudderEvent.integrations,state.nativeDestinations.initializedDestinations.value)
|
1221
|
+
*/init(state,pluginsManager,storeManager,dmtQueue,errorHandler,logger){const finalQOpts=getNormalizedQueueOptions$1(state.loadOptions.value.destinationsQueueOptions);const writeKey=state.lifecycle.writeKey.value;const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
1222
|
+
`${QUEUE_NAME$1}_${writeKey}`,finalQOpts,(rudderEvent,done)=>{const destinationsToSend=filterDestinations(rudderEvent.integrations,state.nativeDestinations.initializedDestinations.value);// list of destinations which are enable for DMT
|
1223
|
+
const destWithTransformationEnabled=[];const clonedRudderEvent=clone$1(rudderEvent);destinationsToSend.forEach(dest=>{const sendEvent=!isEventDenyListed(clonedRudderEvent.type,clonedRudderEvent.event,dest);if(!sendEvent){logger?.warn(DESTINATION_EVENT_FILTERING_WARNING(NATIVE_DESTINATION_QUEUE_PLUGIN,clonedRudderEvent.event,dest.userFriendlyId));return;}if(dest.shouldApplyDeviceModeTransformation){destWithTransformationEnabled.push(dest);}else {sendEventToDestination(clonedRudderEvent,dest,errorHandler);}});if(destWithTransformationEnabled.length>0){pluginsManager.invokeSingle('transformEvent.enqueue',state,dmtQueue,clonedRudderEvent,destWithTransformationEnabled,errorHandler,logger);}// Mark success always
|
1199
1224
|
done(null);},storeManager,MEMORY_STORAGE);// TODO: This seems to not work as expected. Need to investigate
|
1200
1225
|
// effect(() => {
|
1201
1226
|
// if (state.nativeDestinations.clientDestinationsReady.value === true) {
|
@@ -1223,18 +1248,19 @@ const ONETRUST_ACCESS_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed t
|
|
1223
1248
|
|
1224
1249
|
const ONETRUST_CONSENT_MANAGER_PLUGIN='OneTrustConsentManagerPlugin';
|
1225
1250
|
|
1226
|
-
const pluginName$4='OneTrustConsentManager';const OneTrustConsentManager=()=>({name:pluginName$4,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$4];},consentManager:{init(state,
|
1251
|
+
const pluginName$4='OneTrustConsentManager';const OneTrustConsentManager=()=>({name:pluginName$4,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$4];},consentManager:{init(state,logger){// Nothing to initialize
|
1252
|
+
},updateConsentsInfo(state,storeManager,logger){if(!globalThis.OneTrust||!globalThis.OnetrustActiveGroups){logger?.error(ONETRUST_ACCESS_ERROR(ONETRUST_CONSENT_MANAGER_PLUGIN));state.consents.initialized.value=false;return;}// OneTrustConsentManager SDK populates a data layer object OnetrustActiveGroups with
|
1227
1253
|
// the cookie categories Ids that the user has consented to.
|
1228
1254
|
// Eg: ',C0001,C0003,'
|
1229
1255
|
// We split it and save it as an array.
|
1230
1256
|
const allowedConsentIds=globalThis.OnetrustActiveGroups.split(',').filter(n=>n);const allowedConsents={};const deniedConsentIds=[];// Get the groups(cookie categorization), user has created in one trust account.
|
1231
|
-
const oneTrustAllGroupsInfo=globalThis.OneTrust.GetDomainData().Groups;oneTrustAllGroupsInfo.forEach(group=>{const{CustomGroupId,GroupName}=group;if(allowedConsentIds.includes(CustomGroupId)){allowedConsents[CustomGroupId]=GroupName;}else {deniedConsentIds.push(CustomGroupId);}});state.consents.data.value={
|
1257
|
+
const oneTrustAllGroupsInfo=globalThis.OneTrust.GetDomainData().Groups;oneTrustAllGroupsInfo.forEach(group=>{const{CustomGroupId,GroupName}=group;if(allowedConsentIds.includes(CustomGroupId)){allowedConsents[CustomGroupId]=GroupName;}else {deniedConsentIds.push(CustomGroupId);}});state.consents.initialized.value=true;state.consents.data.value={allowedConsentIds:allowedConsents,deniedConsentIds};},isDestinationConsented(state,destConfig,errorHandler,logger){if(!state.consents.initialized.value){return true;}const allowedConsentIds=state.consents.data.value.allowedConsentIds;try{// mapping of the destination with the consent group name
|
1232
1258
|
const{oneTrustCookieCategories}=destConfig;// If the destination do not have this mapping events will be sent.
|
1233
1259
|
if(!oneTrustCookieCategories){return true;}// Change the structure of oneTrustConsentGroup as an array and filter values if empty string
|
1234
1260
|
// Eg:
|
1235
1261
|
// ["Performance Cookies", "Functional Cookies"]
|
1236
1262
|
const validOneTrustCookieCategories=oneTrustCookieCategories.map(c=>c.oneTrustCookieCategory).filter(n=>n);let containsAllConsent=true;// Check if all the destination's mapped cookie categories are consented by the user in the browser.
|
1237
|
-
containsAllConsent=validOneTrustCookieCategories.every(element=>Object.keys(
|
1263
|
+
containsAllConsent=validOneTrustCookieCategories.every(element=>Object.keys(allowedConsentIds).includes(element.trim())||Object.values(allowedConsentIds).includes(element.trim()));return containsAllConsent;}catch(err){errorHandler?.onError(err,ONETRUST_CONSENT_MANAGER_PLUGIN,DESTINATION_CONSENT_STATUS_ERROR);return true;}}}});
|
1238
1264
|
|
1239
1265
|
const pluginName$3='StorageEncryption';const StorageEncryption=()=>({name:pluginName$3,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$3];},storage:{encrypt(value){return encrypt$1(value);},decrypt(value){return decrypt$1(value);}}});
|
1240
1266
|
|
@@ -2223,7 +2249,7 @@ const DATA_PLANE_API_VERSION='v1';const QUEUE_NAME='rudder';const XHR_QUEUE_PLUG
|
|
2223
2249
|
|
2224
2250
|
const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,url)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s) to ${url}.`;
|
2225
2251
|
|
2226
|
-
const getBatchDeliveryPayload=(events,logger)=>
|
2252
|
+
const getBatchDeliveryPayload=(events,logger)=>{const batchPayload={batch:events};return stringifyWithoutCircular(batchPayload,true,undefined,logger);};const getNormalizedQueueOptions=queueOpts=>mergeDeepRight(DEFAULT_RETRY_QUEUE_OPTIONS,queueOpts);const getDeliveryUrl=(dataplaneUrl,endpoint)=>{const dpUrl=new URL(dataplaneUrl);return new URL(removeDuplicateSlashes([dpUrl.pathname,'/',DATA_PLANE_API_VERSION,'/',endpoint].join('')),dpUrl).href;};const getBatchDeliveryUrl=dataplaneUrl=>getDeliveryUrl(dataplaneUrl,'batch');const logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;if(Array.isArray(itemData)){const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));data=getBatchDeliveryPayload(finalEvents,logger);headers=itemData[0]?clone$1(itemData[0].headers):{};url=getBatchDeliveryUrl(state.lifecycle.activeDataplaneUrl.value);}else {const{url:eventUrl,event,headers:eventHeaders}=itemData;const finalEvent=getFinalEventForDeliveryMutator(event);data=getDeliveryPayload(finalEvent,logger);headers=clone$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
|
2227
2253
|
|
2228
2254
|
const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName];},dataplaneEventsQueue:{/**
|
2229
2255
|
* Initialize the queue for delivery
|
@@ -2254,7 +2280,7 @@ AnonymousId:toBase64(event.anonymousId)};eventsQueue.addItem({url,headers,event}
|
|
2254
2280
|
|
2255
2281
|
/**
|
2256
2282
|
* Map plugin names to direct code imports from plugins package
|
2257
|
-
*/const getBundledBuildPluginImports=()=>({BeaconQueue,Bugsnag,DeviceModeDestinations,DeviceModeTransformation,ErrorReporting,ExternalAnonymousId,GoogleLinker,KetchConsentManager,NativeDestinationQueue,OneTrustConsentManager,StorageEncryption,StorageEncryptionLegacy,StorageMigrator,XhrQueue});
|
2283
|
+
*/const getBundledBuildPluginImports=()=>({BeaconQueue,Bugsnag,CustomConsentManager,DeviceModeDestinations,DeviceModeTransformation,ErrorReporting,ExternalAnonymousId,GoogleLinker,KetchConsentManager,NativeDestinationQueue,OneTrustConsentManager,StorageEncryption,StorageEncryptionLegacy,StorageMigrator,XhrQueue});
|
2258
2284
|
|
2259
2285
|
/**
|
2260
2286
|
* Map of mandatory plugin names and direct imports
|
@@ -2283,7 +2309,7 @@ const supportedErrReportingProviderPluginNames=Object.values(ErrorReportingProvi
|
|
2283
2309
|
if(state.loadOptions.value.useBeacon===true&&state.capabilities.isBeaconAvailable.value){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!=='XhrQueue');}else {if(state.loadOptions.value.useBeacon===true){this.logger?.warn(UNSUPPORTED_BEACON_API_WARNING(PLUGINS_MANAGER));}pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!=='BeaconQueue');}// Enforce default cloud mode event delivery queue plugin is none exists
|
2284
2310
|
if(!pluginsToLoadFromConfig.includes('XhrQueue')&&!pluginsToLoadFromConfig.includes('BeaconQueue')){pluginsToLoadFromConfig.push('XhrQueue');}// Device mode destinations related plugins
|
2285
2311
|
if(getNonCloudDestinations(state.nativeDestinations.configuredDestinations.value??[]).length===0){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!['DeviceModeDestinations','DeviceModeTransformation','NativeDestinationQueue'].includes(pluginName));}// Consent Management related plugins
|
2286
|
-
const supportedConsentManagerPlugins=Object.values(ConsentManagersToPluginNameMap);
|
2312
|
+
const supportedConsentManagerPlugins=Object.values(ConsentManagersToPluginNameMap);let filterCondition=pluginName=>!(pluginName!==state.consents.activeConsentManagerPluginName.value&&supportedConsentManagerPlugins.includes(pluginName));if(!state.consents.enabled.value){filterCondition=pluginName=>!supportedConsentManagerPlugins.includes(pluginName);}pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(filterCondition);// Storage encryption related plugins
|
2287
2313
|
const supportedStorageEncryptionPlugins=Object.values(StorageEncryptionVersionsToPluginNameMap);pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>!(pluginName!==state.storage.encryptionPluginName.value&&supportedStorageEncryptionPlugins.includes(pluginName)));// Storage migrator related plugins
|
2288
2314
|
if(!state.storage.migrate.value){pluginsToLoadFromConfig=pluginsToLoadFromConfig.filter(pluginName=>pluginName!=='StorageMigrator');}return [...Object.keys(getMandatoryPluginsMap()),...pluginsToLoadFromConfig];}/**
|
2289
2315
|
* Determine the list of plugins that should be activated
|
@@ -2306,7 +2332,7 @@ unregisterLocalPlugins(){Object.values(pluginsInventory).forEach(localPlugin=>{t
|
|
2306
2332
|
|
2307
2333
|
/**
|
2308
2334
|
* Utility to parse XHR JSON response
|
2309
|
-
*/const responseTextToJson=(responseText,onError)=>{try{return JSON.parse(responseText||'');}catch(err){const error=getMutatedError(err,'Failed to parse response data');if(
|
2335
|
+
*/const responseTextToJson=(responseText,onError)=>{try{return JSON.parse(responseText||'');}catch(err){const error=getMutatedError(err,'Failed to parse response data');if(isFunction(onError)){onError(error);}else {throw error;}}return undefined;};
|
2310
2336
|
|
2311
2337
|
const DEFAULT_XHR_REQUEST_OPTIONS={headers:{Accept:'application/json','Content-Type':'application/json;charset=UTF-8'},method:'GET'};/**
|
2312
2338
|
* Utility to create request configuration based on default options
|
@@ -2326,7 +2352,7 @@ xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options
|
|
2326
2352
|
* Implement requests in a blocking way
|
2327
2353
|
*/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};}}/**
|
2328
2354
|
* Implement requests in a non-blocking way
|
2329
|
-
*/getAsyncData(config){const{callback,url,options,timeout,isRawResponse}=config;const isFireAndForget=!
|
2355
|
+
*/getAsyncData(config){const{callback,url,options,timeout,isRawResponse}=config;const isFireAndForget=!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);}});}/**
|
2330
2356
|
* Handle errors
|
2331
2357
|
*/onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,HTTP_CLIENT);}else {throw error;}}/**
|
2332
2358
|
* Set basic authentication header (eg writekey)
|
@@ -2334,9 +2360,9 @@ xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options
|
|
2334
2360
|
* Clear basic authentication header
|
2335
2361
|
*/resetAuthHeader(){this.basicAuthHeader=undefined;}}const defaultHttpClient=new HttpClient(defaultErrorHandler,defaultLogger);
|
2336
2362
|
|
2337
|
-
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_COOKIE='clientDataInCookie';const CLIENT_DATA_STORE_LS='clientDataInLocalStorage';const CLIENT_DATA_STORE_MEMORY='clientDataInMemory';
|
2363
|
+
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_COOKIE='clientDataInCookie';const CLIENT_DATA_STORE_LS='clientDataInLocalStorage';const CLIENT_DATA_STORE_MEMORY='clientDataInMemory';const CLIENT_DATA_STORE_SESSION='clientDataInSessionStorage';
|
2338
2364
|
|
2339
|
-
const storageClientDataStoreNameMap={[COOKIE_STORAGE]:CLIENT_DATA_STORE_COOKIE,[LOCAL_STORAGE]:CLIENT_DATA_STORE_LS,[MEMORY_STORAGE]:CLIENT_DATA_STORE_MEMORY};
|
2365
|
+
const storageClientDataStoreNameMap={[COOKIE_STORAGE]:CLIENT_DATA_STORE_COOKIE,[LOCAL_STORAGE]:CLIENT_DATA_STORE_LS,[MEMORY_STORAGE]:CLIENT_DATA_STORE_MEMORY,[SESSION_STORAGE]:CLIENT_DATA_STORE_SESSION};
|
2340
2366
|
|
2341
2367
|
const detectAdBlockers=(errorHandler,logger)=>{// Apparently, '?view=ad' is a query param that is blocked by majority of adblockers
|
2342
2368
|
// Use source config URL here as it is very unlikely to be blocked by adblockers
|
@@ -2352,7 +2378,7 @@ const hasCrypto=()=>!isNullOrUndefined(globalThis.crypto)&&isFunction(globalThis
|
|
2352
2378
|
|
2353
2379
|
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();});}};
|
2354
2380
|
|
2355
|
-
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,'Object.assign':()=>typeof Object.assign!==
|
2381
|
+
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,'Object.assign':()=>typeof Object.assign!=='function','Element.prototype.dataset':()=>!isDatasetAvailable(),'String.prototype.replaceAll':()=>!String.prototype.replaceAll,TextEncoder:()=>isUndefined(TextEncoder),TextDecoder:()=>isUndefined(TextDecoder),'String.fromCodePoint':()=>!String.fromCodePoint,requestAnimationFrame:()=>!isFunction(globalThis.requestAnimationFrame),cancelAnimationFrame:()=>!isFunction(globalThis.cancelAnimationFrame),CustomEvent:()=>!isFunction(globalThis.CustomEvent)};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(isFunction(isCapabilityMissing)&&isCapabilityMissing()){needsPolyfill=true;break;}}return needsPolyfill;};
|
2356
2382
|
|
2357
2383
|
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;};
|
2358
2384
|
|
@@ -2371,7 +2397,7 @@ break;case SESSION_STORAGE:storage=storageInstance??globalThis.sessionStorage;te
|
|
2371
2397
|
return undefined;}};/**
|
2372
2398
|
* Parse cookie `str`
|
2373
2399
|
*/const parse=str=>{const obj={};const pairs=str.split(/\s*;\s*/);let pair;if(!pairs[0]){return obj;}// TODO: Decode only the cookies that are needed by the SDK
|
2374
|
-
pairs.forEach(pairItem=>{pair=pairItem.split('=');const keyName=decode(pair[0]);if(keyName){obj[keyName]=decode(pair[1]);}});return obj;};/**
|
2400
|
+
pairs.forEach(pairItem=>{pair=pairItem.split('=');const keyName=pair[0]?decode(pair[0]):undefined;if(keyName){obj[keyName]=pair[1]?decode(pair[1]):undefined;}});return obj;};/**
|
2375
2401
|
* Set cookie `name` to `value`
|
2376
2402
|
*/const set=(name,value,optionsConfig,logger)=>{const options={...optionsConfig}||{};let cookieString=`${encode(name,logger)}=${encode(value,logger)}`;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;};/**
|
2377
2403
|
* Return all cookies
|
@@ -2388,9 +2414,9 @@ const legacyGetHostname=href=>{const l=document.createElement('a');l.href=href;r
|
|
2388
2414
|
* The method returns an empty array when the hostname is an ip.
|
2389
2415
|
*/const levelsFunc=url=>{// This is called before the polyfills load thus new URL cannot be used
|
2390
2416
|
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.
|
2391
|
-
if(parts.length===4&&last===parseInt(last,10).toString()){return levels;}// Localhost.
|
2417
|
+
if(parts.length===4&&last&&last===parseInt(last,10).toString()){return levels;}// Localhost.
|
2392
2418
|
if(parts.length<=1){// Fix to support localhost
|
2393
|
-
if(parts[0].indexOf('localhost')!==-1){return ['localhost'];}return levels;}// Create levels.
|
2419
|
+
if(parts[0]&&parts[0].indexOf('localhost')!==-1){return ['localhost'];}return levels;}// Create levels.
|
2394
2420
|
for(let i=parts.length-2;i>=0;i-=1){levels.push(parts.slice(i).join('.'));}return levels;};/**
|
2395
2421
|
* Get the top domain.
|
2396
2422
|
*
|
@@ -2405,12 +2431,12 @@ cookie(cname,1,opts);// If successful
|
|
2405
2431
|
if(cookie(cname)){// Remove cookie from domain
|
2406
2432
|
cookie(cname,null,opts);return domain;}}return '';};
|
2407
2433
|
|
2408
|
-
const getDefaultCookieOptions=()=>{const topDomain=domain(globalThis.location.href);return {maxage:DEFAULT_COOKIE_MAX_AGE_MS,path:'/',domain:!topDomain||topDomain==='.'?undefined:topDomain,samesite:'Lax',enabled:true};};const getDefaultLocalStorageOptions=()=>({enabled:true});const getDefaultInMemoryStorageOptions=()=>({enabled:true});
|
2434
|
+
const getDefaultCookieOptions=()=>{const topDomain=domain(globalThis.location.href);return {maxage:DEFAULT_COOKIE_MAX_AGE_MS,path:'/',domain:!topDomain||topDomain==='.'?undefined:topDomain,samesite:'Lax',enabled:true};};const getDefaultLocalStorageOptions=()=>({enabled:true});const getDefaultSessionStorageOptions=()=>({enabled:true});const getDefaultInMemoryStorageOptions=()=>({enabled:true});
|
2409
2435
|
|
2410
2436
|
/**
|
2411
2437
|
* A storage utility to persist values in cookies via Storage interface
|
2412
2438
|
*/class CookieStorage{static globalSingleton=null;isSupportAvailable=true;isEnabled=true;length=0;constructor(options={},logger){if(CookieStorage.globalSingleton){// eslint-disable-next-line no-constructor-return
|
2413
|
-
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.logger);this.length=Object.keys(cookie()).length;return true;}// eslint-disable-next-line class-methods-use-this
|
2439
|
+
return CookieStorage.globalSingleton;}this.options=getDefaultCookieOptions();this.logger=logger;this.configure(options);CookieStorage.globalSingleton=this;}configure(options){this.options=mergeDeepRight(this.options??{},options);if(options.sameDomainCookiesOnly){delete this.options.domain;}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.logger);this.length=Object.keys(cookie()).length;return true;}// eslint-disable-next-line class-methods-use-this
|
2414
2440
|
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
|
2415
2441
|
clear(){// Not implemented
|
2416
2442
|
// getting a list of all cookie storage keys and remove all values
|
@@ -2422,7 +2448,7 @@ key(index){const cookies=cookie();const cookieNames=Object.keys(cookies);return
|
|
2422
2448
|
|
2423
2449
|
/**
|
2424
2450
|
* A storage utility to retain values in memory via Storage interface
|
2425
|
-
*/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);
|
2451
|
+
*/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]?Object.keys(this.data)[index]:null;}}const defaultInMemoryStorage=new InMemoryStorage({},defaultLogger);
|
2426
2452
|
|
2427
2453
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
2428
2454
|
|
@@ -2446,19 +2472,25 @@ if(key===undefined){var ret={};this.forEach(function(key,val){return ret[key]=va
|
|
2446
2472
|
* A storage utility to persist values in localstorage via Storage interface
|
2447
2473
|
*/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
|
2448
2474
|
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
|
2449
|
-
key(index){return store.keys()[index];}}const defaultLocalStorage=new LocalStorage({},defaultLogger);
|
2475
|
+
key(index){return store.keys()[index]?store.keys()[index]:null;}}const defaultLocalStorage=new LocalStorage({},defaultLogger);
|
2476
|
+
|
2477
|
+
/**
|
2478
|
+
* A storage utility to persist values in SessionStorage via Storage interface
|
2479
|
+
*/class SessionStorage{isSupportAvailable=true;isEnabled=true;length=0;store=globalThis.sessionStorage;constructor(options={},logger){this.options=getDefaultSessionStorageOptions();this.logger=logger;this.configure(options);}configure(options){this.options=mergeDeepRight(this.options,options);this.isSupportAvailable=isStorageAvailable(SESSION_STORAGE,this,this.logger);this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){this.store.setItem(key,value);this.length=this.store.length;}getItem(key){const value=this.store.getItem(key);return isUndefined(value)?null:value;}removeItem(key){this.store.removeItem(key);this.length=this.store.length;}clear(){this.store.clear();this.length=0;}key(index){return this.store.key(index);}}const defaultSessionStorage=new SessionStorage({},defaultLogger);
|
2450
2480
|
|
2451
2481
|
/**
|
2452
2482
|
* A utility to retrieve the storage singleton instance by type
|
2453
|
-
*/const getStorageEngine=type=>{switch(type){case LOCAL_STORAGE:return defaultLocalStorage;case SESSION_STORAGE:return
|
2483
|
+
*/const getStorageEngine=type=>{switch(type){case LOCAL_STORAGE:return defaultLocalStorage;case SESSION_STORAGE:return defaultSessionStorage;case MEMORY_STORAGE:return defaultInMemoryStorage;case COOKIE_STORAGE:return new CookieStorage({},defaultLogger);default:return defaultInMemoryStorage;}};/**
|
2454
2484
|
* Configure cookie storage singleton
|
2455
2485
|
*/const configureCookieStorageEngine=options=>{new CookieStorage({},defaultLogger).configure(options);};/**
|
2456
2486
|
* Configure local storage singleton
|
2457
2487
|
*/const configureLocalStorageEngine=options=>{defaultLocalStorage.configure(options);};/**
|
2458
2488
|
* Configure in memory storage singleton
|
2459
2489
|
*/const configureInMemoryStorageEngine=options=>{defaultInMemoryStorage.configure(options);};/**
|
2490
|
+
* Configure session storage singleton
|
2491
|
+
*/const configureSessionStorageEngine=options=>{defaultSessionStorage.configure(options);};/**
|
2460
2492
|
* Configure all storage singleton instances
|
2461
|
-
*/const configureStorageEngines=(
|
2493
|
+
*/const configureStorageEngines=(cookieStorageOptions={},localStorageOptions={},inMemoryStorageOptions={},sessionStorageOptions={})=>{configureCookieStorageEngine(cookieStorageOptions);configureLocalStorageEngine(localStorageOptions);configureInMemoryStorageEngine(inMemoryStorageOptions);configureSessionStorageEngine(sessionStorageOptions);};
|
2462
2494
|
|
2463
2495
|
/**
|
2464
2496
|
* Store Implementation with dedicated storage
|
@@ -2494,18 +2526,21 @@ return JSON.parse(str);}catch(err){this.onError(new Error(`${STORE_DATA_FETCH_ER
|
|
2494
2526
|
* Handle errors
|
2495
2527
|
*/onError(error){if(this.hasErrorHandler){this.errorHandler?.onError(error,`Store ${this.id}`);}else {throw error;}}}
|
2496
2528
|
|
2529
|
+
const getStorageTypeFromPreConsent=(state,sessionKey)=>{let overriddenStorageType;if(state.consents.preConsent.value.enabled){switch(state.consents.preConsent.value.storage?.strategy){case'none':overriddenStorageType=NO_STORAGE;break;case'session':if(sessionKey!=='sessionInfo'){overriddenStorageType=NO_STORAGE;}else {overriddenStorageType=DEFAULT_STORAGE_TYPE;}break;case'anonymousId':if(sessionKey!=='anonymousId'){overriddenStorageType=NO_STORAGE;}else {overriddenStorageType=DEFAULT_STORAGE_TYPE;}break;}}return overriddenStorageType;};
|
2530
|
+
|
2497
2531
|
/**
|
2498
2532
|
* A service to manage stores & available storage client configurations
|
2499
2533
|
*/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);}/**
|
2500
2534
|
* Configure available storage client instances
|
2501
|
-
*/init(){if(this.isInitialized){return;}const config={
|
2535
|
+
*/init(){if(this.isInitialized){return;}const config={cookieStorageOptions:{samesite:state.loadOptions.value.sameSiteCookie,secure:state.loadOptions.value.secureCookie,domain:state.loadOptions.value.setCookieDomain,sameDomainCookiesOnly:state.loadOptions.value.sameDomainCookiesOnly,enabled:true},localStorageOptions:{enabled:true},inMemoryStorageOptions:{enabled:true},sessionStorageOptions:{enabled:true}};configureStorageEngines(removeUndefinedValues(mergeDeepRight(config.cookieStorageOptions??{},state.storage.cookie?.value??{})),removeUndefinedValues(config.localStorageOptions),removeUndefinedValues(config.inMemoryStorageOptions),removeUndefinedValues(config.sessionStorageOptions));this.initClientDataStores();this.isInitialized=true;}/**
|
2502
2536
|
* Create store to persist data used by the SDK like session, used details etc
|
2503
|
-
*/
|
2504
|
-
if(getStorageEngine(COOKIE_STORAGE)?.isEnabled){finalStorageType=COOKIE_STORAGE;}else if(getStorageEngine(LOCAL_STORAGE)?.isEnabled){finalStorageType=LOCAL_STORAGE;}else {finalStorageType=MEMORY_STORAGE;}break;}if(finalStorageType!==storageType){this.logger?.warn(STORAGE_UNAVAILABLE_WARNING(STORE_MANAGER,storageType,finalStorageType));}if(finalStorageType!==NO_STORAGE){trulyAnonymousTracking=false;}const storageState=state.storage.entries.value;state.storage.entries.value={...storageState,[sessionKey]:{type:finalStorageType,key:userSessionStorageKeys[storageKey]}};});state.storage.trulyAnonymousTracking.value=trulyAnonymousTracking;// TODO: fill in extra config values and bring them in from StoreManagerOptions if needed
|
2537
|
+
*/initClientDataStores(){this.initializeStorageState();// TODO: fill in extra config values and bring them in from StoreManagerOptions if needed
|
2505
2538
|
// TODO: should we pass the keys for all in order to validate or leave free as v1.1?
|
2506
2539
|
// Initializing all the enabled store because previous user data might be in different storage
|
2507
2540
|
// that needs auto migration
|
2508
|
-
const storageTypesRequiringInitialization=[MEMORY_STORAGE];if(getStorageEngine(LOCAL_STORAGE)?.isEnabled){storageTypesRequiringInitialization.push(LOCAL_STORAGE);}if(getStorageEngine(COOKIE_STORAGE)?.isEnabled){storageTypesRequiringInitialization.push(COOKIE_STORAGE);}storageTypesRequiringInitialization.forEach(storageType=>{this.setStore({id:storageClientDataStoreNameMap[storageType],name:storageClientDataStoreNameMap[storageType],isEncrypted:true,noCompoundKey:true,type:storageType});});}
|
2541
|
+
const storageTypesRequiringInitialization=[MEMORY_STORAGE];if(getStorageEngine(LOCAL_STORAGE)?.isEnabled){storageTypesRequiringInitialization.push(LOCAL_STORAGE);}if(getStorageEngine(COOKIE_STORAGE)?.isEnabled){storageTypesRequiringInitialization.push(COOKIE_STORAGE);}if(getStorageEngine(SESSION_STORAGE)?.isEnabled){storageTypesRequiringInitialization.push(SESSION_STORAGE);}storageTypesRequiringInitialization.forEach(storageType=>{this.setStore({id:storageClientDataStoreNameMap[storageType],name:storageClientDataStoreNameMap[storageType],isEncrypted:true,noCompoundKey:true,type:storageType});});}initializeStorageState(){const globalStorageType=state.storage.type.value;let trulyAnonymousTracking=true;const entries=state.loadOptions.value.storage?.entries;const userSessionKeyValues=['userId','userTraits','anonymousId','groupId','groupTraits','initialReferrer','initialReferringDomain','sessionInfo'];userSessionKeyValues.forEach(sessionKey=>{const key=sessionKey;const storageKey=sessionKey;const providedStorageType=entries?.[key]?.type;const preConsentStorageType=getStorageTypeFromPreConsent(state,sessionKey);// Storage type precedence order: pre-consent strategy > entry type > global type > default
|
2542
|
+
const storageType=preConsentStorageType??providedStorageType??globalStorageType??DEFAULT_STORAGE_TYPE;let finalStorageType=storageType;switch(storageType){case LOCAL_STORAGE:if(!getStorageEngine(LOCAL_STORAGE)?.isEnabled){finalStorageType=MEMORY_STORAGE;}break;case SESSION_STORAGE:if(!getStorageEngine(SESSION_STORAGE)?.isEnabled){finalStorageType=MEMORY_STORAGE;}break;case MEMORY_STORAGE:case NO_STORAGE:break;case COOKIE_STORAGE:default:// First try setting the storage to cookie else to local storage
|
2543
|
+
if(getStorageEngine(COOKIE_STORAGE)?.isEnabled){finalStorageType=COOKIE_STORAGE;}else if(getStorageEngine(LOCAL_STORAGE)?.isEnabled){finalStorageType=LOCAL_STORAGE;}else if(getStorageEngine(SESSION_STORAGE)?.isEnabled){finalStorageType=SESSION_STORAGE;}else {finalStorageType=MEMORY_STORAGE;}break;}if(finalStorageType!==storageType){this.logger?.warn(STORAGE_UNAVAILABLE_WARNING(STORE_MANAGER,storageType,finalStorageType));}if(finalStorageType!==NO_STORAGE){trulyAnonymousTracking=false;}const storageState=state.storage.entries.value;state.storage.entries.value={...storageState,[sessionKey]:{type:finalStorageType,key:userSessionStorageKeys[storageKey]}};});state.storage.trulyAnonymousTracking.value=trulyAnonymousTracking;}/**
|
2509
2544
|
* Create a new store
|
2510
2545
|
*/setStore(storeConfig){const storageEngine=getStorageEngine(storeConfig.type);this.stores[storeConfig.id]=new Store(storeConfig,storageEngine,this.pluginsManager);return this.stores[storeConfig.id];}/**
|
2511
2546
|
* Retrieve a store
|
@@ -2543,7 +2578,7 @@ const validateWriteKey=writeKey=>{if(!isString(writeKey)||writeKey.trim().length
|
|
2543
2578
|
|
2544
2579
|
/**
|
2545
2580
|
* Plugins to be loaded in the plugins loadOption is not defined
|
2546
|
-
*/const defaultOptionalPluginsList=['BeaconQueue','Bugsnag','DeviceModeDestinations','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
|
2581
|
+
*/const defaultOptionalPluginsList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
|
2547
2582
|
|
2548
2583
|
/**
|
2549
2584
|
* A function to check given value is a number or not
|
@@ -2594,18 +2629,27 @@ const DEFAULT_PRE_CONSENT_STORAGE_STRATEGY='none';const DEFAULT_PRE_CONSENT_EVEN
|
|
2594
2629
|
const isErrorReportingEnabled=sourceConfig=>sourceConfig?.statsCollection?.errors?.enabled===true;const getErrorReportingProviderNameFromConfig=sourceConfig=>sourceConfig?.statsCollection?.errors?.provider;const isMetricsReportingEnabled=sourceConfig=>sourceConfig?.statsCollection?.metrics?.enabled===true;
|
2595
2630
|
|
2596
2631
|
/**
|
2597
|
-
*
|
2598
|
-
* @param
|
2599
|
-
* @returns
|
2600
|
-
|
2601
|
-
|
2602
|
-
*
|
2603
|
-
*
|
2604
|
-
*
|
2605
|
-
|
2606
|
-
*
|
2607
|
-
*
|
2608
|
-
|
2632
|
+
* Validates and normalizes the consent options provided by the user
|
2633
|
+
* @param options Consent options provided by the user
|
2634
|
+
* @returns Validated and normalized consent options
|
2635
|
+
*/const getValidPostConsentOptions=options=>{const validOptions={sendPageEvent:false,trackConsent:false,discardPreConsentEvents:false};if(isObjectLiteralAndNotNull(options)){const clonedOptions=clone$1(options);validOptions.storage=clonedOptions.storage;validOptions.integrations=clonedOptions.integrations;validOptions.discardPreConsentEvents=clonedOptions.discardPreConsentEvents===true;validOptions.sendPageEvent=clonedOptions.sendPageEvent===true;validOptions.trackConsent=clonedOptions.trackConsent===true;if(isNonEmptyObject(clonedOptions.consentManagement)){// Override enabled value with the current state value
|
2636
|
+
validOptions.consentManagement=mergeDeepRight(clonedOptions.consentManagement,{enabled:state.consents.enabled.value});}}return validOptions;};/**
|
2637
|
+
* Validates if the input is a valid consents data
|
2638
|
+
* @param value Input consents data
|
2639
|
+
* @returns true if the input is a valid consents data else false
|
2640
|
+
*/const isValidConsentsData=value=>isNonEmptyObject(value)||Array.isArray(value);/**
|
2641
|
+
* Retrieves the corresponding plugin name of the selected consent manager from the supported consent managers
|
2642
|
+
* @param consentProvider consent management provider name
|
2643
|
+
* @param logger logger instance
|
2644
|
+
* @returns Corresponding plugin name of the selected consent manager from the supported consent managers
|
2645
|
+
*/const getConsentManagerPluginName=(consentProvider,logger)=>{const consentManagerPluginName=ConsentManagersToPluginNameMap[consentProvider];if(consentProvider&&!consentManagerPluginName){logger?.error(UNSUPPORTED_CONSENT_MANAGER_ERROR(CONFIG_MANAGER,consentProvider,ConsentManagersToPluginNameMap));}return consentManagerPluginName;};/**
|
2646
|
+
* Validates and converts the consent management options into a normalized format
|
2647
|
+
* @param consentManagementOpts Consent management options provided by the user
|
2648
|
+
* @param logger logger instance
|
2649
|
+
* @returns An object containing the consent manager plugin name, initialized, enabled and consents data
|
2650
|
+
*/const getConsentManagementData=(consentManagementOpts,logger)=>{let consentManagerPluginName;let allowedConsentIds=[];let deniedConsentIds=[];let initialized=false;let enabled=consentManagementOpts?.enabled===true;if(isNonEmptyObject(consentManagementOpts)&&enabled){const consentProvider=consentManagementOpts.provider;// Get the corresponding plugin name of the selected consent manager from the supported consent managers
|
2651
|
+
consentManagerPluginName=getConsentManagerPluginName(consentProvider,logger);if(isValidConsentsData(consentManagementOpts.allowedConsentIds)){allowedConsentIds=consentManagementOpts.allowedConsentIds;initialized=true;}if(isValidConsentsData(consentManagementOpts.deniedConsentIds)){deniedConsentIds=consentManagementOpts.deniedConsentIds;initialized=true;}}const consentsData={allowedConsentIds,deniedConsentIds};// Enable consent management only if consent manager is supported
|
2652
|
+
enabled=enabled&&Boolean(consentManagerPluginName);return {consentManagerPluginName,initialized,enabled,consentsData};};
|
2609
2653
|
|
2610
2654
|
/**
|
2611
2655
|
* Determines the SDK url
|
@@ -2618,10 +2662,11 @@ const isErrorReportingEnabled=sourceConfig=>sourceConfig?.statsCollection?.error
|
|
2618
2662
|
const errReportingProviderPlugin=errReportingProvider?ErrorReportingProvidersToPluginNameMap[errReportingProvider]:undefined;if(!isUndefined(errReportingProvider)&&!errReportingProviderPlugin){// set the default error reporting provider
|
2619
2663
|
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=>{const storageOptsFromLoad=state.loadOptions.value.storage;let storageType=storageOptsFromLoad?.type;if(isDefined(storageType)&&!isValidStorageType(storageType)){logger?.warn(STORAGE_TYPE_VALIDATION_WARNING(CONFIG_MANAGER,storageType,DEFAULT_STORAGE_TYPE));storageType=DEFAULT_STORAGE_TYPE;}let storageEncryptionVersion=storageOptsFromLoad?.encryption?.version;const encryptionPluginName=storageEncryptionVersion&&StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];if(!isUndefined(storageEncryptionVersion)&&isUndefined(encryptionPluginName)){// set the default encryption plugin
|
2620
2664
|
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;}// Allow migration only if the configured encryption version is the default encryption version
|
2621
|
-
const configuredMigrationValue=storageOptsFromLoad?.migrate;const finalMigrationVal=configuredMigrationValue&&storageEncryptionVersion===DEFAULT_STORAGE_ENCRYPTION_VERSION;if(configuredMigrationValue===true&&finalMigrationVal!==configuredMigrationValue){logger?.warn(STORAGE_DATA_MIGRATION_OVERRIDE_WARNING(CONFIG_MANAGER,storageEncryptionVersion,DEFAULT_STORAGE_ENCRYPTION_VERSION));}n(()=>{state.storage.type.value=storageType;state.storage.cookie.value=storageOptsFromLoad?.cookie;state.storage.encryptionPluginName.value=StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];state.storage.migrate.value=finalMigrationVal;});};const updateConsentsState=logger=>{
|
2622
|
-
const
|
2623
|
-
|
2624
|
-
|
2665
|
+
const configuredMigrationValue=storageOptsFromLoad?.migrate;const finalMigrationVal=configuredMigrationValue&&storageEncryptionVersion===DEFAULT_STORAGE_ENCRYPTION_VERSION;if(configuredMigrationValue===true&&finalMigrationVal!==configuredMigrationValue){logger?.warn(STORAGE_DATA_MIGRATION_OVERRIDE_WARNING(CONFIG_MANAGER,storageEncryptionVersion,DEFAULT_STORAGE_ENCRYPTION_VERSION));}n(()=>{state.storage.type.value=storageType;state.storage.cookie.value=storageOptsFromLoad?.cookie;state.storage.encryptionPluginName.value=StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];state.storage.migrate.value=finalMigrationVal;});};const updateConsentsState=logger=>{const{consentManagerPluginName,initialized,enabled,consentsData}=getConsentManagementData(state.loadOptions.value.consentManagement,logger);// Pre-consent
|
2666
|
+
const preConsentOpts=state.loadOptions.value.preConsent;let storageStrategy=preConsentOpts?.storage?.strategy??DEFAULT_PRE_CONSENT_STORAGE_STRATEGY;const StorageStrategies=['none','session','anonymousId'];if(isDefined(storageStrategy)&&!StorageStrategies.includes(storageStrategy)){storageStrategy=DEFAULT_PRE_CONSENT_STORAGE_STRATEGY;logger?.warn(UNSUPPORTED_PRE_CONSENT_STORAGE_STRATEGY(CONFIG_MANAGER,preConsentOpts?.storage?.strategy,DEFAULT_PRE_CONSENT_STORAGE_STRATEGY));}let eventsDeliveryType=preConsentOpts?.events?.delivery??DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE;const deliveryTypes=['immediate','buffer'];if(isDefined(eventsDeliveryType)&&!deliveryTypes.includes(eventsDeliveryType)){eventsDeliveryType=DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE;logger?.warn(UNSUPPORTED_PRE_CONSENT_EVENTS_DELIVERY_TYPE(CONFIG_MANAGER,preConsentOpts?.events?.delivery,DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE));}n(()=>{state.consents.activeConsentManagerPluginName.value=consentManagerPluginName;state.consents.initialized.value=initialized;state.consents.enabled.value=enabled;state.consents.data.value=consentsData;state.consents.preConsent.value={// Only enable pre-consent if it is explicitly enabled and
|
2667
|
+
// if it is not already initialized and
|
2668
|
+
// if consent management is enabled
|
2669
|
+
enabled:state.loadOptions.value.preConsent?.enabled===true&&initialized===false&&enabled===true,storage:{strategy:storageStrategy},events:{delivery:eventsDeliveryType}};});};
|
2625
2670
|
|
2626
2671
|
/**
|
2627
2672
|
* A function that determines integration SDK loading path
|
@@ -2643,7 +2688,7 @@ const sdkURL=getSDKUrl();pluginsCDNPath=sdkURL&&isString(sdkURL)?sdkURL.split('/
|
|
2643
2688
|
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(){O(()=>{this.logger?.setMinLogLevel(state.lifecycle.logLevel.value);});}/**
|
2644
2689
|
* A function to validate, construct and store loadOption, lifecycle, source and destination
|
2645
2690
|
* config related information in global state
|
2646
|
-
*/init(){this.attachEffects();
|
2691
|
+
*/init(){this.attachEffects();validateLoadArgs(state.lifecycle.writeKey.value,state.lifecycle.dataPlaneUrl.value);const lockIntegrationsVersion=state.loadOptions.value.lockIntegrationsVersion;// determine the path to fetch integration SDK from
|
2647
2692
|
const intgCdnUrl=getIntegrationsCDNPath(APP_VERSION,lockIntegrationsVersion,state.loadOptions.value.destSDKBaseURL);// determine the path to fetch remote plugins from
|
2648
2693
|
const pluginsCDNPath=getPluginsCDNPath(state.loadOptions.value.pluginsSDKBaseURL);updateStorageState(this.logger);updateConsentsState(this.logger);// set application lifecycle state in global state
|
2649
2694
|
n(()=>{state.lifecycle.integrationsCDNPath.value=intgCdnUrl;state.lifecycle.pluginsCDNPath.value=pluginsCDNPath;if(state.loadOptions.value.logLevel){state.lifecycle.logLevel.value=state.loadOptions.value.logLevel;}state.lifecycle.sourceConfigUrl.value=getSourceConfigURL(state.loadOptions.value.configUrl,state.lifecycle.writeKey.value,lockIntegrationsVersion,this.logger);});this.getConfig();}/**
|
@@ -2669,6 +2714,12 @@ state.lifecycle.activeDataplaneUrl.value=removeTrailingSlashes(dataPlaneUrl);sta
|
|
2669
2714
|
const res=sourceConfigFunc();if(res instanceof Promise){res.then(pRes=>this.processConfig(pRes)).catch(err=>{this.onError(err,'SourceConfig');});}else {this.processConfig(res);}}else {// fetch source config from config url API
|
2670
2715
|
this.httpClient.getAsyncData({url:state.lifecycle.sourceConfigUrl.value,options:{headers:{'Content-Type':undefined}},callback:this.processConfig});}}}
|
2671
2716
|
|
2717
|
+
/**
|
2718
|
+
* To get the timezone of the user
|
2719
|
+
*
|
2720
|
+
* @returns string
|
2721
|
+
*/const getTimezone=()=>{const timezone=new Date().toString().match(/([A-Z]+[+-]\d+)/);return timezone&&timezone[1]?timezone[1]:'NA';};
|
2722
|
+
|
2672
2723
|
/**
|
2673
2724
|
* Get the referrer URL
|
2674
2725
|
* @returns The referrer URL
|
@@ -2696,15 +2747,15 @@ class CapabilitiesManager{constructor(errorHandler,logger){this.logger=logger;th
|
|
2696
2747
|
detectBrowserCapabilities(){n(()=>{// Storage related details
|
2697
2748
|
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
|
2698
2749
|
state.capabilities.isBeaconAvailable.value=hasBeacon();state.capabilities.isUaCHAvailable.value=hasUAClientHints();state.capabilities.isCryptoAvailable.value=hasCrypto();state.capabilities.isIE11.value=isIE11();state.capabilities.isOnline.value=globalThis.navigator.onLine;// Get page context details
|
2699
|
-
state.context.userAgent.value=getUserAgent();state.context.locale.value=getLanguage();state.context.screen.value=getScreenDetails();if(hasUAClientHints()){getUserAgentClientHint(uach=>{state.context['ua-ch'].value=uach;},state.loadOptions.value.uaChTrackLevel);}});// Ad blocker detection
|
2750
|
+
state.context.userAgent.value=getUserAgent();state.context.locale.value=getLanguage();state.context.screen.value=getScreenDetails();state.context.timezone.value=getTimezone();if(hasUAClientHints()){getUserAgentClientHint(uach=>{state.context['ua-ch'].value=uach;},state.loadOptions.value.uaChTrackLevel);}});// Ad blocker detection
|
2700
2751
|
O(()=>{if(state.loadOptions.value.sendAdblockPage===true&&state.lifecycle.sourceConfigUrl.value!==undefined){detectAdBlockers(this.errorHandler,this.logger);}});}/**
|
2701
2752
|
* Detect if polyfills are required and then load script from polyfill URL
|
2702
|
-
*/prepareBrowserCapabilities(){state.capabilities.isLegacyDOM.value=isLegacyJSEngine();let polyfillUrl=state.loadOptions.value.polyfillURL??POLYFILL_URL;const shouldLoadPolyfill=state.loadOptions.value.polyfillIfRequired&&state.capabilities.isLegacyDOM.value&&Boolean(polyfillUrl);if(shouldLoadPolyfill){const isDefaultPolyfillService=polyfillUrl!==state.loadOptions.value.polyfillURL;if(isDefaultPolyfillService){
|
2753
|
+
*/prepareBrowserCapabilities(){state.capabilities.isLegacyDOM.value=isLegacyJSEngine();let polyfillUrl=state.loadOptions.value.polyfillURL??POLYFILL_URL;const shouldLoadPolyfill=state.loadOptions.value.polyfillIfRequired&&state.capabilities.isLegacyDOM.value&&Boolean(polyfillUrl);if(shouldLoadPolyfill){const isDefaultPolyfillService=polyfillUrl!==state.loadOptions.value.polyfillURL;if(isDefaultPolyfillService){// write key specific callback
|
2703
2754
|
// NOTE: we're not putting this into RudderStackGlobals as providing the property path to the callback function in the polyfill URL is not possible
|
2704
|
-
const polyfillCallbackName=`RS_polyfillCallback_${state.lifecycle.writeKey.value}`;
|
2755
|
+
const polyfillCallbackName=`RS_polyfillCallback_${state.lifecycle.writeKey.value}`;const polyfillCallback=()=>{this.onReady();// Remove the entry from window so we don't leave room for calling it again
|
2756
|
+
delete globalThis[polyfillCallbackName];};globalThis[polyfillCallbackName]=polyfillCallback;polyfillUrl=`${polyfillUrl}&callback=${polyfillCallbackName}`;}this.externalSrcLoader?.loadJSFile({url:polyfillUrl,id:POLYFILL_SCRIPT_ID,async:true,timeout:POLYFILL_LOAD_TIMEOUT,callback:scriptId=>{if(!scriptId){this.onError(new Error(POLYFILL_SCRIPT_LOAD_ERROR(POLYFILL_SCRIPT_ID,polyfillUrl)));}else if(!isDefaultPolyfillService){this.onReady();}}});}else {this.onReady();}}/**
|
2705
2757
|
* Attach listeners to window to observe event that update capabilities state values
|
2706
|
-
*/
|
2707
|
-
attachWindowListeners(){globalThis.addEventListener('offline',()=>{state.capabilities.isOnline.value=false;});globalThis.addEventListener('online',()=>{state.capabilities.isOnline.value=true;});globalThis.addEventListener('resize',debounce(()=>{state.context.screen.value=getScreenDetails();},this));}/**
|
2758
|
+
*/attachWindowListeners(){globalThis.addEventListener('offline',()=>{state.capabilities.isOnline.value=false;});globalThis.addEventListener('online',()=>{state.capabilities.isOnline.value=true;});globalThis.addEventListener('resize',debounce(()=>{state.context.screen.value=getScreenDetails();},this));}/**
|
2708
2759
|
* Set the lifecycle status to next phase
|
2709
2760
|
*/ // eslint-disable-next-line class-methods-use-this
|
2710
2761
|
onReady(){this.detectBrowserCapabilities();state.lifecycle.status.value='browserCapabilitiesReady';}/**
|
@@ -2743,7 +2794,7 @@ const{properties,traits,context}=rudderEvent;const{traits:contextualTraits}=cont
|
|
2743
2794
|
* @param rudderEvent Generated rudder event
|
2744
2795
|
* @param options API options
|
2745
2796
|
*/const updateTopLevelEventElements=(rudderEvent,options)=>{if(options.anonymousId&&isString(options.anonymousId)){// eslint-disable-next-line no-param-reassign
|
2746
|
-
rudderEvent.anonymousId=options.anonymousId;}if(
|
2797
|
+
rudderEvent.anonymousId=options.anonymousId;}if(isObjectLiteralAndNotNull(options.integrations)){// eslint-disable-next-line no-param-reassign
|
2747
2798
|
rudderEvent.integrations=options.integrations;}if(options.originalTimestamp&&isString(options.originalTimestamp)){// eslint-disable-next-line no-param-reassign
|
2748
2799
|
rudderEvent.originalTimestamp=options.originalTimestamp;}};/**
|
2749
2800
|
* To merge the contextual information in API options with existing data
|
@@ -2758,7 +2809,7 @@ rudderEvent.originalTimestamp=options.originalTimestamp;}};/**
|
|
2758
2809
|
* @param rudderEvent Generated rudder event
|
2759
2810
|
* @param options API options
|
2760
2811
|
*/const processOptions=(rudderEvent,options)=>{// Only allow object type for options
|
2761
|
-
if(
|
2812
|
+
if(isObjectLiteralAndNotNull(options)){updateTopLevelEventElements(rudderEvent,options);// eslint-disable-next-line no-param-reassign
|
2762
2813
|
rudderEvent.context=getMergedContext(rudderEvent.context,options);}};/**
|
2763
2814
|
* Returns the final integrations config for the event based on the global config and event's config
|
2764
2815
|
* @param integrationsConfig Event's integrations config
|
@@ -2770,7 +2821,7 @@ rudderEvent.context=getMergedContext(rudderEvent.context,options);}};/**
|
|
2770
2821
|
* @param pageProps Page properties
|
2771
2822
|
* @param logger logger
|
2772
2823
|
* @returns Enriched RudderEvent object
|
2773
|
-
*/const getEnrichedEvent=(rudderEvent,options,pageProps,logger)=>{const commonEventData={channel:CHANNEL,context:{traits:clone$1(state.session.userTraits.value),sessionId:state.session.sessionInfo.value.id||undefined,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:extractUTMParameters(globalThis.location.href),page:getContextPageProperties(pageProps)},originalTimestamp:getCurrentTimeFormatted(),integrations:DEFAULT_INTEGRATIONS_CONFIG,messageId:generateUUID(),userId:rudderEvent.userId||state.session.userId.value};if(state.storage.entries.value.anonymousId?.type===NO_STORAGE){// Generate new anonymous id for each request
|
2824
|
+
*/const getEnrichedEvent=(rudderEvent,options,pageProps,logger)=>{const commonEventData={channel:CHANNEL,context:{traits:clone$1(state.session.userTraits.value),sessionId:state.session.sessionInfo.value.id||undefined,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:extractUTMParameters(globalThis.location.href),page:getContextPageProperties(pageProps),timezone:state.context.timezone.value},originalTimestamp:getCurrentTimeFormatted(),integrations:DEFAULT_INTEGRATIONS_CONFIG,messageId:generateUUID(),userId:rudderEvent.userId||state.session.userId.value};if(state.storage.entries.value.anonymousId?.type===NO_STORAGE){// Generate new anonymous id for each request
|
2774
2825
|
commonEventData.anonymousId=generateUUID();}else {// Type casting to string as the user session manager will take care of initializing the value
|
2775
2826
|
commonEventData.anonymousId=state.session.anonymousId.value;}// set truly anonymous tracking flag
|
2776
2827
|
if(state.storage.trulyAnonymousTracking.value){commonEventData.context.trulyAnonymousTracking=true;}if(rudderEvent.type==='identify'){commonEventData.context.traits=state.storage.entries.value.userTraits?.type!==NO_STORAGE?clone$1(state.session.userTraits.value):rudderEvent.context.traits;}if(rudderEvent.type==='group'){if(rudderEvent.groupId||state.session.groupId.value){commonEventData.groupId=rudderEvent.groupId||state.session.groupId.value;}if(rudderEvent.traits||state.session.groupTraits.value){commonEventData.traits=state.storage.entries.value.groupTraits?.type!==NO_STORAGE?clone$1(state.session.groupTraits.value):rudderEvent.traits;}}const processedEvent=mergeDeepRight(rudderEvent,commonEventData);// Set the default values for the event properties
|
@@ -2821,7 +2872,7 @@ enrichedEvent.userId=to??enrichedEvent.userId;return enrichedEvent;}/**
|
|
2821
2872
|
* @param logger Logger object
|
2822
2873
|
*/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);}/**
|
2823
2874
|
* Initializes the event manager
|
2824
|
-
*/init(){this.eventRepository.init();}/**
|
2875
|
+
*/init(){this.eventRepository.init();}resume(){this.eventRepository.resume();}/**
|
2825
2876
|
* Consumes a new incoming event
|
2826
2877
|
* @param event Incoming event data
|
2827
2878
|
*/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));}}/**
|
@@ -2851,14 +2902,14 @@ timeout,sessionStart:undefined,autoTrack:true};};/**
|
|
2851
2902
|
* @param id Provided sessionId
|
2852
2903
|
* @param logger Logger module
|
2853
2904
|
* @returns SessionInfo
|
2854
|
-
*/const generateManualTrackingSession=(id,logger)=>{const sessionId=isManualSessionIdValid(id,logger)?id:generateSessionId();return {id:sessionId,sessionStart:undefined,manualTrack:true};};const isStorageTypeValidForStoringData=storageType=>Boolean(storageType===COOKIE_STORAGE||storageType===LOCAL_STORAGE||storageType===MEMORY_STORAGE);
|
2905
|
+
*/const generateManualTrackingSession=(id,logger)=>{const sessionId=isManualSessionIdValid(id,logger)?id:generateSessionId();return {id:sessionId,sessionStart:undefined,manualTrack:true};};const isStorageTypeValidForStoringData=storageType=>Boolean(storageType===COOKIE_STORAGE||storageType===LOCAL_STORAGE||storageType===SESSION_STORAGE||storageType===MEMORY_STORAGE);
|
2855
2906
|
|
2856
2907
|
class UserSessionManager{constructor(errorHandler,logger,pluginsManager,storeManager){this.storeManager=storeManager;this.pluginsManager=pluginsManager;this.logger=logger;this.errorHandler=errorHandler;this.onError=this.onError.bind(this);}/**
|
2857
2908
|
* Initialize User session with values from storage
|
2858
|
-
*/init(){this.
|
2859
|
-
|
2860
|
-
if(this.
|
2861
|
-
this.
|
2909
|
+
*/init(){this.syncStorageDataToState();// Register the effect to sync with storage
|
2910
|
+
this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
|
2911
|
+
const userId=this.getUserId();const userTraits=this.getUserTraits();const groupId=this.getGroupId();const groupTraits=this.getGroupTraits();const anonymousId=this.getAnonymousId(state.loadOptions.value.anonymousIdOptions);if(userId){this.setUserId(userId);}if(userTraits){this.setUserTraits(userTraits);}if(groupId){this.setGroupId(groupId);}if(groupTraits){this.setGroupTraits(groupTraits);}if(anonymousId){this.setAnonymousId(anonymousId);}const authToken=this.getAuthToken();if(authToken){this.setAuthToken(authToken);}const persistedInitialReferrer=this.getInitialReferrer();const persistedInitialReferringDomain=this.getInitialReferringDomain();if(persistedInitialReferrer&&persistedInitialReferringDomain){this.setInitialReferrer(persistedInitialReferrer);this.setInitialReferringDomain(persistedInitialReferringDomain);}else {const initialReferrer=persistedInitialReferrer||getReferrer();this.setInitialReferrer(initialReferrer);this.setInitialReferringDomain(getReferringDomain(initialReferrer));}// Initialize session tracking
|
2912
|
+
if(this.isPersistenceEnabledForStorageEntry('sessionInfo')){this.initializeSessionTracking();}}isPersistenceEnabledForStorageEntry(entryName){const entries=state.storage.entries.value;return isStorageTypeValidForStoringData(entries[entryName]?.type);}migrateDataFromPreviousStorage(){const entries=state.storage.entries.value;const storagesForMigration=[COOKIE_STORAGE,LOCAL_STORAGE,SESSION_STORAGE];Object.keys(entries).forEach(entry=>{const key=entry;const currentStorage=entries[key]?.type;const curStore=this.storeManager?.getStore(storageClientDataStoreNameMap[currentStorage]);if(curStore){storagesForMigration.forEach(storage=>{const store=this.storeManager?.getStore(storageClientDataStoreNameMap[storage]);if(store&&storage!==currentStorage){const value=store.get(userSessionStorageKeys[key]);if(isDefinedNotNullAndNotEmptyString(value)){curStore.set(userSessionStorageKeys[key],value);}store.remove(userSessionStorageKeys[key]);}});}});}migrateStorageIfNeeded(){if(!state.storage.migrate.value){return;}const cookieStorage=this.storeManager?.getStore(CLIENT_DATA_STORE_COOKIE);const localStorage=this.storeManager?.getStore(CLIENT_DATA_STORE_LS);const sessionStorage=this.storeManager?.getStore(CLIENT_DATA_STORE_SESSION);const stores=[];if(cookieStorage){stores.push(cookieStorage);}if(localStorage){stores.push(localStorage);}if(sessionStorage){stores.push(sessionStorage);}Object.keys(userSessionStorageKeys).forEach(storageEntryKey=>{const key=storageEntryKey;const storageEntry=userSessionStorageKeys[key];stores.forEach(store=>{const migratedVal=this.pluginsManager?.invokeSingle('storage.migrate',storageEntry,store.engine,this.errorHandler,this.logger);if(migratedVal){store.set(storageEntry,migratedVal);}});});}/**
|
2862
2913
|
* A function to initialize sessionTracking
|
2863
2914
|
*/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_MS));sessionTimeout=DEFAULT_SESSION_TIMEOUT_MS;}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
|
2864
2915
|
// and will proceed with it
|
@@ -2888,14 +2939,16 @@ if(state.session.sessionInfo.value.autoTrack){this.startOrRenewAutoTracking();}}
|
|
2888
2939
|
* Update initial referring domain in storage automatically when it is updated in state
|
2889
2940
|
*/O(()=>{this.syncValueToStorage('initialReferringDomain',state.session.initialReferringDomain.value);});/**
|
2890
2941
|
* Update session tracking info in storage automatically when it is updated in state
|
2891
|
-
*/O(()=>{this.syncValueToStorage('sessionInfo',state.session.sessionInfo.value);})
|
2942
|
+
*/O(()=>{this.syncValueToStorage('sessionInfo',state.session.sessionInfo.value);});/**
|
2943
|
+
* Update session tracking info in storage automatically when it is updated in state
|
2944
|
+
*/O(()=>{this.syncValueToStorage('authToken',state.session.authToken.value);});}/**
|
2892
2945
|
* Sets anonymous id in the following precedence:
|
2893
2946
|
*
|
2894
2947
|
* 1. anonymousId: Id directly provided to the function.
|
2895
2948
|
* 2. rudderAmpLinkerParam: value generated from linker query parm (rudderstack)
|
2896
2949
|
* using parseLinker util.
|
2897
2950
|
* 3. generateUUID: A new unique id is generated and assigned.
|
2898
|
-
*/setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;
|
2951
|
+
*/setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;if(this.isPersistenceEnabledForStorageEntry('anonymousId')){if(!finalAnonymousId&&rudderAmpLinkerParam){const linkerPluginsResult=this.pluginsManager?.invokeMultiple('userSession.anonymousIdGoogleLinker',rudderAmpLinkerParam);finalAnonymousId=linkerPluginsResult?.[0];}state.session.anonymousId.value=finalAnonymousId||this.generateAnonymousId();}}/**
|
2899
2952
|
* Generate a new anonymousId
|
2900
2953
|
* @returns string anonymousID
|
2901
2954
|
*/generateAnonymousId(){return generateUUID();}/**
|
@@ -2926,6 +2979,9 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
|
|
2926
2979
|
* Fetches session tracking information from storage
|
2927
2980
|
* @returns
|
2928
2981
|
*/getSessionFromStorage(){return this.getItem('sessionInfo');}/**
|
2982
|
+
* Fetches auth token from storage
|
2983
|
+
* @returns
|
2984
|
+
*/getAuthToken(){return this.getItem('authToken');}/**
|
2929
2985
|
* If session is active it returns the sessionId
|
2930
2986
|
* @returns
|
2931
2987
|
*/getSessionId(){if(state.session.sessionInfo.value.autoTrack&&!hasSessionExpired(state.session.sessionInfo.value.expiresAt)||state.session.sessionInfo.value.manualTrack){return state.session.sessionInfo.value.id||null;}return null;}/**
|
@@ -2935,7 +2991,8 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
|
|
2935
2991
|
* @param resetAnonymousId
|
2936
2992
|
* @param noNewSessionStart
|
2937
2993
|
* @returns
|
2938
|
-
*/reset(resetAnonymousId,noNewSessionStart){const{manualTrack,autoTrack}=state.session.sessionInfo.value;n(()=>{state.session.userId.value=defaultUserSessionValues.userId;state.session.userTraits.value=defaultUserSessionValues.userTraits;state.session.groupId.value=defaultUserSessionValues.groupId;state.session.groupTraits.value=defaultUserSessionValues.groupTraits;
|
2994
|
+
*/reset(resetAnonymousId,noNewSessionStart){const{manualTrack,autoTrack}=state.session.sessionInfo.value;n(()=>{state.session.userId.value=defaultUserSessionValues.userId;state.session.userTraits.value=defaultUserSessionValues.userTraits;state.session.groupId.value=defaultUserSessionValues.groupId;state.session.groupTraits.value=defaultUserSessionValues.groupTraits;state.session.authToken.value=defaultUserSessionValues.authToken;if(resetAnonymousId){// This will generate a new anonymous ID
|
2995
|
+
this.setAnonymousId();}if(noNewSessionStart){return;}if(autoTrack){state.session.sessionInfo.value=defaultUserSessionValues.sessionInfo;this.startOrRenewAutoTracking();}else if(manualTrack){this.startManualTrackingInternal();}});}/**
|
2939
2996
|
* Set user Id
|
2940
2997
|
* @param userId
|
2941
2998
|
*/setUserId(userId){if(this.isPersistenceEnabledForStorageEntry('userId')){state.session.userId.value=userId;}}/**
|
@@ -2964,13 +3021,16 @@ const autoCapturedAnonymousId=this.pluginsManager?.invokeSingle('storage.getAnon
|
|
2964
3021
|
* An internal function to start manual session
|
2965
3022
|
*/startManualTrackingInternal(){this.start(Date.now());}/**
|
2966
3023
|
* A public method to end an ongoing session.
|
2967
|
-
*/end(){state.session.sessionInfo.value={};}
|
3024
|
+
*/end(){state.session.sessionInfo.value={};}/**
|
3025
|
+
* Set auth token
|
3026
|
+
* @param userId
|
3027
|
+
*/setAuthToken(token){if(this.isPersistenceEnabledForStorageEntry('authToken')){state.session.authToken.value=token;}}}
|
2968
3028
|
|
2969
3029
|
/**
|
2970
3030
|
* A buffer queue to serve as a store for any type of data
|
2971
3031
|
*/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=[];}}
|
2972
3032
|
|
2973
|
-
const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATIONS_QUEUE_EXT_POINT_PREFIX='destinationsEventsQueue';
|
3033
|
+
const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATIONS_QUEUE_EXT_POINT_PREFIX='destinationsEventsQueue';const DMT_EXT_POINT_PREFIX='transformEvent';
|
2974
3034
|
|
2975
3035
|
/**
|
2976
3036
|
* Filters and returns the user supplied integrations config that should take preference over the destination specific integrations config
|
@@ -2984,7 +3044,7 @@ const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATION
|
|
2984
3044
|
* @returns Mutated event with final integrations config
|
2985
3045
|
*/const getFinalEvent=(event,state)=>{const finalEvent=clone$1(event);// Merge the destination specific integrations config with the event's integrations config
|
2986
3046
|
// In general, the preference is given to the event's integrations config
|
2987
|
-
const eventIntgConfig=event.integrations??DEFAULT_INTEGRATIONS_CONFIG;const destinationsIntgConfig=state.nativeDestinations.integrationsConfig.value;const overriddenIntgOpts=getOverriddenIntegrationOptions(eventIntgConfig,destinationsIntgConfig);finalEvent.integrations=mergeDeepRight(destinationsIntgConfig,overriddenIntgOpts);return finalEvent;};
|
3047
|
+
const eventIntgConfig=event.integrations??DEFAULT_INTEGRATIONS_CONFIG;const destinationsIntgConfig=state.nativeDestinations.integrationsConfig.value;const overriddenIntgOpts=getOverriddenIntegrationOptions(eventIntgConfig,destinationsIntgConfig);finalEvent.integrations=mergeDeepRight(destinationsIntgConfig,overriddenIntgOpts);return finalEvent;};const shouldBufferEventsForPreConsent=state=>state.consents.preConsent.value.enabled&&state.consents.preConsent.value.events?.delivery==='buffer'&&(state.consents.preConsent.value.storage?.strategy==='session'||state.consents.preConsent.value.storage?.strategy==='none');
|
2988
3048
|
|
2989
3049
|
/**
|
2990
3050
|
* Event repository class responsible for queuing events for further processing and delivery
|
@@ -2996,13 +3056,13 @@ const eventIntgConfig=event.integrations??DEFAULT_INTEGRATIONS_CONFIG;const dest
|
|
2996
3056
|
* @param logger Logger object
|
2997
3057
|
*/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);}/**
|
2998
3058
|
* Initializes the event repository
|
2999
|
-
*/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
|
3000
|
-
O(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){this.destinationsEventsQueue?.start();}});// Start the queue processing only when the destinations are ready or hybrid mode destinations exist
|
3059
|
+
*/init(){this.dataplaneEventsQueue=this.pluginsManager.invokeSingle(`${DATA_PLANE_QUEUE_EXT_POINT_PREFIX}.init`,state,this.httpClient,this.storeManager,this.errorHandler,this.logger);this.dmtEventsQueue=this.pluginsManager.invokeSingle(`${DMT_EXT_POINT_PREFIX}.init`,state,this.pluginsManager,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.dmtEventsQueue,this.errorHandler,this.logger);// Start the queue once the client destinations are ready
|
3060
|
+
O(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){this.destinationsEventsQueue?.start();this.dmtEventsQueue?.start();}});// Start the queue processing only when the destinations are ready or hybrid mode destinations exist
|
3001
3061
|
// However, events will be enqueued for now.
|
3002
3062
|
// At the time of processing the events, the integrations config data from destinations
|
3003
3063
|
// is merged into the event object
|
3004
|
-
let timeoutId;O(()=>{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?.scheduleTimeoutActive!==true){globalThis.clearTimeout(timeoutId);this.dataplaneEventsQueue?.start();}});// Force start the data plane events queue processing after a timeout
|
3005
|
-
if(state.loadOptions.value.bufferDataPlaneEventsUntilReady===true){timeoutId=globalThis.setTimeout(()=>{if(this.dataplaneEventsQueue?.scheduleTimeoutActive!==true){this.dataplaneEventsQueue?.start();}},state.loadOptions.value.dataPlaneEventsBufferTimeout);}}/**
|
3064
|
+
let timeoutId;O(()=>{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)&&!shouldBufferEventsForPreConsent(state)&&this.dataplaneEventsQueue?.scheduleTimeoutActive!==true){globalThis.clearTimeout(timeoutId);this.dataplaneEventsQueue?.start();}});// Force start the data plane events queue processing after a timeout
|
3065
|
+
if(state.loadOptions.value.bufferDataPlaneEventsUntilReady===true){timeoutId=globalThis.setTimeout(()=>{if(this.dataplaneEventsQueue?.scheduleTimeoutActive!==true){this.dataplaneEventsQueue?.start();}},state.loadOptions.value.dataPlaneEventsBufferTimeout);}}resume(){if(this.dataplaneEventsQueue?.scheduleTimeoutActive!==true){if(state.consents.postConsent.value.discardPreConsentEvents){this.dataplaneEventsQueue?.clear();this.destinationsEventsQueue?.clear();}this.dataplaneEventsQueue?.start();}}/**
|
3006
3066
|
* Enqueues the event for processing
|
3007
3067
|
* @param event RudderEvent object
|
3008
3068
|
* @param callback API callback function
|
@@ -3024,14 +3084,16 @@ callback?.(dpQEvent);}catch(error){this.onError(error,API_CALLBACK_INVOKE_ERROR)
|
|
3024
3084
|
* Start application lifecycle if not already started
|
3025
3085
|
*/load(writeKey,dataPlaneUrl,loadOptions={}){if(state.lifecycle.status.value){return;}let clonedDataPlaneUrl=clone$1(dataPlaneUrl);let clonedLoadOptions=clone$1(loadOptions);// dataPlaneUrl is not provided
|
3026
3086
|
if(isObjectAndNotNull(dataPlaneUrl)){clonedLoadOptions=dataPlaneUrl;clonedDataPlaneUrl=undefined;}// Set initial state values
|
3027
|
-
n(()=>{state.lifecycle.writeKey.value=writeKey;state.lifecycle.dataPlaneUrl.value=clonedDataPlaneUrl;state.loadOptions.value=normalizeLoadOptions(state.loadOptions.value,clonedLoadOptions);state.lifecycle.status.value='mounted';});//
|
3087
|
+
n(()=>{state.lifecycle.writeKey.value=writeKey;state.lifecycle.dataPlaneUrl.value=clonedDataPlaneUrl;state.loadOptions.value=normalizeLoadOptions(state.loadOptions.value,clonedLoadOptions);state.lifecycle.status.value='mounted';});// set log level as early as possible
|
3088
|
+
if(state.loadOptions.value.logLevel){this.logger?.setMinLogLevel(state.loadOptions.value.logLevel);}// Expose state to global objects
|
3028
3089
|
setExposedGlobal('state',state,writeKey);// Configure initial config of any services or components here
|
3029
3090
|
// State application lifecycle
|
3030
3091
|
this.startLifecycle();}// Start lifecycle methods
|
3031
3092
|
/**
|
3032
3093
|
* Orchestrate the lifecycle of the application phases/status
|
3033
3094
|
*/startLifecycle(){O(()=>{try{switch(state.lifecycle.status.value){case'mounted':this.prepareBrowserCapabilities();break;case'browserCapabilitiesReady':// initialize the preloaded events enqueuing
|
3034
|
-
retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig();break;case'configured':this.loadPlugins();break;case'pluginsLoading':break;case'pluginsReady':this.init();break;case'initialized':this.onInitialized();break;case'loaded':this.
|
3095
|
+
retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig();break;case'configured':this.loadPlugins();break;case'pluginsLoading':break;case'pluginsReady':this.init();break;case'initialized':this.onInitialized();break;case'loaded':this.onLoaded();break;case'destinationsLoading':break;case'destinationsReady':this.onDestinationsReady();break;case'ready':this.onReady();break;default:break;}}catch(err){const issue='Failed to load the SDK';this.errorHandler.onError(getMutatedError(err,issue),ANALYTICS_CORE);}});}onLoaded(){this.processBufferedEvents();// Short-circuit the life cycle and move to the ready state if pre-consent behavior is enabled
|
3096
|
+
if(state.consents.preConsent.value.enabled===true){state.lifecycle.status.value='ready';}else {this.loadDestinations();}}/**
|
3035
3097
|
* Load browser polyfill if required
|
3036
3098
|
*/prepareBrowserCapabilities(){this.capabilitiesManager.init();}/**
|
3037
3099
|
* Enqueue in SDK preload buffer events, used from preloadBuffer component
|
@@ -3039,11 +3101,11 @@ retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig
|
|
3039
3101
|
* Process the buffer preloaded events by passing their arguments to the respective facade methods
|
3040
3102
|
*/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.storeManager);this.eventRepository=new EventRepository(this.pluginsManager,this.storeManager,this.errorHandler,this.logger);this.eventManager=new EventManager(this.eventRepository,this.userSessionManager,this.errorHandler,this.logger);}/**
|
3041
3103
|
* Load configuration
|
3042
|
-
*/loadConfig(){if(
|
3104
|
+
*/loadConfig(){if(state.lifecycle.writeKey.value){this.httpClient.setAuthHeader(state.lifecycle.writeKey.value);}this.configManager?.init();}/**
|
3043
3105
|
* Initialize the storage and event queue
|
3044
3106
|
*/init(){this.errorHandler.init(this.externalSrcLoader);// Initialize storage
|
3045
|
-
this.storeManager?.init();this.userSessionManager?.init();// Initialize consent manager
|
3046
|
-
if(state.consents.
|
3107
|
+
this.storeManager?.init();this.userSessionManager?.init();// Initialize the appropriate consent manager plugin
|
3108
|
+
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager?.invokeSingle(`consentManager.init`,state,this.logger);if(state.consents.preConsent.value.enabled===false){this.pluginsManager?.invokeSingle(`consentManager.updateConsentsInfo`,state,this.storeManager,this.logger);}}// Initialize event manager
|
3047
3109
|
this.eventManager?.init();// Mark the SDK as initialized
|
3048
3110
|
state.lifecycle.status.value='initialized';}/**
|
3049
3111
|
* Load plugins
|
@@ -3060,19 +3122,21 @@ n(()=>{state.lifecycle.loaded.value=true;state.lifecycle.status.value='loaded';}
|
|
3060
3122
|
const initializedEvent=new CustomEvent('RSA_Initialised',{detail:{analyticsInstance:globalThis.rudderanalytics},bubbles:true,cancelable:true,composed:true});globalThis.document.dispatchEvent(initializedEvent);}/**
|
3061
3123
|
* Emit ready event
|
3062
3124
|
*/ // eslint-disable-next-line class-methods-use-this
|
3063
|
-
onReady(){
|
3125
|
+
onReady(){state.eventBuffer.readyCallbacksArray.value.forEach(callback=>{try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}});// Emit an event to use as substitute to the ready callback
|
3064
3126
|
const readyEvent=new CustomEvent('RSA_Ready',{detail:{analyticsInstance:globalThis.rudderanalytics},bubbles:true,cancelable:true,composed:true});globalThis.document.dispatchEvent(readyEvent);}/**
|
3065
3127
|
* Consume preloaded events buffer
|
3066
3128
|
*/processBufferedEvents(){// Process buffered events
|
3067
3129
|
state.eventBuffer.toBeProcessedArray.value.forEach(bufferedItem=>{const methodName=bufferedItem[0];if(isFunction(this[methodName])){this[methodName](...bufferedItem.slice(1));}});state.eventBuffer.toBeProcessedArray.value=[];}/**
|
3068
3130
|
* Load device mode destinations
|
3069
|
-
*/loadDestinations(){// Set in state the desired activeDestinations to inject in DOM
|
3131
|
+
*/loadDestinations(){if(state.nativeDestinations.clientDestinationsReady.value){return;}// Set in state the desired activeDestinations to inject in DOM
|
3070
3132
|
this.pluginsManager?.invokeSingle('nativeDestinations.setActiveDestinations',state,this.pluginsManager,this.errorHandler,this.logger);const totalDestinationsToLoad=state.nativeDestinations.activeDestinations.value.length;if(totalDestinationsToLoad===0){state.lifecycle.status.value='destinationsReady';return;}// Start loading native integration scripts and create instances
|
3071
3133
|
state.lifecycle.status.value='destinationsLoading';this.pluginsManager?.invokeSingle('nativeDestinations.load',state,this.externalSrcLoader,this.errorHandler,this.logger);// Progress to next lifecycle phase if all native destinations are initialized or failed
|
3072
3134
|
O(()=>{const areAllDestinationsReady=totalDestinationsToLoad===0||state.nativeDestinations.initializedDestinations.value.length+state.nativeDestinations.failedDestinations.value.length===totalDestinationsToLoad;if(areAllDestinationsReady){n(()=>{state.lifecycle.status.value='destinationsReady';state.nativeDestinations.clientDestinationsReady.value=true;});}});}/**
|
3073
|
-
*
|
3135
|
+
* Move to the ready state
|
3074
3136
|
*/ // eslint-disable-next-line class-methods-use-this
|
3075
|
-
onDestinationsReady(){
|
3137
|
+
onDestinationsReady(){// May be do any destination specific actions here
|
3138
|
+
// Mark the ready status if not already done
|
3139
|
+
if(state.lifecycle.status.value!=='ready'){state.lifecycle.status.value='ready';}}// End lifecycle methods
|
3076
3140
|
// Start consumer exposed methods
|
3077
3141
|
ready(callback){const type='ready';this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,callback]);return;}if(!isFunction(callback)){this.logger.error(READY_API_CALLBACK_ERROR(READY_API));return;}/**
|
3078
3142
|
* If destinations are loaded or no integration is available for loading
|
@@ -3091,7 +3155,13 @@ getUserId(){return state.session.userId.value;}// eslint-disable-next-line class
|
|
3091
3155
|
getUserTraits(){return state.session.userTraits.value;}// eslint-disable-next-line class-methods-use-this
|
3092
3156
|
getGroupId(){return state.session.groupId.value;}// eslint-disable-next-line class-methods-use-this
|
3093
3157
|
getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId){const type='startSession';this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type,sessionId]);return;}this.userSessionManager?.start(sessionId);}endSession(){const type='endSession';this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value.push([type]);return;}this.userSessionManager?.end();}// eslint-disable-next-line class-methods-use-this
|
3094
|
-
getSessionId(){const sessionId=this.userSessionManager?.getSessionId();return sessionId??null;}
|
3158
|
+
getSessionId(){const sessionId=this.userSessionManager?.getSessionId();return sessionId??null;}consent(options){this.errorHandler.leaveBreadcrumb(`New consent invocation`);n(()=>{state.consents.preConsent.value={...state.consents.preConsent.value,enabled:false};state.consents.postConsent.value=getValidPostConsentOptions(options);const{initialized,consentsData}=getConsentManagementData(state.consents.postConsent.value.consentManagement,this.logger);state.consents.initialized.value=initialized||state.consents.initialized.value;state.consents.data.value=consentsData;});// Update consents data in state
|
3159
|
+
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager?.invokeSingle(`consentManager.updateConsentsInfo`,state,this.storeManager,this.logger);}// TODO: Re-init store manager
|
3160
|
+
// this.storeManager?.initClientDataStores();
|
3161
|
+
// TODO: Re-init user session manager
|
3162
|
+
// this.userSessionManager?.syncStorageDataToState();
|
3163
|
+
// Resume event manager to process the events to destinations
|
3164
|
+
this.eventManager?.resume();this.loadDestinations();}setAuthToken(token){this.userSessionManager?.setAuthToken(token);}// End consumer exposed methods
|
3095
3165
|
}
|
3096
3166
|
|
3097
3167
|
/*
|
@@ -3103,7 +3173,7 @@ getSessionId(){const sessionId=this.userSessionManager?.getSessionId();return se
|
|
3103
3173
|
constructor(){if(RudderAnalytics.globalSingleton){// START-NO-SONAR-SCAN
|
3104
3174
|
// eslint-disable-next-line no-constructor-return
|
3105
3175
|
return RudderAnalytics.globalSingleton;// END-NO-SONAR-SCAN
|
3106
|
-
}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
|
3176
|
+
}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);this.setAuthToken=this.setAuthToken.bind(this);this.consent=this.consent.bind(this);RudderAnalytics.globalSingleton=this;// get the preloaded events before replacing global object
|
3107
3177
|
this.getPreloadBuffer();// start loading if a load event was buffered or wait for explicit load call
|
3108
3178
|
this.triggerBufferedLoadEvent();}/**
|
3109
3179
|
* Set instance to use if no specific writeKey is provided in methods
|
@@ -3136,6 +3206,6 @@ this.load.apply(null,loadEvent);}}/**
|
|
3136
3206
|
* Process alias arguments and forward to page call
|
3137
3207
|
*/alias(to,from,options,callback){this.getAnalyticsInstance().alias(aliasArgumentsToCallOptions(to,from,options,callback));}/**
|
3138
3208
|
* Process group arguments and forward to page call
|
3139
|
-
*/group(groupId,traits,options,callback){if(arguments.length===0){this.logger.error(EMPTY_GROUP_CALL_ERROR(RS_APP));return;}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();}}
|
3209
|
+
*/group(groupId,traits,options,callback){if(arguments.length===0){this.logger.error(EMPTY_GROUP_CALL_ERROR(RS_APP));return;}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();}setAuthToken(token){return this.getAnalyticsInstance().setAuthToken(token);}consent(options){return this.getAnalyticsInstance().consent(options);}}
|
3140
3210
|
|
3141
3211
|
export { RudderAnalytics };
|