@rudderstack/analytics-js 3.34.3 → 3.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/npm/index.d.cts +5 -2
- package/dist/npm/index.d.mts +5 -2
- package/dist/npm/legacy/bundled/cjs/index.cjs +94 -48
- package/dist/npm/legacy/bundled/esm/index.mjs +94 -48
- package/dist/npm/legacy/bundled/umd/index.js +94 -48
- package/dist/npm/legacy/cjs/index.cjs +94 -48
- package/dist/npm/legacy/content-script/cjs/index.cjs +92 -47
- package/dist/npm/legacy/content-script/esm/index.mjs +92 -47
- package/dist/npm/legacy/content-script/umd/index.js +92 -47
- package/dist/npm/legacy/esm/index.mjs +94 -48
- package/dist/npm/legacy/lite/cjs/index.cjs +94 -48
- package/dist/npm/legacy/lite/esm/index.mjs +94 -48
- package/dist/npm/legacy/lite/umd/index.js +94 -48
- package/dist/npm/legacy/umd/index.js +94 -48
- package/dist/npm/modern/bundled/cjs/index.cjs +398 -310
- package/dist/npm/modern/bundled/esm/index.mjs +398 -310
- package/dist/npm/modern/bundled/umd/index.js +398 -310
- package/dist/npm/modern/cjs/index.cjs +295 -212
- package/dist/npm/modern/content-script/cjs/index.cjs +398 -310
- package/dist/npm/modern/content-script/esm/index.mjs +398 -310
- package/dist/npm/modern/content-script/umd/index.js +398 -310
- package/dist/npm/modern/esm/index.mjs +295 -212
- package/dist/npm/modern/lite/cjs/index.cjs +369 -281
- package/dist/npm/modern/lite/esm/index.mjs +369 -281
- package/dist/npm/modern/lite/umd/index.js +369 -281
- package/dist/npm/modern/umd/index.js +295 -212
- package/package.json +1 -1
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
function _defineProperty(e, r, t) {
|
|
2
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
3
|
+
value: t,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
}) : e[r] = t, e;
|
|
8
|
+
}
|
|
9
|
+
function ownKeys(e, r) {
|
|
10
|
+
var t = Object.keys(e);
|
|
11
|
+
if (Object.getOwnPropertySymbols) {
|
|
12
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
13
|
+
r && (o = o.filter(function (r) {
|
|
14
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
15
|
+
})), t.push.apply(t, o);
|
|
16
|
+
}
|
|
17
|
+
return t;
|
|
18
|
+
}
|
|
19
|
+
function _objectSpread2(e) {
|
|
20
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
21
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
22
|
+
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
|
|
23
|
+
_defineProperty(e, r, t[r]);
|
|
24
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
25
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return e;
|
|
29
|
+
}
|
|
30
|
+
function _objectWithoutProperties(e, t) {
|
|
31
|
+
if (null == e) return {};
|
|
32
|
+
var o,
|
|
33
|
+
r,
|
|
34
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
35
|
+
if (Object.getOwnPropertySymbols) {
|
|
36
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
37
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
38
|
+
}
|
|
39
|
+
return i;
|
|
40
|
+
}
|
|
41
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
42
|
+
if (null == r) return {};
|
|
43
|
+
var t = {};
|
|
44
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
45
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
46
|
+
t[n] = r[n];
|
|
47
|
+
}
|
|
48
|
+
return t;
|
|
49
|
+
}
|
|
50
|
+
function _toPrimitive(t, r) {
|
|
51
|
+
if ("object" != typeof t || !t) return t;
|
|
52
|
+
var e = t[Symbol.toPrimitive];
|
|
53
|
+
if (void 0 !== e) {
|
|
54
|
+
var i = e.call(t, r);
|
|
55
|
+
if ("object" != typeof i) return i;
|
|
56
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
57
|
+
}
|
|
58
|
+
return ("string" === r ? String : Number)(t);
|
|
59
|
+
}
|
|
60
|
+
function _toPropertyKey(t) {
|
|
61
|
+
var i = _toPrimitive(t, "string");
|
|
62
|
+
return "symbol" == typeof i ? i : i + "";
|
|
63
|
+
}
|
|
64
|
+
|
|
1
65
|
function _isPlaceholder(a){return a!=null&&typeof a==='object'&&a['@@functional/placeholder']===true;}
|
|
2
66
|
|
|
3
67
|
/**
|
|
@@ -379,7 +443,7 @@ if(isString(category)&&!isString(name)){payload.category=undefined;payload.name=
|
|
|
379
443
|
// and set some proper defaults
|
|
380
444
|
// Also, to clone the incoming object type arguments
|
|
381
445
|
if(!isDefined(payload.category)){payload.category=undefined;}if(!isDefined(payload.name)){payload.name=undefined;}payload.properties=payload.properties?clone(payload.properties):{};if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}const nameForProperties=isString(payload.name)?payload.name:payload.properties.name;const categoryForProperties=isString(payload.category)?payload.category:payload.properties.category;// add name and category to properties
|
|
382
|
-
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{
|
|
446
|
+
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},_objectSpread2(_objectSpread2({},nameForProperties&&{name:nameForProperties}),categoryForProperties&&{category:categoryForProperties}));return payload;};/*
|
|
383
447
|
* Normalise the overloaded arguments of the track call facade
|
|
384
448
|
*/const trackArgumentsToCallOptions=(event,properties,options,callback)=>{const payload={name:event,properties:properties,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.properties=properties;payload.options=undefined;payload.callback=options;}if(isFunction(properties)){payload.properties=undefined;payload.options=undefined;payload.callback=properties;}// Rest of the code is just to clean up undefined values
|
|
385
449
|
// and set some proper defaults
|
|
@@ -436,7 +500,7 @@ const generateUUID=()=>{if(hasCrypto$1()){return v4$1();}return v4();};
|
|
|
436
500
|
/**
|
|
437
501
|
* Determines if the SDK is running inside a chrome extension
|
|
438
502
|
* @returns boolean
|
|
439
|
-
*/const isSDKRunningInChromeExtension=()
|
|
503
|
+
*/const isSDKRunningInChromeExtension=()=>{var _chrome;return !!((_chrome=window.chrome)!==null&&_chrome!==void 0&&(_chrome=_chrome.runtime)!==null&&_chrome!==void 0&&_chrome.id);};const isIE11=()=>isString(globalThis.navigator.userAgent)&&/Trident.*rv:11\./.test(globalThis.navigator.userAgent);
|
|
440
504
|
|
|
441
505
|
/**
|
|
442
506
|
* Registers events to detect page leave scenarios
|
|
@@ -470,25 +534,25 @@ const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A scrip
|
|
|
470
534
|
|
|
471
535
|
const JSON_STRINGIFY='JSONStringify';const JSON_UTIL='JSON';const BIG_INT_PLACEHOLDER='[BigInt]';const CIRCULAR_REFERENCE_PLACEHOLDER='[Circular Reference]';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
|
472
536
|
// eslint-disable-next-line func-names
|
|
473
|
-
return function(key,value){if(excludeKeys
|
|
537
|
+
return function(key,value){if(excludeKeys!==null&&excludeKeys!==void 0&&excludeKeys.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
|
474
538
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
475
539
|
// @ts-ignore-next-line
|
|
476
|
-
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger
|
|
540
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger===null||logger===void 0||logger.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return CIRCULAR_REFERENCE_PLACEHOLDER;}ancestors.push(value);return value;};};/**
|
|
477
541
|
* Utility method for JSON stringify object excluding null values & circular references
|
|
478
542
|
*
|
|
479
543
|
* @param {*} value input
|
|
480
544
|
* @param {boolean} excludeNull if it should exclude nul or not
|
|
481
545
|
* @param {function} logger optional logger methods for warning
|
|
482
546
|
* @returns string
|
|
483
|
-
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger
|
|
547
|
+
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger===null||logger===void 0||logger.warn(JSON_STRINGIFY_WARNING,err);return null;}};const getReplacer=logger=>{const ancestors=[];// Array to track ancestor objects
|
|
484
548
|
// Using a regular function to use `this` for the parent context
|
|
485
|
-
return function replacer(key,value){if(isBigInt(value)){logger
|
|
549
|
+
return function replacer(key,value){if(isBigInt(value)){logger===null||logger===void 0||logger.warn(BAD_DATA_WARNING(JSON_UTIL,key));return BIG_INT_PLACEHOLDER;// Replace BigInt values
|
|
486
550
|
}// `this` is the object that value is contained in, i.e., its direct parent.
|
|
487
551
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
488
552
|
// @ts-ignore-next-line
|
|
489
553
|
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();// Remove ancestors that are no longer part of the chain
|
|
490
554
|
}// Check for circular references (if the value is already in the ancestors)
|
|
491
|
-
if(ancestors.includes(value)){logger
|
|
555
|
+
if(ancestors.includes(value)){logger===null||logger===void 0||logger.warn(BAD_DATA_WARNING(JSON_UTIL,key));return CIRCULAR_REFERENCE_PLACEHOLDER;}// Add current value to ancestors
|
|
492
556
|
ancestors.push(value);return value;};};const traverseWithThis=(obj,replacer)=>{// Create a new result object or array
|
|
493
557
|
const result=Array.isArray(obj)?[]:{};// Traverse object properties or array elements
|
|
494
558
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -511,11 +575,11 @@ const MANUAL_ERROR_IDENTIFIER='[SDK DISPATCHED ERROR]';const getStacktrace=err=>
|
|
|
511
575
|
*/const getMutatedError=(err,issue)=>{if(!isTypeOfError(err)){return new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}try{// Preserve the specific error type (TypeError, ReferenceError, etc.)
|
|
512
576
|
const ErrorConstructor=err.constructor;const newError=new ErrorConstructor(`${issue}: ${err.message}`);// Preserve stack trace
|
|
513
577
|
const stack=getStacktrace(err);if(stack){newError.stack=stack;}// Preserve any other enumerable properties
|
|
514
|
-
Object.getOwnPropertyNames(err).forEach(key=>{if(key!=='message'&&key!=='stack'&&key!=='name'){try{newError[key]=err[key];}catch{// Ignore if property is not writable
|
|
515
|
-
}}});return newError;}catch{return new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}};const dispatchErrorEvent=error=>{if(isTypeOfError(error)){const errStack=getStacktrace(error);if(errStack){// eslint-disable-next-line no-param-reassign
|
|
578
|
+
Object.getOwnPropertyNames(err).forEach(key=>{if(key!=='message'&&key!=='stack'&&key!=='name'){try{newError[key]=err[key];}catch(_unused){// Ignore if property is not writable
|
|
579
|
+
}}});return newError;}catch(_unused2){return new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}};const dispatchErrorEvent=error=>{if(isTypeOfError(error)){const errStack=getStacktrace(error);if(errStack){// eslint-disable-next-line no-param-reassign
|
|
516
580
|
error.stack=`${errStack}\n${MANUAL_ERROR_IDENTIFIER}`;}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
|
|
517
581
|
|
|
518
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.
|
|
582
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.35.1';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const BUILD_VARIANT='lite';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';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
|
|
519
583
|
|
|
520
584
|
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';
|
|
521
585
|
|
|
@@ -583,10 +647,10 @@ const EXTERNAL_SOURCE_LOAD_ORIGIN='RS_JS_SDK';
|
|
|
583
647
|
* @param {*} newScriptElement the script element to add
|
|
584
648
|
*
|
|
585
649
|
* @returns
|
|
586
|
-
*/const insertScript=newScriptElement=>{
|
|
587
|
-
const headElements=document.getElementsByTagName('head');if(headElements.length>0){headElements[0]
|
|
588
|
-
const scriptElements=document.getElementsByTagName('script');if(scriptElements.length>0&&scriptElements[0]
|
|
589
|
-
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement
|
|
650
|
+
*/const insertScript=newScriptElement=>{var _scriptElements$;// First try to add it to the head
|
|
651
|
+
const headElements=document.getElementsByTagName('head');if(headElements.length>0){var _headElements$,_headElements$2;(_headElements$=headElements[0])===null||_headElements$===void 0||_headElements$.insertBefore(newScriptElement,(_headElements$2=headElements[0])===null||_headElements$2===void 0?void 0:_headElements$2.firstChild);return;}// Else wise add it before the first script tag
|
|
652
|
+
const scriptElements=document.getElementsByTagName('script');if(scriptElements.length>0&&(_scriptElements$=scriptElements[0])!==null&&_scriptElements$!==void 0&&_scriptElements$.parentNode){var _scriptElements$2;(_scriptElements$2=scriptElements[0])===null||_scriptElements$2===void 0||_scriptElements$2.parentNode.insertBefore(newScriptElement,scriptElements[0]);return;}// Create a new head element and add the script as fallback
|
|
653
|
+
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement===null||htmlElement===void 0||htmlElement.insertBefore(headElement,htmlElement.firstChild);};/**
|
|
590
654
|
* Loads external js file as a script html tag
|
|
591
655
|
*
|
|
592
656
|
* @param {*} url The URL of the script to be loaded
|
|
@@ -614,7 +678,7 @@ var i=Symbol.for("preact-signals");function t(){if(!(v>1)){var i,t=false;!functi
|
|
|
614
678
|
|
|
615
679
|
const LOG_LEVEL_MAP={LOG:0,INFO:1,DEBUG:2,WARN:3,ERROR:4,NONE:5};const DEFAULT_LOG_LEVEL='LOG';const POST_LOAD_LOG_LEVEL='ERROR';const LOG_MSG_PREFIX='RS SDK';const LOG_MSG_PREFIX_STYLE='font-weight: bold; background: black; color: white;';const LOG_MSG_STYLE='font-weight: normal;';/**
|
|
616
680
|
* Service to log messages/data to output provider, default is console
|
|
617
|
-
*/class Logger{constructor(minLogLevel=DEFAULT_LOG_LEVEL,scope='',logProvider=console){this.minLogLevel=LOG_LEVEL_MAP[minLogLevel];this.scope=scope;this.logProvider=logProvider;}log(...data){this.outputLog('LOG',data);}info(...data){this.outputLog('INFO',data);}debug(...data){this.outputLog('DEBUG',data);}warn(...data){this.outputLog('WARN',data);}error(...data){this.outputLog('ERROR',data);}outputLog(logMethod,data){if(this.minLogLevel<=LOG_LEVEL_MAP[logMethod]){this.logProvider[logMethod.toLowerCase()]
|
|
681
|
+
*/class Logger{constructor(minLogLevel=DEFAULT_LOG_LEVEL,scope='',logProvider=console){this.minLogLevel=LOG_LEVEL_MAP[minLogLevel];this.scope=scope;this.logProvider=logProvider;}log(...data){this.outputLog('LOG',data);}info(...data){this.outputLog('INFO',data);}debug(...data){this.outputLog('DEBUG',data);}warn(...data){this.outputLog('WARN',data);}error(...data){this.outputLog('ERROR',data);}outputLog(logMethod,data){if(this.minLogLevel<=LOG_LEVEL_MAP[logMethod]){var _this$logProvider,_this$logProvider2;(_this$logProvider=(_this$logProvider2=this.logProvider)[logMethod.toLowerCase()])===null||_this$logProvider===void 0||_this$logProvider.call(_this$logProvider2,...this.formatLogData(data));}}setScope(scopeVal){this.scope=scopeVal||this.scope;}// TODO: should we allow to change the level via global variable on run time
|
|
618
682
|
// to assist on the fly debugging?
|
|
619
683
|
setMinLogLevel(logLevel){this.minLogLevel=LOG_LEVEL_MAP[logLevel];if(isUndefined(this.minLogLevel)){this.minLogLevel=LOG_LEVEL_MAP[DEFAULT_LOG_LEVEL];}}/**
|
|
620
684
|
* Formats the console message using `scope` and styles
|
|
@@ -635,7 +699,7 @@ const SUPPORTED_STORAGE_TYPES=['localStorage','memoryStorage','cookieStorage','s
|
|
|
635
699
|
|
|
636
700
|
const SOURCE_CONFIG_RESOLUTION_ERROR=`Unable to process/parse source configuration response`;const SOURCE_DISABLED_ERROR=`The source is disabled. Please enable the source in the dashboard to send events.`;const XHR_PAYLOAD_PREP_ERROR=`Failed to prepare data for the request.`;const PLUGIN_EXT_POINT_MISSING_ERROR=`Failed to invoke plugin because the extension point name is missing.`;const PLUGIN_EXT_POINT_INVALID_ERROR=`Failed to invoke plugin because the extension point name is invalid.`;const SOURCE_CONFIG_OPTION_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}The "getSourceConfig" load API option must be a function that returns valid source configuration data.`;const COMPONENT_BASE_URL_ERROR=(context,component,url)=>`${context}${LOG_CONTEXT_SEPARATOR}The base URL "${url}" for ${component} is not valid.`;// ERROR
|
|
637
701
|
const UNSUPPORTED_CONSENT_MANAGER_ERROR=(context,selectedConsentManager,consentManagersToPluginNameMap)=>`${context}${LOG_CONTEXT_SEPARATOR}The consent manager "${selectedConsentManager}" is not supported. Please choose one of the following supported consent managers: "${Object.keys(consentManagersToPluginNameMap)}".`;const NON_ERROR_WARNING=(context,errStr)=>`${context}${LOG_CONTEXT_SEPARATOR}Ignoring a non-error: ${errStr}.`;const BREADCRUMB_ERROR=`Failed to log breadcrumb`;const HANDLE_ERROR_FAILURE=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to handle the error.`;const PLUGIN_NAME_MISSING_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin name is missing.`;const PLUGIN_ALREADY_EXISTS_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" already exists.`;const PLUGIN_NOT_FOUND_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" not found.`;const PLUGIN_ENGINE_BUG_ERROR=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" not found in plugins but found in byName. This indicates a bug in the plugin engine. Please report this issue to the development team.`;const PLUGIN_DEPS_ERROR=(context,pluginName,notExistDeps)=>`${context}${LOG_CONTEXT_SEPARATOR}Plugin "${pluginName}" could not be loaded because some of its dependencies "${notExistDeps}" do not exist.`;const PLUGIN_INVOCATION_ERROR=(context,extPoint,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to invoke the "${extPoint}" extension point of plugin "${pluginName}".`;const SOURCE_CONFIG_FETCH_ERROR='Failed to fetch the source config';const WRITE_KEY_VALIDATION_ERROR=(context,writeKey)=>`${context}${LOG_CONTEXT_SEPARATOR}The write key "${writeKey}" is invalid. It must be a non-empty string. Please check that the write key is correct and try again.`;const DATA_PLANE_URL_VALIDATION_ERROR=(context,dataPlaneUrl)=>`${context}${LOG_CONTEXT_SEPARATOR}The data plane URL "${dataPlaneUrl}" is invalid. It must be a valid URL string. Please check that the data plane URL is correct and try again.`;const INVALID_CALLBACK_FN_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}The provided callback parameter is not a function.`;const XHR_DELIVERY_ERROR=(prefix,status,statusText,url,response)=>`${prefix} with status ${status} (${statusText}) for URL: ${url}. Response: ${response.trim()}`;const XHR_REQUEST_ERROR=(prefix,e,url)=>`${prefix} due to timeout or no connection (${e?e.type:''}) at the client side for URL: ${url}`;const XHR_SEND_ERROR=(prefix,url)=>`${prefix} for URL: ${url}`;const STORE_DATA_SAVE_ERROR=key=>`Failed to save the value for "${key}" to storage`;const STORE_DATA_FETCH_ERROR=key=>`Failed to retrieve or parse data for "${key}" from storage`;const DATA_SERVER_URL_INVALID_ERROR=(context,url)=>`${context}${LOG_CONTEXT_SEPARATOR}The server side cookies functionality is disabled as the provided data server URL, "${url}" is invalid.`;const DATA_SERVER_REQUEST_FAIL_ERROR=status=>`The server responded with status ${status} while setting the cookies. As a fallback, the cookies will be set client side.`;const FAILED_SETTING_COOKIE_FROM_SERVER_ERROR=key=>`The server failed to set the ${key} cookie. As a fallback, the cookies will be set client side.`;const FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR=`Failed to set/remove cookies via server. As a fallback, the cookies will be managed client side.`;const COLLAPSED_COOKIE_BATCH_ERROR=(missingCookies,batchSize)=>`The server did not set ${missingCookies.length} of the ${batchSize} cookies sent in one request: ${missingCookies.join(', ')}. A fallback to set them client side was attempted. Check that the data service and any proxy preserve every "Set-Cookie" header, and that the cookie domain and SameSite/Secure attributes are valid.`;// WARNING
|
|
638
|
-
const STORAGE_TYPE_VALIDATION_WARNING=(context,storageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${storageType}" is not supported. Please choose one of the following supported types: "${SUPPORTED_STORAGE_TYPES}". The default storage type will be used instead.`;const UNSUPPORTED_STORAGE_ENTRY_TYPE_WARNING=(context,entry,storageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${storageType}" configured for the entry "${entry}" is not supported. Please choose one of the following supported types: "${SUPPORTED_STORAGE_TYPES}". The default storage type will be used instead.`;const UNSUPPORTED_STORAGE_ENCRYPTION_VERSION_WARNING=(context,selectedStorageEncryptionVersion,storageEncryptionVersionsToPluginNameMap,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage encryption version "${selectedStorageEncryptionVersion}" is not supported. Please choose one of the following supported versions: "${Object.keys(storageEncryptionVersionsToPluginNameMap)}". The default version "${defaultVersion}" will be used instead.`;const STORAGE_DATA_MIGRATION_OVERRIDE_WARNING=(context,storageEncryptionVersion,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage data migration has been disabled because the configured storage encryption version (${storageEncryptionVersion}) is not the latest (${defaultVersion}). To enable storage data migration, please update the storage encryption version to the latest version.`;const SERVER_SIDE_COOKIE_FEATURE_OVERRIDE_ERROR=(context,providedCookieDomain,currentCookieDomain)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided cookie domain (${providedCookieDomain}) does not match the current webpage's domain (${currentCookieDomain}). Hence, the cookies will be set client-side.`;const SERVER_SIDE_COOKIE_DATA_SERVICE_HOST_ERROR=(context,dataServiceHost,webpageHost)=>`${context}${LOG_CONTEXT_SEPARATOR}The data service host (${dataServiceHost}) cannot set cookies for the current webpage (${webpageHost}). Hence, the cookies will be set client-side instead of server-side.`;const RESERVED_KEYWORD_WARNING=(context,property,parentKeyPath,reservedElements)=>`${context}${LOG_CONTEXT_SEPARATOR}The "${property}" property defined under "${parentKeyPath}" is a reserved keyword. Please choose a different property name to avoid conflicts with reserved keywords (${reservedElements}).`;const RESERVED_CUSTOM_CONTEXT_KEY_WARNING=(logContext,property)=>`${logContext}${LOG_CONTEXT_SEPARATOR}The top-level custom context property "${property}" is reserved and was ignored.`;const INVALID_CONTEXT_OBJECT_WARNING=logContext=>`${logContext}${LOG_CONTEXT_SEPARATOR}Please make sure that the "context" property in the event API's "options" argument is a valid object literal with key-value pairs.`;const INVALID_CUSTOM_CONTEXT_WARNING=logContext=>`${logContext}${LOG_CONTEXT_SEPARATOR}Invalid custom context. Use a plain object without prototype pollution keys.`;const UNSUPPORTED_BEACON_API_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The Beacon API is not supported by your browser. The events will be sent using XHR instead.`;const TIMEOUT_NOT_NUMBER_WARNING=(context,timeout,defaultValue)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value "${timeout}" is not a number. The default timeout of ${defaultValue} ms will be used instead.`;const CUT_OFF_DURATION_NOT_NUMBER_WARNING=(context,cutOffDuration,defaultValue)=>`${context}${LOG_CONTEXT_SEPARATOR}The session cut off duration value "${cutOffDuration}" is not a number. The default cut off duration of ${defaultValue} ms will be used instead.`;const CUT_OFF_DURATION_LESS_THAN_TIMEOUT_WARNING=(context,cutOffDuration,timeout)=>`${context}${LOG_CONTEXT_SEPARATOR}The session cut off duration value "${cutOffDuration}" ms is less than the session timeout value "${timeout}" ms. The cut off functionality will be disabled.`;const TIMEOUT_ZERO_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value is 0, which disables the automatic session tracking feature. If you want to enable session tracking, please provide a positive integer value for the timeout.`;const TIMEOUT_NOT_RECOMMENDED_WARNING=(context,timeout,minTimeout)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value ${timeout} ms is less than the recommended minimum of ${minTimeout} ms. Please consider increasing the timeout value to ensure optimal performance and reliability.`;const INVALID_SESSION_ID_WARNING=(context,sessionId,minSessionIdLength)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided session ID (${sessionId}) is either invalid, not a positive integer, or not at least "${minSessionIdLength}" digits long. A new session ID will be auto-generated instead.`;const STORAGE_QUOTA_EXCEEDED_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The storage is either full or unavailable, so the data will not be persisted. Switching to in-memory storage.`;const STORAGE_UNAVAILABLE_WARNING=(context,entry,selectedStorageType,finalStorageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${selectedStorageType}" is not available for entry "${entry}". The SDK will initialize the entry with "${finalStorageType}" storage type instead.`;const CALLBACK_INVOKE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}The callback threw an exception`;const INVALID_CONFIG_URL_WARNING=(context,configUrl)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided source config URL "${configUrl}" is invalid. Using the default source config URL instead.`;const
|
|
702
|
+
const STORAGE_TYPE_VALIDATION_WARNING=(context,storageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${storageType}" is not supported. Please choose one of the following supported types: "${SUPPORTED_STORAGE_TYPES}". The default storage type will be used instead.`;const UNSUPPORTED_STORAGE_ENTRY_TYPE_WARNING=(context,entry,storageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${storageType}" configured for the entry "${entry}" is not supported. Please choose one of the following supported types: "${SUPPORTED_STORAGE_TYPES}". The default storage type will be used instead.`;const UNSUPPORTED_STORAGE_ENCRYPTION_VERSION_WARNING=(context,selectedStorageEncryptionVersion,storageEncryptionVersionsToPluginNameMap,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage encryption version "${selectedStorageEncryptionVersion}" is not supported. Please choose one of the following supported versions: "${Object.keys(storageEncryptionVersionsToPluginNameMap)}". The default version "${defaultVersion}" will be used instead.`;const STORAGE_DATA_MIGRATION_OVERRIDE_WARNING=(context,storageEncryptionVersion,defaultVersion)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage data migration has been disabled because the configured storage encryption version (${storageEncryptionVersion}) is not the latest (${defaultVersion}). To enable storage data migration, please update the storage encryption version to the latest version.`;const SERVER_SIDE_COOKIE_FEATURE_OVERRIDE_ERROR=(context,providedCookieDomain,currentCookieDomain)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided cookie domain (${providedCookieDomain}) does not match the current webpage's domain (${currentCookieDomain}). Hence, the cookies will be set client-side.`;const SERVER_SIDE_COOKIE_DATA_SERVICE_HOST_ERROR=(context,dataServiceHost,webpageHost)=>`${context}${LOG_CONTEXT_SEPARATOR}The data service host (${dataServiceHost}) cannot set cookies for the current webpage (${webpageHost}). Hence, the cookies will be set client-side instead of server-side.`;const RESERVED_KEYWORD_WARNING=(context,property,parentKeyPath,reservedElements)=>`${context}${LOG_CONTEXT_SEPARATOR}The "${property}" property defined under "${parentKeyPath}" is a reserved keyword. Please choose a different property name to avoid conflicts with reserved keywords (${reservedElements}).`;const RESERVED_CUSTOM_CONTEXT_KEY_WARNING=(logContext,property)=>`${logContext}${LOG_CONTEXT_SEPARATOR}The top-level custom context property "${property}" is reserved and was ignored.`;const INVALID_CONTEXT_OBJECT_WARNING=logContext=>`${logContext}${LOG_CONTEXT_SEPARATOR}Please make sure that the "context" property in the event API's "options" argument is a valid object literal with key-value pairs.`;const INVALID_CUSTOM_CONTEXT_WARNING=logContext=>`${logContext}${LOG_CONTEXT_SEPARATOR}Invalid custom context. Use a plain object without prototype pollution keys.`;const UNSUPPORTED_BEACON_API_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The Beacon API is not supported by your browser. The events will be sent using XHR instead.`;const TIMEOUT_NOT_NUMBER_WARNING=(context,timeout,defaultValue)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value "${timeout}" is not a number. The default timeout of ${defaultValue} ms will be used instead.`;const CUT_OFF_DURATION_NOT_NUMBER_WARNING=(context,cutOffDuration,defaultValue)=>`${context}${LOG_CONTEXT_SEPARATOR}The session cut off duration value "${cutOffDuration}" is not a number. The default cut off duration of ${defaultValue} ms will be used instead.`;const CUT_OFF_DURATION_LESS_THAN_TIMEOUT_WARNING=(context,cutOffDuration,timeout)=>`${context}${LOG_CONTEXT_SEPARATOR}The session cut off duration value "${cutOffDuration}" ms is less than the session timeout value "${timeout}" ms. The cut off functionality will be disabled.`;const TIMEOUT_ZERO_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value is 0, which disables the automatic session tracking feature. If you want to enable session tracking, please provide a positive integer value for the timeout.`;const TIMEOUT_NOT_RECOMMENDED_WARNING=(context,timeout,minTimeout)=>`${context}${LOG_CONTEXT_SEPARATOR}The session timeout value ${timeout} ms is less than the recommended minimum of ${minTimeout} ms. Please consider increasing the timeout value to ensure optimal performance and reliability.`;const INVALID_SESSION_ID_WARNING=(context,sessionId,minSessionIdLength)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided session ID (${sessionId}) is either invalid, not a positive integer, or not at least "${minSessionIdLength}" digits long. A new session ID will be auto-generated instead.`;const STORAGE_QUOTA_EXCEEDED_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}The storage is either full or unavailable, so the data will not be persisted. Switching to in-memory storage.`;const STORAGE_UNAVAILABLE_WARNING=(context,entry,selectedStorageType,finalStorageType)=>`${context}${LOG_CONTEXT_SEPARATOR}The storage type "${selectedStorageType}" is not available for entry "${entry}". The SDK will initialize the entry with "${finalStorageType}" storage type instead.`;const CALLBACK_INVOKE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}The callback threw an exception`;const INVALID_CONFIG_URL_WARNING=(context,configUrl)=>`${context}${LOG_CONTEXT_SEPARATOR}The provided source config URL "${configUrl}" is invalid. Using the default source config URL instead.`;const UNSUPPORTED_PRE_CONSENT_STORAGE_STRATEGY=(context,selectedStrategy,defaultStrategy)=>`${context}${LOG_CONTEXT_SEPARATOR}The pre-consent storage strategy "${selectedStrategy}" is not supported. Please choose one of the following supported strategies: "none, session, anonymousId". The default strategy "${defaultStrategy}" will be used instead.`;const DEPRECATED_PRE_CONSENT_STORAGE_STRATEGY=context=>`${context}${LOG_CONTEXT_SEPARATOR}The pre-consent storage strategy option is deprecated. Please enable "storage" in the pre-consent options and use the "storage" load API option instead.`;const UNSUPPORTED_PRE_CONSENT_EVENTS_DELIVERY_TYPE=(context,selectedDeliveryType,defaultDeliveryType)=>`${context}${LOG_CONTEXT_SEPARATOR}The pre-consent events delivery type "${selectedDeliveryType}" is not supported. Please choose one of the following supported types: "immediate, buffer". The default type "${defaultDeliveryType}" will be used instead.`;const DEPRECATED_PLUGIN_WARNING=(context,pluginName)=>`${context}${LOG_CONTEXT_SEPARATOR}${pluginName} plugin is deprecated. Please exclude it from the load API options.`;const generateMisconfiguredPluginsWarning=(context,configurationStatus,missingPlugins,shouldAddMissingPlugins)=>{const isSinglePlugin=missingPlugins.length===1;const pluginsString=isSinglePlugin?` '${missingPlugins[0]}' plugin was`:` ['${missingPlugins.join("', '")}'] plugins were`;const baseWarning=`${context}${LOG_CONTEXT_SEPARATOR}${configurationStatus}, but${pluginsString} not configured to load.`;if(shouldAddMissingPlugins){return `${baseWarning} So, ${isSinglePlugin?'the plugin':'those plugins'} will be loaded automatically.`;}return `${baseWarning} Ignore if this was intentional. Otherwise, consider adding ${isSinglePlugin?'it':'them'} to the 'plugins' load API option.`;};const PAGE_UNLOAD_ON_BEACON_DISABLED_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}Page Unloaded event can only be tracked when the Beacon transport is active. Please enable "useBeacon" load API option.`;const UNKNOWN_PLUGINS_WARNING=(context,unknownPlugins)=>`${context}${LOG_CONTEXT_SEPARATOR}Ignoring unknown plugins: ${unknownPlugins.join(', ')}.`;const REMOTE_PLUGIN_LOAD_ERROR=(context,pluginName,reason)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to load plugin "${pluginName}" - ${reason}`;const NO_PLUGIN_FACTORY_EXPORTED_REASON='the module exported no plugin factory';const UNAVAILABLE_PLUGINS_ERROR=(context,unavailablePlugins)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to load the following unavailable local plugins: ${unavailablePlugins.join(', ')}. Some features of the SDK may not work as expected. Make sure you are using the correct SDK bundle variant.`;const CUSTOM_INTEGRATION_CANNOT_BE_ADDED_ERROR=(context,destinationId)=>`${context}${LOG_CONTEXT_SEPARATOR}Cannot add custom integration for destination ID "${destinationId}" after the SDK is loaded.`;
|
|
639
703
|
|
|
640
704
|
const DEFAULT_INTEGRATIONS_CONFIG={All:true};
|
|
641
705
|
|
|
@@ -650,7 +714,9 @@ const CDN_INT_DIR='js-integrations';const CDN_PLUGINS_DIR='plugins';const URL_PA
|
|
|
650
714
|
'(\\#[-a-zA-Z\\d_]*)?$')// fragment locator
|
|
651
715
|
;
|
|
652
716
|
|
|
653
|
-
const BUILD_TYPE='modern';const SDK_CDN_BASE_URL='https://cdn.rudderlabs.com';const CDN_ARCH_VERSION_DIR='v3';const DEFAULT_INTEGRATION_SDKS_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/${BUILD_TYPE}/${CDN_INT_DIR}`;const DEFAULT_PLUGINS_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/${BUILD_TYPE}/${CDN_PLUGINS_DIR}`;const DEFAULT_CONFIG_BE_URL='https://api.rudderstack.com'
|
|
717
|
+
const BUILD_TYPE='modern';const SDK_CDN_BASE_URL='https://cdn.rudderlabs.com';const CDN_ARCH_VERSION_DIR='v3';const DEFAULT_INTEGRATION_SDKS_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/${BUILD_TYPE}/${CDN_INT_DIR}`;const DEFAULT_PLUGINS_URL=`${SDK_CDN_BASE_URL}/${CDN_ARCH_VERSION_DIR}/${BUILD_TYPE}/${CDN_PLUGINS_DIR}`;const DEFAULT_CONFIG_BE_URL='https://api.rudderstack.com';// Mirrors remotePluginsExportsFilename in rollup.config.mjs, which builds the URL
|
|
718
|
+
// the generated federation code requests at runtime.
|
|
719
|
+
const REMOTE_PLUGINS_ENTRY_FILE='rsa-plugins.js';
|
|
654
720
|
|
|
655
721
|
const DEFAULT_STORAGE_ENCRYPTION_VERSION='v3';const DEFAULT_DATA_PLANE_EVENTS_TRANSPORT='xhr';const ConsentManagersToPluginNameMap={iubenda:'IubendaConsentManager',oneTrust:'OneTrustConsentManager',ketch:'KetchConsentManager',custom:'CustomConsentManager'};const StorageEncryptionVersionsToPluginNameMap={[DEFAULT_STORAGE_ENCRYPTION_VERSION]:'StorageEncryption',legacy:'StorageEncryptionLegacy'};const DataPlaneEventsTransportToPluginNameMap={[DEFAULT_DATA_PLANE_EVENTS_TRANSPORT]:'XhrQueue',beacon:'BeaconQueue'};const DEFAULT_DATA_SERVICE_ENDPOINT='rsaRequest';const METRICS_SERVICE_ENDPOINT='rsaMetrics';const CUSTOM_DEVICE_MODE_DESTINATION_DISPLAY_NAME='Custom Device Mode';
|
|
656
722
|
|
|
@@ -693,9 +759,11 @@ const dataPlaneEventsState={eventsQueuePluginName:y(undefined),deliveryEnabled:y
|
|
|
693
759
|
|
|
694
760
|
const autoTrackState={enabled:y(false),pageLifecycle:{enabled:y(false),pageViewId:y(undefined),pageLoadedTimestamp:y(undefined)}};
|
|
695
761
|
|
|
696
|
-
const defaultStateValues={capabilities:capabilitiesState,consents:consentsState,context:contextState,customContext:customContextState,eventBuffer:eventBufferState,lifecycle:lifecycleState,loadOptions:loadOptionsState,metrics:metricsState,nativeDestinations:nativeDestinationsState,plugins:pluginsState,reporting:reportingState,session:sessionState,source:sourceConfigState,storage:storageState,serverCookies:serverSideCookiesState,dataPlaneEvents:dataPlaneEventsState,autoTrack:autoTrackState};const state={
|
|
762
|
+
const defaultStateValues={capabilities:capabilitiesState,consents:consentsState,context:contextState,customContext:customContextState,eventBuffer:eventBufferState,lifecycle:lifecycleState,loadOptions:loadOptionsState,metrics:metricsState,nativeDestinations:nativeDestinationsState,plugins:pluginsState,reporting:reportingState,session:sessionState,source:sourceConfigState,storage:storageState,serverCookies:serverSideCookiesState,dataPlaneEvents:dataPlaneEventsState,autoTrack:autoTrackState};const state=_objectSpread2({},clone(defaultStateValues));
|
|
697
763
|
|
|
698
|
-
const CHROME_STACK_LINE_RE=/^\s*at /;const SAFARI_NATIVE_RE=/^(eval@)?(\[native code])?$/;const
|
|
764
|
+
const CHROME_STACK_LINE_RE=/^\s*at /;const SAFARI_NATIVE_RE=/^(eval@)?(\[native code])?$/;const DIGITS_RE=/^\d+$/;function extractLocation(urlLike){if(!(urlLike!==null&&urlLike!==void 0&&urlLike.includes(':'))){return [urlLike||undefined,undefined,undefined];}const normalizedUrlLike=urlLike.startsWith('(')&&urlLike.endsWith(')')?urlLike.slice(1,-1):urlLike;// Take up to two trailing all-digit segments as line and column; whatever is left,
|
|
765
|
+
// colons included, is the file. A url keeps its scheme because "//host" is not digits.
|
|
766
|
+
const segments=normalizedUrlLike.split(':');const location=[];while(segments.length>1&&location.length<2&&DIGITS_RE.test(segments[segments.length-1])){location.unshift(Number(segments.pop()));}return [segments.join(':')||undefined,location[0],location[1]];}function parseV8Line(line){if(!CHROME_STACK_LINE_RE.test(line)){return null;}if(line.includes('(eval ')){line=line.replace(/eval code/g,'eval').replace(/\(eval at [^()]*/g,'').replace(/,.*/,'');}const sanitized=line.replace(/^\s+/,'').replace(/\(eval code/g,'(').replace(/^.*?\s+/,'');const parenLoc=/ (\(.+\)$)/.exec(sanitized);const withoutLoc=parenLoc?sanitized.replace(parenLoc[0],''):sanitized;const[rawFile,lineNumber,columnNumber]=extractLocation(parenLoc?parenLoc[1]:sanitized);const functionName=parenLoc&&withoutLoc||undefined;const fileName=rawFile==='eval'||rawFile==='<anonymous>'?undefined:rawFile;return {functionName,fileName,lineNumber,columnNumber};}function parseFFSafariLine(line){if(SAFARI_NATIVE_RE.test(line)){return null;}if(line.includes(' > eval')){line=line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,':$1');}if(!line.includes('@')&&!line.includes(':')){return {functionName:line,fileName:undefined,lineNumber:undefined,columnNumber:undefined};}const atIndex=line.lastIndexOf('@');const functionName=atIndex>0?line.slice(0,atIndex):undefined;const[fileName,lineNumber,columnNumber]=extractLocation(line.slice(atIndex+1));return {functionName,fileName,lineNumber,columnNumber};}/**
|
|
699
767
|
* Parses an Error object's stack trace into structured frames.
|
|
700
768
|
* Supports V8/Chromium (Chrome, Edge, Node) and SpiderMonkey/WebKit (Firefox, Safari) formats.
|
|
701
769
|
* Throws if the error has no stack property.
|
|
@@ -705,7 +773,7 @@ const GLOBAL_CODE='global code';const normalizeFunctionName=name=>{if(isDefined(
|
|
|
705
773
|
// - non-error exception thrown from global code in FF
|
|
706
774
|
// This adds one.
|
|
707
775
|
if(f.lineNumber&&f.lineNumber>-1&&!f.file&&!f.method){f.file=GLOBAL_CODE;}return f;};const ensureString=str=>isString(str)?str:'';function createException(errorClass,errorMessage,msgPrefix,stacktrace){return {errorClass:ensureString(errorClass),message:`${msgPrefix}${ensureString(errorMessage)}`,type:'browserjs',stacktrace:stacktrace.reduce((accum,frame)=>{const f=formatStackframe(frame);// don't include a stackframe if none of its properties are defined
|
|
708
|
-
try{if(JSON.stringify(f)==='{}')return accum;return accum.concat(f);}catch{return accum;}},[])};}const normalizeError=(maybeError,logger)=>{let error;if(isTypeOfError(maybeError)&&isString(getStacktrace(maybeError))){error=maybeError;}else {logger.warn(NON_ERROR_WARNING(ERROR_HANDLER,stringifyWithoutCircular(maybeError)));error=undefined;}return error;};const createBugsnagException=(error,msgPrefix)=>{try{const stacktrace=parseStackTrace(error);return createException(error.name,error.message,msgPrefix,stacktrace);}catch{return createException(error.name,error.message,msgPrefix,[]);}};
|
|
776
|
+
try{if(JSON.stringify(f)==='{}')return accum;return accum.concat(f);}catch(_unused){return accum;}},[])};}const normalizeError=(maybeError,logger)=>{let error;if(isTypeOfError(maybeError)&&isString(getStacktrace(maybeError))){error=maybeError;}else {logger.warn(NON_ERROR_WARNING(ERROR_HANDLER,stringifyWithoutCircular(maybeError)));error=undefined;}return error;};const createBugsnagException=(error,msgPrefix)=>{try{const stacktrace=parseStackTrace(error);return createException(error.name,error.message,msgPrefix,stacktrace);}catch(_unused2){return createException(error.name,error.message,msgPrefix,[]);}};
|
|
709
777
|
|
|
710
778
|
/**
|
|
711
779
|
* Utility to parse XHR JSON response
|
|
@@ -723,7 +791,7 @@ const DEFAULT_XHR_REQUEST_OPTIONS={headers:{Accept:'application/json','Content-T
|
|
|
723
791
|
* this is not supported by our sourceConfig API
|
|
724
792
|
*/const xhrRequest=(options,timeout=DEFAULT_XHR_TIMEOUT_MS,logger)=>new Promise((resolve,reject)=>{let payload;if(options.sendRawData===true){payload=options.data;}else {payload=stringifyWithoutCircular(options.data,false,[],logger);if(isNull(payload)){reject({error:new Error(XHR_PAYLOAD_PREP_ERROR),undefined,options});// return and don't process further if the payload could not be stringified
|
|
725
793
|
return;}}const xhr=new XMLHttpRequest();// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
726
|
-
const xhrReject=e=>{reject({error:new Error(XHR_DELIVERY_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,xhr.status,xhr.statusText,options.url,xhr.responseText)),xhr,options});};const xhrError=e=>{reject({error:new Error(XHR_REQUEST_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,e,options.url)),xhr,options
|
|
794
|
+
const xhrReject=e=>{reject({error:new Error(XHR_DELIVERY_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,xhr.status,xhr.statusText,options.url,xhr.responseText)),xhr,options});};const xhrError=e=>{reject(_objectSpread2({error:new Error(XHR_REQUEST_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,e,options.url)),xhr,options},(e===null||e===void 0?void 0:e.type)==='timeout'?{timedOut:true}:{}));};xhr.ontimeout=xhrError;xhr.onerror=xhrError;xhr.onload=()=>{if(xhr.status>=200&&xhr.status<400){resolve({response:xhr.responseText,xhr,options});}else {xhrReject();}};xhr.open(options.method,options.url,true);if(options.withCredentials===true){xhr.withCredentials=true;}// The timeout property may be set only in the time interval between a call to the open method
|
|
727
795
|
// and the first call to the send method in legacy browsers
|
|
728
796
|
xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options.headers[headerName]){xhr.setRequestHeader(headerName,options.headers[headerName]);}});try{xhr.send(payload);}catch(err){reject({error:getMutatedError(err,XHR_SEND_ERROR(FAILED_REQUEST_ERR_MSG_PREFIX,options.url)),xhr,options});}});
|
|
729
797
|
|
|
@@ -736,7 +804,7 @@ xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options
|
|
|
736
804
|
*/getAsyncData(config){const{callback,url,options,timeout,isRawResponse,skipAuthHeader}=config;const isFireAndForget=!isFunction(callback);xhrRequest(createXhrRequestOptions(url,options,this.getAuthHeader(skipAuthHeader)),timeout,this.logger).then(data=>{if(!isFireAndForget){callback(isRawResponse?data.response:responseTextToJson(data.response,this.onError),data);}},data=>{if(!isFireAndForget){callback(undefined,data);}})// Exceptions thrown by the callback must never re-enter it
|
|
737
805
|
.catch(this.onError);}/**
|
|
738
806
|
* Handle errors
|
|
739
|
-
*/onError(error,groupingHash){this.errorHandler
|
|
807
|
+
*/onError(error,groupingHash){var _this$errorHandler;(_this$errorHandler=this.errorHandler)===null||_this$errorHandler===void 0||_this$errorHandler.onError({error,context:HTTP_CLIENT,groupingHash});}/**
|
|
740
808
|
* Set basic authentication header (eg writekey)
|
|
741
809
|
*/getAuthHeader(skipAuthHeader){return skipAuthHeader===true?undefined:this.basicAuthHeader;}setAuthHeader(value,noBtoa=false){const authVal=noBtoa?value:toBase64(`${value}:`);this.basicAuthHeader=`Basic ${authVal}`;}/**
|
|
742
810
|
* Clear basic authentication header
|
|
@@ -757,9 +825,7 @@ const getErrInstance=(err,errorType)=>{switch(errorType){case ErrorType.UNHANDLE
|
|
|
757
825
|
* A function to get the Bugsnag release stage for the current environment
|
|
758
826
|
* @param getHostName Optional function to get the hostname (primarily for testing)
|
|
759
827
|
* @returns 'development' if the host is empty (for file:// protocol etc.) or a dev host (localhost, 127.0.0.1, etc.), otherwise ''production'' (it'll be replaced with the actual release stage during the build)
|
|
760
|
-
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'production';};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):{};};const getURLWithoutQueryString=()=>{const url=globalThis.location.href.split('?');return url[0];};const getUserDetails=(source,session,lifecycle,autoTrack)=>
|
|
761
|
-
// so that they show up as separate tabs in the dashboard
|
|
762
|
-
...getAppStateForMetadata(state)},user:getUserDetails(source,session,lifecycle,autoTrack)}]};};// A violation only speaks for the kind of load the directive governs. default-src
|
|
828
|
+
*/const getReleaseStage=(getHostName=()=>window.location.hostname)=>{const host=getHostName();return !host||host&&DEV_HOSTS.includes(host)?'development':'production';};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):{};};const getURLWithoutQueryString=()=>{const url=globalThis.location.href.split('?');return url[0];};const getUserDetails=(source,session,lifecycle,autoTrack)=>{var _source$value$id,_source$value,_session$sessionInfo$,_autoTrack$pageLifecy,_source$value$name,_source$value2;return {id:`${(_source$value$id=(_source$value=source.value)===null||_source$value===void 0?void 0:_source$value.id)!==null&&_source$value$id!==void 0?_source$value$id:lifecycle.writeKey.value}..${(_session$sessionInfo$=session.sessionInfo.value.id)!==null&&_session$sessionInfo$!==void 0?_session$sessionInfo$:'NA'}..${(_autoTrack$pageLifecy=autoTrack.pageLifecycle.pageViewId.value)!==null&&_autoTrack$pageLifecy!==void 0?_autoTrack$pageLifecy:'NA'}`,name:(_source$value$name=(_source$value2=source.value)===null||_source$value2===void 0?void 0:_source$value2.name)!==null&&_source$value$name!==void 0?_source$value$name:'NA'};};const getDeviceDetails=(locale,userAgent)=>{var _locale$value,_userAgent$value;return {locale:(_locale$value=locale.value)!==null&&_locale$value!==void 0?_locale$value:'NA',userAgent:(_userAgent$value=userAgent.value)!==null&&_userAgent$value!==void 0?_userAgent$value:'NA',time:new Date()};};const getBugsnagErrorEvent=(exception,errorState,state,groupingHash)=>{const{context,lifecycle,session,source,reporting,autoTrack}=state;const{app,locale,userAgent,timezone,screen,library}=context;return {payloadVersion:'5',notifier:{name:NOTIFIER_NAME,version:app.value.version,url:SDK_GITHUB_URL},events:[{exceptions:[clone(exception)],severity:errorState.severity,unhandled:errorState.unhandled,severityReason:errorState.severityReason,app:{version:app.value.version,releaseStage:getReleaseStage(),type:app.value.installType},device:getDeviceDetails(locale,userAgent),request:{url:getURLWithoutQueryString(),clientIp:'[NOT COLLECTED]'},breadcrumbs:clone(reporting.breadcrumbs.value),context:exception.message,groupingHash,metaData:_objectSpread2({app:{snippetVersion:library.value.snippetVersion},device:_objectSpread2(_objectSpread2({},screen.value),{},{timezone:timezone.value})},getAppStateForMetadata(state)),user:getUserDetails(source,session,lifecycle,autoTrack)}]};};// A violation only speaks for the kind of load the directive governs. default-src
|
|
763
829
|
// is the fallback for both, so it counts for either.
|
|
764
830
|
const SCRIPT_CSP_DIRECTIVES=['script-src-elem','script-src','default-src'];const CONNECT_CSP_DIRECTIVES=['connect-src','default-src'];const hasCspViolation=(state,url,directives)=>state.capabilities.cspViolations.value.some(violation=>directives.includes(violation.directive)&&isSameOrUnder(url,violation.blockedURL));/**
|
|
765
831
|
* Whether a URL is the blocked one or sits beneath it.
|
|
@@ -779,11 +845,11 @@ const inFlightProbes=new Map();/**
|
|
|
779
845
|
* integrations sit under different prefixes and can be blocked independently.
|
|
780
846
|
*/const probeSdkCdn=(state,httpClient,url,done)=>{if(isDefined(state.capabilities.sdkCdnProbe.value[url])){done();return;}const waiting=inFlightProbes.get(url);if(waiting){waiting.push(done);return;}inFlightProbes.set(url,[done]);httpClient.getAsyncData({url,// The CDN refuses preflight, so this has to stay a simple request: a HEAD
|
|
781
847
|
// carrying none of the headers the client would otherwise add.
|
|
782
|
-
skipAuthHeader:true,options:{method:'HEAD',headers:{'Content-Type':undefined,Accept:undefined}},isRawResponse:true,callback:(_result,details)=>{
|
|
848
|
+
skipAuthHeader:true,options:{method:'HEAD',headers:{'Content-Type':undefined,Accept:undefined}},isRawResponse:true,callback:(_result,details)=>{var _details$xhr$status,_details$xhr,_details$xhr2,_inFlightProbes$get;// A request that never reached the CDN reports status 0. A blocker that
|
|
783
849
|
// answers instead of dropping it lands on a URL outside the CDN. An
|
|
784
850
|
// ordinary redirect that stays under the CDN -- canonicalisation, a signed
|
|
785
851
|
// URL -- is the CDN answering and must not be mistaken for one.
|
|
786
|
-
const status=details
|
|
852
|
+
const status=(_details$xhr$status=details===null||details===void 0||(_details$xhr=details.xhr)===null||_details$xhr===void 0?void 0:_details$xhr.status)!==null&&_details$xhr$status!==void 0?_details$xhr$status:0;const responseURL=details===null||details===void 0||(_details$xhr2=details.xhr)===null||_details$xhr2===void 0?void 0:_details$xhr2.responseURL;state.capabilities.sdkCdnProbe.value=_objectSpread2(_objectSpread2({},state.capabilities.sdkCdnProbe.value),{},{[url]:{status,timedOut:(details===null||details===void 0?void 0:details.timedOut)===true,redirectedOffCdn:status!==0&&isString(responseURL)&&responseURL!==url&&!isSameOrUnder(responseURL,SDK_CDN_BASE_URL)}});const waiters=(_inFlightProbes$get=inFlightProbes.get(url))!==null&&_inFlightProbes$get!==void 0?_inFlightProbes$get:[];inFlightProbes.delete(url);waiters.forEach(waiter=>waiter());}});};/**
|
|
787
853
|
* A function to determine whether the error should be promoted to notify or not.
|
|
788
854
|
* Script load failures from a host other than the RS CDN are not promoted.
|
|
789
855
|
* For those from the RS CDN, a probe of the failed URL is awaited so its result
|
|
@@ -800,7 +866,7 @@ const status=details?.xhr?.status??0;const responseURL=details?.xhr?.responseURL
|
|
|
800
866
|
* @param {IHttpClient} httpClient The HTTP client instance
|
|
801
867
|
* @returns A promise that resolves to a boolean indicating whether the error should be promoted to notify or not
|
|
802
868
|
*/const checkIfAllowedToBeNotified=(exception,state,httpClient)=>{const errMsg=exception.message;return new Promise(resolve=>{// Filter out script load failures that are not from the RS CDN.
|
|
803
|
-
if(SCRIPT_LOAD_FAILURE_MESSAGES.some(regex=>regex.test(errMsg))){const extractedURL=/https?:\/\/[^\s"'(),;<>[\]{}]+/.exec(errMsg)
|
|
869
|
+
if(SCRIPT_LOAD_FAILURE_MESSAGES.some(regex=>regex.test(errMsg))){var _exec;const extractedURL=(_exec=/https?:\/\/[^\s"'(),;<>[\]{}]+/.exec(errMsg))===null||_exec===void 0?void 0:_exec[0];if(isString(extractedURL)){if(isSameOrUnder(extractedURL,SDK_CDN_BASE_URL)){// Wait for the CDN reachability probe so its result is carried in the
|
|
804
870
|
// report. The generic ad blocker signal is deliberately not consulted:
|
|
805
871
|
// it probes the source config host rather than the CDN, and a client
|
|
806
872
|
// that cannot reach the CDN is indistinguishable from a CDN outage, so
|
|
@@ -821,11 +887,13 @@ resolve(true);}}else {resolve(!ERROR_MESSAGES_TO_BE_FILTERED.some(e=>e.test(errM
|
|
|
821
887
|
* A function to get the directory name from a file path.
|
|
822
888
|
* @param {string} filePath The file path
|
|
823
889
|
* @returns The directory name or undefined if the file path is invalid
|
|
824
|
-
*/const getDirectoryName=filePath=>{if(!filePath){return undefined;}const paths=filePath.split('/')
|
|
890
|
+
*/const getDirectoryName=filePath=>{if(!filePath){return undefined;}const paths=filePath.split('/');// Not `.at(-2)`: Array.prototype.at is neither transpiled nor polyfilled
|
|
891
|
+
return paths[paths.length-2];// NOSONAR
|
|
892
|
+
};/**
|
|
825
893
|
* A function to get the top stack path from the exception.
|
|
826
894
|
* @param {Exception} exception The exception object
|
|
827
895
|
* @returns The top stack path or undefined if the exception is invalid
|
|
828
|
-
*/const getTopStackPath=exception=>{const errorOrigin=exception.stacktrace[0]
|
|
896
|
+
*/const getTopStackPath=exception=>{var _exception$stacktrace;const errorOrigin=(_exception$stacktrace=exception.stacktrace[0])===null||_exception$stacktrace===void 0?void 0:_exception$stacktrace.file;if(!errorOrigin||typeof errorOrigin!=='string'){return undefined;}return errorOrigin;};/**
|
|
829
897
|
* A function to determine if the error is from Rudder SDK
|
|
830
898
|
* @param {Error} exception
|
|
831
899
|
* @returns
|
|
@@ -842,8 +910,8 @@ resolve(true);}}else {resolve(!ERROR_MESSAGES_TO_BE_FILTERED.some(e=>e.test(errM
|
|
|
842
910
|
|
|
843
911
|
/**
|
|
844
912
|
* A service to handle errors
|
|
845
|
-
*/class ErrorHandler{
|
|
846
|
-
constructor(httpClient,logger){this.httpClient=httpClient;this.logger=logger;}/**
|
|
913
|
+
*/class ErrorHandler{// If no logger is passed errors will be thrown as unhandled error
|
|
914
|
+
constructor(httpClient,logger){_defineProperty(this,"initialized",false);this.httpClient=httpClient;this.logger=logger;}/**
|
|
847
915
|
* Initializes the error handler by attaching global error listeners.
|
|
848
916
|
* This method should be called once after construction.
|
|
849
917
|
*/init(){if(this.initialized){return;}this.attachErrorListeners();this.initialized=true;}/**
|
|
@@ -861,7 +929,7 @@ document.addEventListener('securitypolicyviolation',event=>{const blockedURL=isS
|
|
|
861
929
|
* @param errorInfo.errorType - The type of the error (handled or unhandled)
|
|
862
930
|
* @param errorInfo.groupingHash - The grouping hash of the error
|
|
863
931
|
* @param errorInfo.category - The category of the error (sdk or integrations)
|
|
864
|
-
*/async onError(errorInfo){try{const{error,context,customMessage,groupingHash,category}=errorInfo;const errorType=errorInfo.errorType
|
|
932
|
+
*/async onError(errorInfo){try{var _errorInfo$errorType;const{error,context,customMessage,groupingHash,category}=errorInfo;const errorType=(_errorInfo$errorType=errorInfo.errorType)!==null&&_errorInfo$errorType!==void 0?_errorInfo$errorType:ErrorType.HANDLEDEXCEPTION;const errInstance=getErrInstance(error,errorType);const normalizedError=normalizeError(errInstance,this.logger);if(isUndefined(normalizedError)){return;}const customMsgVal=customMessage?`${customMessage} - `:'';const errorMsgPrefix=`${context}${LOG_CONTEXT_SEPARATOR}${customMsgVal}`;const bsException=createBugsnagException(normalizedError,errorMsgPrefix);const stacktrace=getStacktrace(normalizedError);const isSdkDispatched=stacktrace.includes(MANUAL_ERROR_IDENTIFIER);// Filter errors that are not originated in the SDK.
|
|
865
933
|
// In case of NPM installations, the unhandled errors from the SDK cannot be identified
|
|
866
934
|
// and will NOT be reported unless they occur in plugins or integrations.
|
|
867
935
|
if(!isSdkDispatched&&!isSDKError(bsException)&&errorType!==ErrorType.HANDLEDEXCEPTION){return;}if(state.reporting.isErrorReportingEnabled.value){const isAllowed=await checkIfAllowedToBeNotified(bsException,state,this.httpClient);if(isAllowed){const errorState={severity:'error',unhandled:errorType!==ErrorType.HANDLEDEXCEPTION,severityReason:{type:errorType}};// This will allow custom grouping of errors.
|
|
@@ -885,10 +953,10 @@ const defaultErrorHandler=new ErrorHandler(defaultHttpClient,defaultLogger);
|
|
|
885
953
|
// to next or return the value if it is the last one instead of an array per
|
|
886
954
|
// plugin that is the normal invoke
|
|
887
955
|
// TODO: add invoke method for extension point that we know only one plugin can be used. add invokeMultiple and invokeSingle methods
|
|
888
|
-
class PluginEngine{plugins
|
|
956
|
+
class PluginEngine{constructor(logger,options={}){_defineProperty(this,"plugins",[]);_defineProperty(this,"byName",{});_defineProperty(this,"cache",{});_defineProperty(this,"config",{throws:true});this.config=_objectSpread2({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);return;}}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);return;}}this.cache={};this.plugins=this.plugins.slice();let pos=this.plugins.length;this.plugins.forEach((pluginItem,index)=>{var _pluginItem$deps;if((_pluginItem$deps=pluginItem.deps)!==null&&_pluginItem$deps!==void 0&&_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);return;}}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);return;}}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!==null&&extPoint!==void 0?extPoint:'.';if(!this.cache[lifeCycleName]){this.cache[lifeCycleName]=this.plugins.filter(plugin=>{var _plugin$deps;if((_plugin$deps=plugin.deps)!==null&&_plugin$deps!==void 0&&_plugin$deps.some(dependency=>!this.byName[dependency])){// If deps not exist, then not load it.
|
|
889
957
|
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
|
|
890
958
|
// do some unified pre-process before application starts.
|
|
891
|
-
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
|
|
959
|
+
processRawPlugins(callback){callback(this.plugins);this.cache={};}invoke(extPoint,allowMultiple=true,...args){var _this$config$throws;let extensionPointName=extPoint;if(!extensionPointName){throw new Error(PLUGIN_EXT_POINT_MISSING_ERROR);}const noCall=extensionPointName.startsWith('!');const throws=(_this$config$throws=this.config.throws)!==null&&_this$config$throws!==void 0?_this$config$throws:extensionPointName.endsWith('!');// eslint-disable-next-line unicorn/better-regex
|
|
892
960
|
extensionPointName=extensionPointName.replace(/(^!|!$)/g,'');if(!extensionPointName){throw new Error(PLUGIN_EXT_POINT_INVALID_ERROR);}const extensionPointNameParts=extensionPointName.split('.');extensionPointNameParts.pop();const pluginMethodPath=extensionPointNameParts.join('.');const pluginsToInvoke=allowMultiple?this.getPlugins(extensionPointName):[this.getPlugins(extensionPointName)[0]];return pluginsToInvoke.map(plugin=>{const method=getValueByPath(plugin,extensionPointName);if(!isFunction(method)||noCall){return method;}try{return method.apply(getValueByPath(plugin,pluginMethodPath),args);}catch(err){// When a plugin failed, doesn't break the app
|
|
893
961
|
if(throws){throw err;}else {this.logger.error(PLUGIN_INVOCATION_ERROR(PLUGIN_ENGINE,extensionPointName,plugin.name),err);}}return null;});}invokeSingle(extPoint,...args){return this.invoke(extPoint,false,...args)[0];}invokeMultiple(extPoint,...args){return this.invoke(extPoint,true,...args);}}const defaultPluginEngine=new PluginEngine(defaultLogger,{throws:true});
|
|
894
962
|
|
|
@@ -911,7 +979,8 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
|
|
|
911
979
|
* @param id The id of the destination
|
|
912
980
|
*
|
|
913
981
|
* @returns the user friendly id
|
|
914
|
-
*/const getDestinationUserFriendlyId=(displayName,id)
|
|
982
|
+
*/const getDestinationUserFriendlyId=(displayName,id)=>// displayName comes from the source config response, so it is not guaranteed to be a string
|
|
983
|
+
`${String(displayName!==null&&displayName!==void 0?displayName:'').replace(/ /g,'-')}___${id}`;
|
|
915
984
|
|
|
916
985
|
/**
|
|
917
986
|
* List of plugin names that are loaded as dynamic imports in modern builds
|
|
@@ -936,7 +1005,7 @@ new URL(url);}return URL_PATTERN.test(url);}catch(e){return false;}};
|
|
|
936
1005
|
|
|
937
1006
|
/**
|
|
938
1007
|
* Encode.
|
|
939
|
-
*/const encode=(value,logger)=>{try{return encodeURIComponent(value);}catch(err){logger
|
|
1008
|
+
*/const encode=(value,logger)=>{try{return encodeURIComponent(value);}catch(err){logger===null||logger===void 0||logger.error(COOKIE_DATA_ENCODING_ERROR,err);return undefined;}};/**
|
|
940
1009
|
* Decode
|
|
941
1010
|
*/const decode=value=>{try{return decodeURIComponent(value);}catch(err){// Do nothing as non-RS SDK cookies may not be URI encoded
|
|
942
1011
|
return undefined;}};/**
|
|
@@ -944,7 +1013,7 @@ return undefined;}};/**
|
|
|
944
1013
|
*/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
|
|
945
1014
|
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;};/**
|
|
946
1015
|
* Set cookie `name` to `value`
|
|
947
|
-
*/const set=(name,value,optionsConfig,logger)=>{const options={
|
|
1016
|
+
*/const set=(name,value,optionsConfig,logger)=>{const options=_objectSpread2({},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;};/**
|
|
948
1017
|
* Return all cookies
|
|
949
1018
|
*/const all=()=>{const cookieStringValue=globalThis.document.cookie;return parse(cookieStringValue);};/**
|
|
950
1019
|
* Get cookie `name`
|
|
@@ -955,7 +1024,7 @@ const cookie=function(name,value,options,logger){switch(arguments.length){case 4
|
|
|
955
1024
|
|
|
956
1025
|
const userIdKey='rl_user_id';const userTraitsKey='rl_trait';const anonymousUserIdKey='rl_anonymous_id';const groupIdKey='rl_group_id';const groupTraitsKey='rl_group_trait';const pageInitialReferrerKey='rl_page_init_referrer';const pageInitialReferringDomainKey='rl_page_init_referring_domain';const sessionInfoKey='rl_session';const authTokenKey='rl_auth_token';const COOKIE_KEYS={userId:userIdKey,userTraits:userTraitsKey,anonymousId:anonymousUserIdKey,groupId:groupIdKey,groupTraits:groupTraitsKey,initialReferrer:pageInitialReferrerKey,initialReferringDomain:pageInitialReferringDomainKey,sessionInfo:sessionInfoKey,authToken:authTokenKey};const ENCRYPTION_PREFIX_V3='RS_ENC_v3_';
|
|
957
1026
|
|
|
958
|
-
const encryptBrowser=value=>`${ENCRYPTION_PREFIX_V3}${toBase64(value)}`;const decryptBrowser=value=>{if(value
|
|
1027
|
+
const encryptBrowser=value=>`${ENCRYPTION_PREFIX_V3}${toBase64(value)}`;const decryptBrowser=value=>{if(value!==null&&value!==void 0&&value.startsWith(ENCRYPTION_PREFIX_V3)){return fromBase64(value.substring(ENCRYPTION_PREFIX_V3.length));}return value;};
|
|
959
1028
|
|
|
960
1029
|
const EVENT_PAYLOAD_SIZE_BYTES_LIMIT=32*1024;// 32 KB
|
|
961
1030
|
const RETRY_REASON_CLIENT_NETWORK='client-network';const RETRY_REASON_CLIENT_TIMEOUT='client-timeout';const DEFAULT_RETRY_REASON=RETRY_REASON_CLIENT_NETWORK;
|
|
@@ -963,8 +1032,8 @@ const RETRY_REASON_CLIENT_NETWORK='client-network';const RETRY_REASON_CLIENT_TIM
|
|
|
963
1032
|
const isStorageQuotaExceeded=e=>{const matchingNames=['QuotaExceededError','NS_ERROR_DOM_QUOTA_REACHED'];// Everything except Firefox, Firefox
|
|
964
1033
|
const matchingCodes=[22,1014];if(e instanceof DOMException){return matchingNames.includes(e.name)||matchingCodes.includes(e.code);}return false;};// TODO: also check for SecurityErrors
|
|
965
1034
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#exceptions
|
|
966
|
-
const isStorageAvailable=(type=LOCAL_STORAGE,storageInstance,logger)=>{let storage;let testData;const msgPrefix=STORAGE_UNAVAILABILITY_ERROR_PREFIX(CAPABILITIES_MANAGER,type);let reason='unavailable';let isAccessible=true;let errObj;try{switch(type){case MEMORY_STORAGE:return true;case COOKIE_STORAGE:storage=storageInstance;testData=STORAGE_TEST_COOKIE;break;case LOCAL_STORAGE:storage=storageInstance
|
|
967
|
-
break;case SESSION_STORAGE:storage=storageInstance
|
|
1035
|
+
const isStorageAvailable=(type=LOCAL_STORAGE,storageInstance,logger)=>{let storage;let testData;const msgPrefix=STORAGE_UNAVAILABILITY_ERROR_PREFIX(CAPABILITIES_MANAGER,type);let reason='unavailable';let isAccessible=true;let errObj;try{switch(type){case MEMORY_STORAGE:return true;case COOKIE_STORAGE:storage=storageInstance;testData=STORAGE_TEST_COOKIE;break;case LOCAL_STORAGE:storage=storageInstance!==null&&storageInstance!==void 0?storageInstance:globalThis.localStorage;testData=STORAGE_TEST_LOCAL_STORAGE;// was STORAGE_TEST_LOCAL_STORAGE in ours and generateUUID() in segment retry one
|
|
1036
|
+
break;case SESSION_STORAGE:storage=storageInstance!==null&&storageInstance!==void 0?storageInstance:globalThis.sessionStorage;testData=STORAGE_TEST_SESSION_STORAGE;break;default:return false;}if(storage){storage.setItem(testData,'true');if(storage.getItem(testData)){storage.removeItem(testData);return true;}}isAccessible=false;}catch(err){isAccessible=false;errObj=err;if(isStorageQuotaExceeded(err)){reason='full';}}if(!isAccessible){logger===null||logger===void 0||logger.warn(`${msgPrefix}${reason}.`,errObj);}// if we've have reached here, it means the storage is not available
|
|
968
1037
|
return false;};
|
|
969
1038
|
|
|
970
1039
|
const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${context}${LOG_CONTEXT_SEPARATOR}The size of the event payload (${payloadSize} bytes) exceeds the maximum limit of ${sizeLimit} bytes. Events with large payloads may be dropped in the future. Please review your instrumentation to ensure that event payloads are within the size limit.`;const EVENT_PAYLOAD_SIZE_VALIDATION_WARNING=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to validate event payload size. Please make sure that the event payload is within the size limit and is a valid JSON object.`;const QUEUE_UTILITIES='QueueUtilities';/**
|
|
@@ -976,7 +1045,7 @@ const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${
|
|
|
976
1045
|
* Utility to validate final payload size before sending to server
|
|
977
1046
|
* @param event RudderEvent object
|
|
978
1047
|
* @param logger Logger instance
|
|
979
|
-
*/const validateEventPayloadSize=(event,logger)=>{const payloadStr=getDeliveryPayload(event,logger);if(payloadStr){const payloadSize=payloadStr.length;if(payloadSize>EVENT_PAYLOAD_SIZE_BYTES_LIMIT){logger
|
|
1048
|
+
*/const validateEventPayloadSize=(event,logger)=>{const payloadStr=getDeliveryPayload(event,logger);if(payloadStr){const payloadSize=payloadStr.length;if(payloadSize>EVENT_PAYLOAD_SIZE_BYTES_LIMIT){logger===null||logger===void 0||logger.warn(EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING(QUEUE_UTILITIES,payloadSize,EVENT_PAYLOAD_SIZE_BYTES_LIMIT));}}else {logger===null||logger===void 0||logger.warn(EVENT_PAYLOAD_SIZE_VALIDATION_WARNING(QUEUE_UTILITIES));}};/**
|
|
980
1049
|
* Mutates the event and return final event for delivery
|
|
981
1050
|
* Updates certain parameters like sentAt timestamp, integrations config etc.
|
|
982
1051
|
* @param event RudderEvent object
|
|
@@ -1007,7 +1076,7 @@ const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flush
|
|
|
1007
1076
|
* @param events RudderEvent object array
|
|
1008
1077
|
* @param logger Logger instance
|
|
1009
1078
|
* @returns stringified events payload as Blob, undefined if error occurs.
|
|
1010
|
-
*/const getBatchDeliveryPayload$1=(events,currentTime,logger)=>{const data={batch:events,sentAt:currentTime};try{const blobPayload=stringifyWithoutCircular(data,true);const blobOptions={type:'text/plain'};if(blobPayload){return new Blob([blobPayload],blobOptions);}logger
|
|
1079
|
+
*/const getBatchDeliveryPayload$1=(events,currentTime,logger)=>{const data={batch:events,sentAt:currentTime};try{const blobPayload=stringifyWithoutCircular(data,true);const blobOptions={type:'text/plain'};if(blobPayload){return new Blob([blobPayload],blobOptions);}logger===null||logger===void 0||logger.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){logger===null||logger===void 0||logger.error(BEACON_QUEUE_BLOB_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN),err);}return undefined;};const getNormalizedBeaconQueueOptions=queueOpts=>mergeDeepRight(DEFAULT_BEACON_QUEUE_OPTIONS,queueOpts);const getDeliveryUrl$1=(dataplaneUrl,writeKey)=>{const dpUrl=new URL(dataplaneUrl);return new URL(removeDuplicateSlashes([dpUrl.pathname,'/','beacon','/',DATA_PLANE_API_VERSION$1,'/',`batch?writeKey=${writeKey}`].join('')),dpUrl).href;};
|
|
1011
1080
|
|
|
1012
1081
|
let ScheduleModes=/*#__PURE__*/function(ScheduleModes){ScheduleModes[ScheduleModes["ASAP"]=1]="ASAP";ScheduleModes[ScheduleModes["RESCHEDULE"]=2]="RESCHEDULE";ScheduleModes[ScheduleModes["ABANDON"]=3]="ABANDON";return ScheduleModes;}({});const DEFAULT_CLOCK_LATE_FACTOR=2;const DEFAULT_CLOCK={setTimeout(fn,ms){return globalThis.setTimeout(fn,ms);},clearTimeout(id){return globalThis.clearTimeout(id);},Date:globalThis.Date,clockLateFactor:DEFAULT_CLOCK_LATE_FACTOR};class Schedule{constructor(){this.tasks={};this.nextId=1;this.clock=DEFAULT_CLOCK;}now(){return +new this.clock.Date();}run(task,timeout,mode){if(this.nextId===Number.MAX_SAFE_INTEGER){this.nextId=1;}const id=(this.nextId++).toString();this.tasks[id]=this.clock.setTimeout(this.handle(id,task,timeout,mode||ScheduleModes.ASAP),timeout);return id;}handle(id,callback,timeout,mode){const start=this.now();return ()=>{delete this.tasks[id];const elapsedTimeoutTime=start+timeout*(this.clock.clockLateFactor||DEFAULT_CLOCK_LATE_FACTOR);const currentTime=this.now();const notCompletedOrTimedOut=mode>=ScheduleModes.RESCHEDULE&&elapsedTimeoutTime<currentTime;if(notCompletedOrTimedOut){if(mode===ScheduleModes.RESCHEDULE){this.run(callback,timeout,mode);}return undefined;}return callback();};}cancel(id){if(this.tasks[id]){this.clock.clearTimeout(this.tasks[id]);delete this.tasks[id];}}cancelAll(){Object.values(this.tasks).forEach(this.clock.clearTimeout);this.tasks={};}}
|
|
1013
1082
|
|
|
@@ -1024,29 +1093,31 @@ const runningQueueIdsByName=new Map();class RetryQueue{/**
|
|
|
1024
1093
|
* Constructs a RetryQueue backed by localStorage
|
|
1025
1094
|
*
|
|
1026
1095
|
* @param {String} name The name of the queue. Will be used to find abandoned queues and retry their items
|
|
1027
|
-
* @param {QueueOpts} [options] Optional argument to override `maxItems`, `maxAttempts`, `minRetryDelay
|
|
1096
|
+
* @param {QueueOpts} [options] Optional argument to override `maxItems`, `maxAttempts`, `minRetryDelay`, `maxRetryDelay`, `backoffFactor` and `backoffJitter`.
|
|
1028
1097
|
* @param {QueueProcessCallback} queueProcessCb The function to call in order to process an item added to the queue
|
|
1029
1098
|
* @param {IStoreManager} storeManager The store manager instance to use
|
|
1030
1099
|
* @param {StorageType} [storageType] The storage type to use. Defaults to LOCAL_STORAGE
|
|
1031
1100
|
* @param {ILogger} [logger] The logger to use
|
|
1032
1101
|
* @param {QueueBatchItemsSizeCalculatorCallback} [queueBatchItemsSizeCalculatorCb] The callback to use to calculate the size of items in the batch queue
|
|
1033
|
-
*/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
|
|
1034
|
-
|
|
1102
|
+
*/constructor(name,options,queueProcessCb,storeManager,storageType=LOCAL_STORAGE,logger,queueBatchItemsSizeCalculatorCb){var _options$maxAttempts,_options$backoffJitte,_options$timerScaleFa;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=options.maxAttempts)!==null&&_options$maxAttempts!==void 0?_options$maxAttempts:DEFAULT_MAX_RETRY_ATTEMPTS;this.batch={enabled:false};this.configureBatchMode(options);// `??` keeps an explicit 0 but also keeps NaN, which would make every delay NaN
|
|
1103
|
+
const jitter=(_options$backoffJitte=options.backoffJitter)!==null&&_options$backoffJitte!==void 0?_options$backoffJitte:DEFAULT_BACKOFF_JITTER;this.backoff={minRetryDelay:options.minRetryDelay||DEFAULT_MIN_RETRY_DELAY_MS,maxRetryDelay:options.maxRetryDelay||DEFAULT_MAX_RETRY_DELAY_MS,factor:options.backoffFactor||DEFAULT_BACKOFF_FACTOR,// Clamp so delays stay positive and within maxRetryDelay
|
|
1104
|
+
jitter:Number.isNaN(jitter)?DEFAULT_BACKOFF_JITTER:Math.min(Math.max(jitter,0),1)};// Limit the timer scale factor to the minimum value
|
|
1105
|
+
let timerScaleFactor=Math.max((_options$timerScaleFa=options.timerScaleFactor)!==null&&_options$timerScaleFa!==void 0?_options$timerScaleFa:MIN_TIMER_SCALE_FACTOR,MIN_TIMER_SCALE_FACTOR);// Limit the timer scale factor to the maximum value
|
|
1035
1106
|
timerScaleFactor=Math.min(timerScaleFactor,MAX_TIMER_SCALE_FACTOR);// painstakingly tuned. that's why they're not "easily" configurable
|
|
1036
1107
|
this.timeouts={ackTimer:Math.round(timerScaleFactor*DEFAULT_ACK_TIMER_MS),reclaimTimer:Math.round(timerScaleFactor*DEFAULT_RECLAIM_TIMER_MS),reclaimTimeout:Math.round(timerScaleFactor*DEFAULT_RECLAIM_TIMEOUT_MS),reclaimWait:Math.round(timerScaleFactor*DEFAULT_RECLAIM_WAIT_MS)};this.schedule=new Schedule();this.processId='0';// Set up our empty queues
|
|
1037
1108
|
this.store=this.storeManager.setStore({id:this.id,name:this.name,validKeys:QueueStatuses,type:storageType,errorHandler:this.storeManager.errorHandler,logger:this.storeManager.logger});this.setDefaultQueueEntries();// bind recurring tasks for ease of use
|
|
1038
1109
|
this.ack=this.ack.bind(this);this.checkReclaim=this.checkReclaim.bind(this);this.processHead=this.processHead.bind(this);this.flushBatch=this.flushBatch.bind(this);this.isPageAccessible=true;// Flush the queue on page leave
|
|
1039
|
-
this.flushBatchOnPageLeave();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){
|
|
1040
|
-
this.batch.maxSize=Math.min(batchOptions.maxSize
|
|
1110
|
+
this.flushBatchOnPageLeave();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){var _batchOptions$maxSize,_batchOptions$maxItem,_batchOptions$flushIn;// Set upper cap on the batch payload size
|
|
1111
|
+
this.batch.maxSize=Math.min((_batchOptions$maxSize=batchOptions.maxSize)!==null&&_batchOptions$maxSize!==void 0?_batchOptions$maxSize:DEFAULT_MAX_BATCH_SIZE_BYTES,DEFAULT_MAX_BATCH_SIZE_BYTES);this.batch.maxItems=(_batchOptions$maxItem=batchOptions.maxItems)!==null&&_batchOptions$maxItem!==void 0?_batchOptions$maxItem:DEFAULT_MAX_BATCH_ITEMS;this.batch.flushInterval=(_batchOptions$flushIn=batchOptions.flushInterval)!==null&&_batchOptions$flushIn!==void 0?_batchOptions$flushIn:DEFAULT_BATCH_FLUSH_INTERVAL_MS;}}flushBatchOnPageLeave(){if(this.batch.enabled){onPageLeave(this.flushBatch);}}getStorageEntry(name){return this.store.get(name);}// TODO: fix the type of different queues to be the same if possible
|
|
1041
1112
|
setStorageEntry(name,value){if(isNullOrUndefined(value)){this.store.remove(name);}else {this.store.set(name,value);}}/**
|
|
1042
1113
|
* Stops processing the queue
|
|
1043
|
-
*/stop(){this.schedule.cancelAll();this.scheduleTimeoutActive=false;const runningQueueIds=runningQueueIdsByName.get(this.name);runningQueueIds
|
|
1114
|
+
*/stop(){this.schedule.cancelAll();this.scheduleTimeoutActive=false;const runningQueueIds=runningQueueIdsByName.get(this.name);runningQueueIds===null||runningQueueIds===void 0||runningQueueIds.delete(this.id);if((runningQueueIds===null||runningQueueIds===void 0?void 0:runningQueueIds.size)===0){runningQueueIdsByName.delete(this.name);}}/**
|
|
1044
1115
|
* Starts processing the queue
|
|
1045
|
-
*/start(){if(this.scheduleTimeoutActive){this.stop();}const runningQueueIds=runningQueueIdsByName.get(this.name)
|
|
1116
|
+
*/start(){var _runningQueueIdsByNam;if(this.scheduleTimeoutActive){this.stop();}const runningQueueIds=(_runningQueueIdsByNam=runningQueueIdsByName.get(this.name))!==null&&_runningQueueIdsByNam!==void 0?_runningQueueIdsByNam:new Set();if(runningQueueIds.size>0&&!runningQueueIds.has(this.id)){var _this$logger;(_this$logger=this.logger)===null||_this$logger===void 0||_this$logger.error(RETRY_QUEUE_NAME_COLLISION_ERROR(RETRY_QUEUE,this.name));}runningQueueIds.add(this.id);runningQueueIdsByName.set(this.name,runningQueueIds);this.scheduleTimeoutActive=true;this.scheduleFlushBatch();this.ack();this.checkReclaim();this.processHead();}/**
|
|
1046
1117
|
* Configures the timeout handler for flushing the batch queue
|
|
1047
|
-
*/scheduleFlushBatch(){if(this.batch.enabled&&this.batch
|
|
1118
|
+
*/scheduleFlushBatch(){var _this$batch;if(this.batch.enabled&&(_this$batch=this.batch)!==null&&_this$batch!==void 0&&_this$batch.flushInterval){if(this.flushBatchTaskId){this.schedule.cancel(this.flushBatchTaskId);}this.flushBatchTaskId=this.schedule.run(this.flushBatch,this.batch.flushInterval,ScheduleModes.ASAP);}}/**
|
|
1048
1119
|
* Flushes the batch queue
|
|
1049
|
-
*/flushBatch(isAccessible=true){if(!this.batchingInProgress){this.isPageAccessible=isAccessible;this.batchingInProgress=true;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)
|
|
1120
|
+
*/flushBatch(isAccessible=true){if(!this.batchingInProgress){var _ref;this.isPageAccessible=isAccessible;this.batchingInProgress=true;let batchQueue=(_ref=this.getStorageEntry(QueueStatuses.BATCH_QUEUE))!==null&&_ref!==void 0?_ref:[];if(batchQueue.length>0){batchQueue=batchQueue.slice(-batchQueue.length);const batchEntry=this.genQueueItem(batchQueue.map(queueItem=>queueItem.item),BATCH_QUEUE_ITEM_TYPE);this.setStorageEntry(QueueStatuses.BATCH_QUEUE,[]);this.pushToMainQueue(batchEntry);}this.batchingInProgress=false;// Re-schedule the flush task
|
|
1050
1121
|
this.scheduleFlushBatch();}}/**
|
|
1051
1122
|
* Decides whether to retry. Overridable.
|
|
1052
1123
|
*
|
|
@@ -1058,16 +1129,18 @@ this.scheduleFlushBatch();}}/**
|
|
|
1058
1129
|
*
|
|
1059
1130
|
* @param {Number} attemptNumber The attemptNumber (1 for first retry)
|
|
1060
1131
|
* @return {Number} The delay in milliseconds to wait before attempting a retry
|
|
1061
|
-
*/getDelay(attemptNumber){
|
|
1132
|
+
*/getDelay(attemptNumber){// Cap leaves headroom for +jitter so the jittered delay never exceeds maxRetryDelay
|
|
1133
|
+
const cap=Math.floor(this.backoff.maxRetryDelay/(1+this.backoff.jitter));let ms=Math.min(// First retry waits the base delay
|
|
1134
|
+
Number((this.backoff.minRetryDelay*this.backoff.factor**(attemptNumber-1)).toPrecision(1)),cap);if(this.backoff.jitter){const rand=Math.random();const deviation=Math.floor(rand*this.backoff.jitter*ms);if(Math.floor(rand*10)<5){ms-=deviation;}else {ms+=deviation;}}return Math.min(ms,this.backoff.maxRetryDelay);}enqueue(entry){let curEntry;if(this.batch.enabled&&entry.type===SINGLE_QUEUE_ITEM_TYPE){curEntry=this.handleNewItemForBatch(entry);}else {curEntry=entry;}// when batching is enabled, `curEntry` could be `undefined` if the batch criteria is not met
|
|
1062
1135
|
if(curEntry){this.pushToMainQueue(curEntry);}}/**
|
|
1063
1136
|
* Handles a new item added to the retry queue when batching is enabled
|
|
1064
1137
|
* @param entry New item added to the retry queue
|
|
1065
1138
|
* @returns Undefined or batch entry object
|
|
1066
|
-
*/handleNewItemForBatch(entry){let curEntry;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)
|
|
1139
|
+
*/handleNewItemForBatch(entry){var _ref2;let curEntry;let batchQueue=(_ref2=this.getStorageEntry(QueueStatuses.BATCH_QUEUE))!==null&&_ref2!==void 0?_ref2:[];if(!this.batchingInProgress){this.batchingInProgress=true;batchQueue=batchQueue.slice(-batchQueue.length);batchQueue.push(entry);const batchDispatchInfo=this.getBatchDispatchInfo(batchQueue);// if batch criteria is met, queue the batch events to the main queue and clear batch queue
|
|
1067
1140
|
if(batchDispatchInfo.criteriaMet||batchDispatchInfo.criteriaExceeded){let batchEntries;if(batchDispatchInfo.criteriaExceeded){batchEntries=batchQueue.slice(0,batchQueue.length-1);batchQueue=[entry];}else {batchEntries=batchQueue;batchQueue=[];}// Don't make any batch request if there are no items
|
|
1068
1141
|
if(batchEntries.length>0){const isReclaimed=batchEntries.every(queueItem=>queueItem.reclaimed);const batchItems=batchEntries.map(queueItem=>queueItem.item);if(isReclaimed){curEntry=this.genQueueItem(batchItems,BATCH_QUEUE_ITEM_TYPE,true);}else {curEntry=this.genQueueItem(batchItems,BATCH_QUEUE_ITEM_TYPE);}}// re-attach the timeout handler
|
|
1069
1142
|
this.scheduleFlushBatch();}this.batchingInProgress=false;}else {batchQueue.push(entry);}// update the batch queue
|
|
1070
|
-
this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}pushToMainQueue(curEntry){let queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1143
|
+
this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}pushToMainQueue(curEntry){var _ref3;let queue=(_ref3=this.getStorageEntry(QueueStatuses.QUEUE))!==null&&_ref3!==void 0?_ref3:[];if(this.maxItems>1){queue=queue.slice(-(this.maxItems-1));}else {queue=[];}queue.push(curEntry);queue=queue.sort(sortByTime);this.setStorageEntry(QueueStatuses.QUEUE,queue);if(this.scheduleTimeoutActive){this.processHead();}}/**
|
|
1071
1144
|
* Adds an item to the queue
|
|
1072
1145
|
*
|
|
1073
1146
|
* @param {Object} itemData The item to process
|
|
@@ -1075,51 +1148,51 @@ this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}push
|
|
|
1075
1148
|
* Generates a queue item
|
|
1076
1149
|
* @param itemData Queue item data
|
|
1077
1150
|
* @returns Queue item
|
|
1078
|
-
*/genQueueItem(itemData,type=SINGLE_QUEUE_ITEM_TYPE,reclaimed){return {item:itemData,attemptNumber:0,time:this.schedule.now(),id:generateUUID(),type
|
|
1151
|
+
*/genQueueItem(itemData,type=SINGLE_QUEUE_ITEM_TYPE,reclaimed){return _objectSpread2({item:itemData,attemptNumber:0,time:this.schedule.now(),id:generateUUID(),type},isDefined(reclaimed)?{reclaimed}:{});}/**
|
|
1079
1152
|
* Adds an item to the retry queue
|
|
1080
1153
|
*
|
|
1081
1154
|
* @param {Object} qItem The item to process
|
|
1082
1155
|
*/requeue(qItem){const{attemptNumber,item,type,id,firstAttemptedAt,lastAttemptedAt,reclaimed,retryReason}=qItem;// Increment the attempt number as we're about to retry
|
|
1083
|
-
const attemptNumberToUse=attemptNumber+1;if(this.shouldRetry(item,attemptNumberToUse)){this.enqueue({item,attemptNumber:attemptNumberToUse,time:this.schedule.now()+this.getDelay(attemptNumberToUse),id:id
|
|
1156
|
+
const attemptNumberToUse=attemptNumber+1;if(this.shouldRetry(item,attemptNumberToUse)){this.enqueue({item,attemptNumber:attemptNumberToUse,time:this.schedule.now()+this.getDelay(attemptNumberToUse),id:id!==null&&id!==void 0?id:generateUUID(),type,firstAttemptedAt,lastAttemptedAt,reclaimed,retryReason});}}/**
|
|
1084
1157
|
* Returns the information about whether the batch criteria is met or exceeded
|
|
1085
1158
|
* @param batchItems Prospective batch items
|
|
1086
1159
|
* @returns Batch dispatch info
|
|
1087
|
-
*/getBatchDispatchInfo(batchItems){let lengthCriteriaMet=false;let lengthCriteriaExceeded=false;const configuredBatchMaxItems=this.batch
|
|
1160
|
+
*/getBatchDispatchInfo(batchItems){var _this$batch2,_this$batch3;let lengthCriteriaMet=false;let lengthCriteriaExceeded=false;const configuredBatchMaxItems=(_this$batch2=this.batch)===null||_this$batch2===void 0?void 0:_this$batch2.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$batch3=this.batch)===null||_this$batch3===void 0?void 0:_this$batch3.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(){var _ref4,_ref6,_ref8;// cancel the scheduled task if it exists
|
|
1088
1161
|
this.schedule.cancel(this.processId);// Pop the head off the queue
|
|
1089
|
-
let queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1090
|
-
const processItemCallback=(el,id)=>(err,res)=>{const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)
|
|
1162
|
+
let queue=(_ref4=this.getStorageEntry(QueueStatuses.QUEUE))!==null&&_ref4!==void 0?_ref4:[];const now=this.schedule.now();const toRun=[];// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1163
|
+
const processItemCallback=(el,id)=>(err,res)=>{var _ref5;const inProgress=(_ref5=this.getStorageEntry(QueueStatuses.IN_PROGRESS))!==null&&_ref5!==void 0?_ref5:{};const inProgressItem=inProgress[id];const firstAttemptedAt=inProgressItem===null||inProgressItem===void 0?void 0:inProgressItem.firstAttemptedAt;const lastAttemptedAt=inProgressItem===null||inProgressItem===void 0?void 0:inProgressItem.lastAttemptedAt;delete inProgress[id];this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);if(err){var _res$retryReason;this.requeue(_objectSpread2(_objectSpread2({},el),{},{firstAttemptedAt,lastAttemptedAt,retryReason:(_res$retryReason=res===null||res===void 0?void 0:res.retryReason)!==null&&_res$retryReason!==void 0?_res$retryReason:DEFAULT_RETRY_REASON}));}};const enqueueItem=(el,id)=>{toRun.push({id,item:el.item,done:processItemCallback(el,id),attemptNumber:el.attemptNumber});};const inProgress=(_ref6=this.getStorageEntry(QueueStatuses.IN_PROGRESS))!==null&&_ref6!==void 0?_ref6:{};let inProgressSize=Object.keys(inProgress).length;// eslint-disable-next-line no-plusplus
|
|
1091
1164
|
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
|
|
1092
1165
|
inProgress[id]={item:el.item,attemptNumber:el.attemptNumber,time:this.schedule.now(),type:el.type,firstAttemptedAt:el.firstAttemptedAt,lastAttemptedAt:el.lastAttemptedAt,reclaimed:el.reclaimed};enqueueItem(el,id);}}this.setStorageEntry(QueueStatuses.QUEUE,queue);this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);toRun.forEach(el=>{// TODO: handle processQueueCb timeout
|
|
1093
|
-
try{const now=this.schedule.now();const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)
|
|
1094
|
-
reclaimed=inProgressItem.reclaimed
|
|
1166
|
+
try{var _ref7;const now=this.schedule.now();const inProgress=(_ref7=this.getStorageEntry(QueueStatuses.IN_PROGRESS))!==null&&_ref7!==void 0?_ref7:{};const inProgressItem=inProgress[el.id];let firstAttemptedAt=now;let lastAttemptedAt=now;let reclaimed=false;let retryReason=DEFAULT_RETRY_REASON;if(inProgressItem){var _inProgressItem$retry,_inProgressItem$first,_inProgressItem$lastA,_inProgressItem$recla;retryReason=(_inProgressItem$retry=inProgressItem.retryReason)!==null&&_inProgressItem$retry!==void 0?_inProgressItem$retry:retryReason;firstAttemptedAt=(_inProgressItem$first=inProgressItem.firstAttemptedAt)!==null&&_inProgressItem$first!==void 0?_inProgressItem$first:firstAttemptedAt;lastAttemptedAt=(_inProgressItem$lastA=inProgressItem.lastAttemptedAt)!==null&&_inProgressItem$lastA!==void 0?_inProgressItem$lastA:lastAttemptedAt;// Indicates if the item has been reclaimed from local storage
|
|
1167
|
+
reclaimed=(_inProgressItem$recla=inProgressItem.reclaimed)!==null&&_inProgressItem$recla!==void 0?_inProgressItem$recla:reclaimed;// Update the first attempted at timestamp for the in progress item
|
|
1095
1168
|
inProgressItem.firstAttemptedAt=firstAttemptedAt;// Update the last attempted at to current timestamp for the in progress item
|
|
1096
1169
|
inProgressItem.lastAttemptedAt=now;inProgress[el.id]=inProgressItem;this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);}// A decimal integer representing the milliseconds since the first attempt
|
|
1097
1170
|
const timeSinceFirstAttempt=now-firstAttemptedAt;// A decimal integer representing the milliseconds since the last attempt
|
|
1098
|
-
const timeSinceLastAttempt=now-lastAttemptedAt;const willBeRetried=this.shouldRetry(el.item,el.attemptNumber+1);this.processQueueCb(el.item,el.done,{retryAttemptNumber:el.attemptNumber,maxRetryAttempts:this.maxAttempts,willBeRetried,timeSinceFirstAttempt,timeSinceLastAttempt,reclaimed,isPageAccessible:this.isPageAccessible,retryReason});}catch(err){let errMsg='';if(el.attemptNumber<this.maxAttempts){errMsg='The item will be requeued.';if(el.attemptNumber>0){errMsg=`${errMsg} Retry attempt ${el.attemptNumber} of ${this.maxAttempts}.`;}// requeue the item to be retried
|
|
1171
|
+
const timeSinceLastAttempt=now-lastAttemptedAt;const willBeRetried=this.shouldRetry(el.item,el.attemptNumber+1);this.processQueueCb(el.item,el.done,{retryAttemptNumber:el.attemptNumber,maxRetryAttempts:this.maxAttempts,willBeRetried,timeSinceFirstAttempt,timeSinceLastAttempt,reclaimed,isPageAccessible:this.isPageAccessible,retryReason});}catch(err){var _this$logger2;let errMsg='';if(el.attemptNumber<this.maxAttempts){errMsg='The item will be requeued.';if(el.attemptNumber>0){errMsg=`${errMsg} Retry attempt ${el.attemptNumber} of ${this.maxAttempts}.`;}// requeue the item to be retried
|
|
1099
1172
|
el.done(err);}else {errMsg=`Retries exhausted (${this.maxAttempts}). The item will be dropped.`;// drop the event as we're unable to process it
|
|
1100
1173
|
// after the max attempts are exhausted
|
|
1101
|
-
el.done();}this.logger
|
|
1102
|
-
queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1174
|
+
el.done();}(_this$logger2=this.logger)===null||_this$logger2===void 0||_this$logger2.error(RETRY_QUEUE_PROCESS_ERROR(RETRY_QUEUE,errMsg),err);}});// re-read the queue in case the process function finished immediately or added another item
|
|
1175
|
+
queue=(_ref8=this.getStorageEntry(QueueStatuses.QUEUE))!==null&&_ref8!==void 0?_ref8:[];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
|
|
1103
1176
|
ack(){this.setStorageEntry(QueueStatuses.ACK,this.schedule.now());if(this.reclaimStartVal!=null){this.reclaimStartVal=null;this.setStorageEntry(QueueStatuses.RECLAIM_START,null);}if(this.reclaimEndVal!=null){this.reclaimEndVal=null;this.setStorageEntry(QueueStatuses.RECLAIM_END,null);}this.schedule.run(this.ack,this.timeouts.ackTimer,ScheduleModes.ASAP);}/**
|
|
1104
1177
|
* Take over the items of another queue.
|
|
1105
1178
|
*
|
|
1106
1179
|
* Reads through the handle `findOtherQueues` discovered rather than building a
|
|
1107
1180
|
* fresh one: a quota error during the handshake swaps that handle to the
|
|
1108
1181
|
* in-memory engine, and a new localStorage store would find nothing.
|
|
1109
|
-
*/reclaim(other){const our={queue:this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1182
|
+
*/reclaim(other){var _this$getStorageEntry,_other$get,_other$get2,_other$get3;const our={queue:(_this$getStorageEntry=this.getStorageEntry(QueueStatuses.QUEUE))!==null&&_this$getStorageEntry!==void 0?_this$getStorageEntry:[]};const their={inProgress:(_other$get=other.get(QueueStatuses.IN_PROGRESS))!==null&&_other$get!==void 0?_other$get:{},batchQueue:(_other$get2=other.get(QueueStatuses.BATCH_QUEUE))!==null&&_other$get2!==void 0?_other$get2:[],queue:(_other$get3=other.get(QueueStatuses.QUEUE))!==null&&_other$get3!==void 0?_other$get3:[]};const trackMessageIds=[];const addConcatQueue=(queue,incrementAttemptNumberBy)=>{const concatIterator=el=>{var _el$id;const id=(_el$id=el.id)!==null&&_el$id!==void 0?_el$id:generateUUID();if(trackMessageIds.includes(id));else {var _el$type;// Hack to determine the item type by the contents of the entry
|
|
1110
1183
|
// After some point, we can remove this hack as most of the stale data will have been processed
|
|
1111
1184
|
// and the new entries will have the type field set
|
|
1112
|
-
const type=Array.isArray(el.item)?BATCH_QUEUE_ITEM_TYPE:SINGLE_QUEUE_ITEM_TYPE;our.queue.push({item:el.item,attemptNumber:el.attemptNumber+incrementAttemptNumberBy,time:this.schedule.now(),id,type:el.type
|
|
1185
|
+
const type=Array.isArray(el.item)?BATCH_QUEUE_ITEM_TYPE:SINGLE_QUEUE_ITEM_TYPE;our.queue.push({item:el.item,attemptNumber:el.attemptNumber+incrementAttemptNumberBy,time:this.schedule.now(),id,type:(_el$type=el.type)!==null&&_el$type!==void 0?_el$type:type,firstAttemptedAt:el.firstAttemptedAt,lastAttemptedAt:el.lastAttemptedAt,retryReason:el.retryReason,// Mark the item as reclaimed from local storage
|
|
1113
1186
|
reclaimed:true});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#
|
|
1114
1187
|
addConcatQueue(their.queue,0);// Process batch queue items
|
|
1115
|
-
if(this.batch.enabled){their.batchQueue.forEach(el=>{const id=el.id
|
|
1116
|
-
reclaimed:true,type:el.type
|
|
1188
|
+
if(this.batch.enabled){their.batchQueue.forEach(el=>{var _el$id2;const id=(_el$id2=el.id)!==null&&_el$id2!==void 0?_el$id2:generateUUID();if(trackMessageIds.includes(id));else {var _el$type2;this.enqueue(_objectSpread2(_objectSpread2({},el),{},{id,retryReason:el.retryReason,// Mark the item as reclaimed from local storage
|
|
1189
|
+
reclaimed:true,type:(_el$type2=el.type)!==null&&_el$type2!==void 0?_el$type2:SINGLE_QUEUE_ITEM_TYPE,time:this.schedule.now()}));trackMessageIds.push(id);}});}else {// if batching is not enabled in the current instance, add those items to the main queue directly
|
|
1117
1190
|
addConcatQueue(their.batchQueue,0);}// if the queue is abandoned, all the in-progress are failed. retry them immediately and increment the attempt#
|
|
1118
1191
|
addConcatQueue(their.inProgress,1);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
|
|
1119
1192
|
this.clearQueueEntries(other,1);// process the new items we claimed
|
|
1120
1193
|
this.processHead();}clearQueueEntries(other,localStorageBackoff){this.removeStorageEntry(other,0,localStorageBackoff);}removeStorageEntry(store,entryIdx,backoff,attempt=1){const maxAttempts=2;const queueEntryKeys=Object.keys(QueueStatuses);const entry=QueueStatuses[queueEntryKeys[entryIdx]];globalThis.setTimeout(()=>{try{store.remove(entry);// clear the next entry
|
|
1121
1194
|
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
|
|
1122
|
-
this.removeStorageEntry(store,entryIdx,backoff+40,attempt+1);}else {this.logger
|
|
1195
|
+
this.removeStorageEntry(store,entryIdx,backoff+40,attempt+1);}else {var _this$logger3;(_this$logger3=this.logger)===null||_this$logger3===void 0||_this$logger3.error(RETRY_QUEUE_ENTRY_REMOVE_ERROR(RETRY_QUEUE,entry,attempt),err);}// clear the next entry after we've exhausted our attempts
|
|
1123
1196
|
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);};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 storageEngine=this.store.getOriginalEngine();let storageKeys=[];// 'keys' API is not supported by all the core SDK versions
|
|
1124
1197
|
// Hence, we need this backward compatibility check
|
|
1125
1198
|
if(isFunction(storageEngine.keys)){storageKeys=storageEngine.keys();}else {for(let i=0;i<storageEngine.length;i++){const key=storageEngine.key(i);if(key){storageKeys.push(key);}}}storageKeys.forEach(k=>{const keyParts=k?k.split('.'):[];if(keyParts.length>=3&&keyParts[0]===name&&keyParts[1]!==this.id&&keyParts[2]===QueueStatuses.ACK){res.push(this.storeManager.setStore({id:keyParts[1],name,validKeys:QueueStatuses,type:LOCAL_STORAGE,// This store stands in for another queue's entries. If its storage is
|
|
@@ -1135,14 +1208,14 @@ const pluginName$7='BeaconQueue';const BeaconQueue=()=>({name:pluginName$7,deps:
|
|
|
1135
1208
|
* @param errorHandler Error handler instance
|
|
1136
1209
|
* @param logger Logger instance
|
|
1137
1210
|
* @returns BeaconItemsQueue instance
|
|
1138
|
-
*/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
|
|
1139
|
-
done(null);return;}try{if(!navigator.sendBeacon(url,data)){if(isPageAccessible){logger
|
|
1211
|
+
*/init(state,httpClient,storeManager,errorHandler,logger){var _state$loadOptions$va;const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions((_state$loadOptions$va=state.loadOptions.value.beaconQueueOptions)!==null&&_state$loadOptions$va!==void 0?_state$loadOptions$va:{});const queueProcessCallback=(itemData,done,info)=>{const{isPageAccessible}=info;logger===null||logger===void 0||logger.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const currentTime=getCurrentTimeFormatted();const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event,currentTime));const data=getBatchDeliveryPayload$1(finalEvents,currentTime,logger);if(!data){// Mark the item as done so that it can be removed from the queue
|
|
1212
|
+
done(null);return;}try{if(!navigator.sendBeacon(url,data)){if(isPageAccessible){logger===null||logger===void 0||logger.error(`${BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN,url)} The event(s) will be dropped.`);// Remove the item from queue
|
|
1140
1213
|
done(null);}else {// Note: We're not removing the item from the queue as we want to retry the request
|
|
1141
|
-
logger
|
|
1142
|
-
done(null);}}catch(err){errorHandler
|
|
1214
|
+
logger===null||logger===void 0||logger.warn(`${BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN,url)} The event(s) will be retried as the current page is being unloaded.`);}}else {// Remove the item from queue as the request was successful
|
|
1215
|
+
done(null);}}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:BEACON_QUEUE_PLUGIN,customMessage:BEACON_QUEUE_DELIVERY_ERROR(url)});// Remove the item from queue
|
|
1143
1216
|
done(null);}};const eventsQueue=new RetryQueue(`${QUEUE_NAME$1}_${writeKey}`,{batch:{enabled:true,flushInterval:finalQOpts.flushQueueInterval,maxSize:MAX_BATCH_PAYLOAD_SIZE_BYTES,// set the hard limit
|
|
1144
|
-
maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,getStorageTypeForEventsPersistence(logger),logger,itemData=>{const currentTime=getCurrentTimeFormatted();const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
|
|
1145
|
-
return getBatchDeliveryPayload$1(events,currentTime,logger).size;});return eventsQueue;},/**
|
|
1217
|
+
maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,getStorageTypeForEventsPersistence(logger),logger,itemData=>{var _getBatchDeliveryPayl;const currentTime=getCurrentTimeFormatted();const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
|
|
1218
|
+
return (_getBatchDeliveryPayl=getBatchDeliveryPayload$1(events,currentTime,logger))===null||_getBatchDeliveryPayl===void 0?void 0:_getBatchDeliveryPayl.size;});return eventsQueue;},/**
|
|
1146
1219
|
* Add event to the queue for delivery
|
|
1147
1220
|
* @param state Application state
|
|
1148
1221
|
* @param eventsQueue IQueue instance
|
|
@@ -1160,22 +1233,22 @@ const DESTINATION_CONSENT_STATUS_ERROR$3=`Failed to determine the consent status
|
|
|
1160
1233
|
|
|
1161
1234
|
const pluginName$6='CustomConsentManager';const CustomConsentManager=()=>({name:pluginName$6,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$6];},consentManager:{init(state,logger){// Nothing to initialize
|
|
1162
1235
|
},updateConsentsInfo(state,storeManager,logger){// Nothing to update. Already provided by the user
|
|
1163
|
-
},isDestinationConsented(state,destConfig,errorHandler,logger){if(!state.consents.initialized.value){return true;}const allowedConsentIds=state.consents.data.value.allowedConsentIds;try{const{consentManagement}=destConfig;// If the destination does not have consent management config, events should be sent.
|
|
1236
|
+
},isDestinationConsented(state,destConfig,errorHandler,logger){if(!state.consents.initialized.value){return true;}const allowedConsentIds=state.consents.data.value.allowedConsentIds;try{var _cmpConfig$resolution;const{consentManagement}=destConfig;// If the destination does not have consent management config, events should be sent.
|
|
1164
1237
|
if(!consentManagement){return true;}// Get the corresponding consents for the destination
|
|
1165
1238
|
const cmpConfig=consentManagement.find(c=>c.provider===state.consents.provider.value);// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1166
|
-
if(!cmpConfig
|
|
1239
|
+
if(!(cmpConfig!==null&&cmpConfig!==void 0&&cmpConfig.consents)){return true;}const configuredConsents=cmpConfig.consents.map(c=>c.consent.trim()).filter(n=>n);const resolutionStrategy=(_cmpConfig$resolution=cmpConfig.resolutionStrategy)!==null&&_cmpConfig$resolution!==void 0?_cmpConfig$resolution:state.consents.resolutionStrategy.value;// match the configured consents with user provided consents as per
|
|
1167
1240
|
// the configured resolution strategy
|
|
1168
|
-
const matchPredicate=consent=>allowedConsentIds.includes(consent);switch(resolutionStrategy){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}}catch(err){errorHandler
|
|
1241
|
+
const matchPredicate=consent=>allowedConsentIds.includes(consent);switch(resolutionStrategy){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:CUSTOM_CONSENT_MANAGER_PLUGIN,customMessage:DESTINATION_CONSENT_STATUS_ERROR$3});return true;}}}});
|
|
1169
1242
|
|
|
1170
1243
|
const externallyLoadedSessionStorageKeys={segment:'ajs_anonymous_id'};
|
|
1171
1244
|
|
|
1172
1245
|
const getSegmentAnonymousId=getStorageEngine=>{let anonymousId;/**
|
|
1173
1246
|
* First check the local storage for anonymousId
|
|
1174
1247
|
* Ref: https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/#identify
|
|
1175
|
-
*/const lsEngine=getStorageEngine(LOCAL_STORAGE);if(lsEngine
|
|
1176
|
-
const csEngine=getStorageEngine(COOKIE_STORAGE);if(!anonymousId&&csEngine
|
|
1248
|
+
*/const lsEngine=getStorageEngine(LOCAL_STORAGE);if(lsEngine!==null&&lsEngine!==void 0&&lsEngine.isEnabled){anonymousId=lsEngine.getItem(externallyLoadedSessionStorageKeys.segment);}// If anonymousId is not present in local storage and find it in cookies
|
|
1249
|
+
const csEngine=getStorageEngine(COOKIE_STORAGE);if(!anonymousId&&csEngine!==null&&csEngine!==void 0&&csEngine.isEnabled){anonymousId=csEngine.getItem(externallyLoadedSessionStorageKeys.segment);}return anonymousId;};
|
|
1177
1250
|
|
|
1178
|
-
const pluginName$5='ExternalAnonymousId';const ExternalAnonymousId=()=>({name:pluginName$5,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$5];},storage:{getAnonymousId(getStorageEngine,options){let anonymousId;if(options
|
|
1251
|
+
const pluginName$5='ExternalAnonymousId';const ExternalAnonymousId=()=>({name:pluginName$5,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$5];},storage:{getAnonymousId(getStorageEngine,options){var _options$autoCapture;let anonymousId;if(options!==null&&options!==void 0&&(_options$autoCapture=options.autoCapture)!==null&&_options$autoCapture!==void 0&&_options$autoCapture.enabled&&options.autoCapture.source){const source=options.autoCapture.source.toLowerCase();if(!Object.keys(externallyLoadedSessionStorageKeys).includes(source)){return anonymousId;}// eslint-disable-next-line sonarjs/no-small-switch
|
|
1179
1252
|
switch(source){case 'segment':anonymousId=getSegmentAnonymousId(getStorageEngine);break;}}return anonymousId;}}});
|
|
1180
1253
|
|
|
1181
1254
|
const IUBENDA_CONSENT_COOKIE_READ_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to read the consent cookie.`;const IUBENDA_CONSENT_COOKIE_PARSE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to parse the consent cookie.`;const DESTINATION_CONSENT_STATUS_ERROR$2=`Failed to determine the consent status for the destination. Please check the destination configuration and try again.`;
|
|
@@ -1185,13 +1258,13 @@ const IUBENDA_CONSENT_MANAGER_PLUGIN='IubendaConsentManagerPlugin';const IUBENDA
|
|
|
1185
1258
|
const getIubendaCookieName=logger=>{try{// Retrieve cookies as a string and split them into an array
|
|
1186
1259
|
const cookies=document.cookie.split('; ');// Find the cookie that matches the iubenda cookie pattern
|
|
1187
1260
|
const matchedCookie=cookies.find(cookie=>{const[name]=cookie.split('=');return IUBENDA_CONSENT_COOKIE_NAME_PATTERN.test((name||'').trim());});if(!matchedCookie){throw new Error('Iubenda Cookie not found with the specified pattern.');}// Extract and return the cookie name
|
|
1188
|
-
const[name]=matchedCookie.split('=');return name||'';}catch(err){logger
|
|
1261
|
+
const[name]=matchedCookie.split('=');return name||'';}catch(err){logger===null||logger===void 0||logger.error(IUBENDA_CONSENT_COOKIE_READ_ERROR(IUBENDA_CONSENT_MANAGER_PLUGIN),err);return '';}};/**
|
|
1189
1262
|
* Gets the consent data from the Iubenda's consent cookie
|
|
1190
1263
|
* @param storeManager Store manager instance
|
|
1191
1264
|
* @param logger Logger instance
|
|
1192
1265
|
* @returns Consent data from the consent cookie
|
|
1193
|
-
*/const getIubendaConsentData=(storeManager,logger)=>{let rawConsentCookieData=null;try{const dataStore=storeManager
|
|
1194
|
-
let consentCookieData;try{consentCookieData=JSON.parse(decodeURIComponent(rawConsentCookieData));}catch(err){logger
|
|
1266
|
+
*/const getIubendaConsentData=(storeManager,logger)=>{let rawConsentCookieData=null;try{const dataStore=storeManager===null||storeManager===void 0?void 0:storeManager.setStore({id:IUBENDA_CONSENT_MANAGER_PLUGIN,name:IUBENDA_CONSENT_MANAGER_PLUGIN,type:COOKIE_STORAGE,errorHandler:storeManager===null||storeManager===void 0?void 0:storeManager.errorHandler,logger:storeManager===null||storeManager===void 0?void 0:storeManager.logger});rawConsentCookieData=dataStore===null||dataStore===void 0?void 0:dataStore.engine.getItem(getIubendaCookieName(logger));}catch(err){logger===null||logger===void 0||logger.error(IUBENDA_CONSENT_COOKIE_READ_ERROR(IUBENDA_CONSENT_MANAGER_PLUGIN),err);return undefined;}if(isNullOrUndefined(rawConsentCookieData)){return undefined;}// Decode and parse the cookie data to JSON
|
|
1267
|
+
let consentCookieData;try{consentCookieData=JSON.parse(decodeURIComponent(rawConsentCookieData));}catch(err){logger===null||logger===void 0||logger.error(IUBENDA_CONSENT_COOKIE_PARSE_ERROR(IUBENDA_CONSENT_MANAGER_PLUGIN),err);return undefined;}if(!consentCookieData){return undefined;}// Convert the cookie data to consent data
|
|
1195
1268
|
const consentPurposes=consentCookieData.purposes;return consentPurposes;};/**
|
|
1196
1269
|
* Gets the consent data in the format expected by the application state
|
|
1197
1270
|
* @param iubendaConsentData Consent data derived from the consent cookie
|
|
@@ -1200,18 +1273,18 @@ const consentPurposes=consentCookieData.purposes;return consentPurposes;};/**
|
|
|
1200
1273
|
|
|
1201
1274
|
const pluginName$4='IubendaConsentManager';const IubendaConsentManager=()=>({name:pluginName$4,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$4];},consentManager:{init(state,logger){// getIubendaUserConsentedPurposes returns current iubenda opted-in purposes
|
|
1202
1275
|
// This will be helpful for debugging
|
|
1203
|
-
globalThis.getIubendaUserConsentedPurposes=()=>state.consents.data.value.allowedConsentIds
|
|
1276
|
+
globalThis.getIubendaUserConsentedPurposes=()=>{var _state$consents$data$;return (_state$consents$data$=state.consents.data.value.allowedConsentIds)===null||_state$consents$data$===void 0?void 0:_state$consents$data$.slice();};// getIubendaUserDeniedPurposes returns current Iubenda opted-out purposes
|
|
1204
1277
|
// This will be helpful for debugging
|
|
1205
|
-
globalThis.getIubendaUserDeniedPurposes=()=>state.consents.data.value.deniedConsentIds
|
|
1278
|
+
globalThis.getIubendaUserDeniedPurposes=()=>{var _state$consents$data$2;return (_state$consents$data$2=state.consents.data.value.deniedConsentIds)===null||_state$consents$data$2===void 0?void 0:_state$consents$data$2.slice();};// updateIubendaConsent callback function to update current consent purpose state
|
|
1206
1279
|
globalThis.updateIubendaConsent=iubendaConsentData=>{updateConsentStateFromData$1(state,iubendaConsentData);};},updateConsentsInfo(state,storeManager,logger){// retrieve consent data and update the state
|
|
1207
1280
|
let iubendaConsentData;// From window
|
|
1208
1281
|
if(!isUndefined(globalThis._iub.cs.consent.purposes)){iubendaConsentData=globalThis._iub.cs.consent.purposes;// From cookie
|
|
1209
1282
|
}else {iubendaConsentData=getIubendaConsentData(storeManager,logger);}updateConsentStateFromData$1(state,iubendaConsentData);},isDestinationConsented(state,destConfig,errorHandler,logger){if(!state.consents.initialized.value){return true;}const allowedConsentIds=state.consents.data.value.allowedConsentIds;const matchPredicate=consent=>allowedConsentIds.includes(consent);try{const{consentManagement}=destConfig;// If the destination does not have consent management config, events should be sent.
|
|
1210
|
-
if(consentManagement){
|
|
1283
|
+
if(consentManagement){var _cmpConfig$resolution;// Get the corresponding consents for the destination
|
|
1211
1284
|
const cmpConfig=consentManagement.find(c=>c.provider===state.consents.provider.value);// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1212
|
-
if(!cmpConfig
|
|
1285
|
+
if(!(cmpConfig!==null&&cmpConfig!==void 0&&cmpConfig.consents)){return true;}const configuredConsents=cmpConfig.consents.map(c=>c.consent.trim()).filter(n=>n);const resolutionStrategy=(_cmpConfig$resolution=cmpConfig.resolutionStrategy)!==null&&_cmpConfig$resolution!==void 0?_cmpConfig$resolution:state.consents.resolutionStrategy.value;// match the configured consents with user provided consents as per
|
|
1213
1286
|
// the configured resolution strategy
|
|
1214
|
-
switch(resolutionStrategy){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}}return true;}catch(err){errorHandler
|
|
1287
|
+
switch(resolutionStrategy){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}}return true;}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:IUBENDA_CONSENT_MANAGER_PLUGIN,customMessage:DESTINATION_CONSENT_STATUS_ERROR$2});return true;}}}});
|
|
1215
1288
|
|
|
1216
1289
|
const KETCH_CONSENT_COOKIE_READ_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to read the consent cookie.`;const KETCH_CONSENT_COOKIE_PARSE_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to parse the consent cookie.`;const DESTINATION_CONSENT_STATUS_ERROR$1=`Failed to determine the consent status for the destination. Please check the destination configuration and try again.`;
|
|
1217
1290
|
|
|
@@ -1223,9 +1296,9 @@ const KETCH_CONSENT_MANAGER_PLUGIN='KetchConsentManagerPlugin';const KETCH_CONSE
|
|
|
1223
1296
|
* @param logger Logger instance
|
|
1224
1297
|
* @returns Consent data from the consent cookie
|
|
1225
1298
|
*/const getKetchConsentData=(storeManager,logger)=>{let rawConsentCookieData=null;try{// Create a data store instance to read the consent cookie
|
|
1226
|
-
const dataStore=storeManager
|
|
1227
|
-
let consentCookieData;try{consentCookieData=JSON.parse(fromBase64(rawConsentCookieData));}catch(err){logger
|
|
1228
|
-
const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{const purposeCode=pEntry[0];const purposeValue=pEntry[1];consentPurposes[purposeCode]=purposeValue
|
|
1299
|
+
const dataStore=storeManager===null||storeManager===void 0?void 0:storeManager.setStore({id:KETCH_CONSENT_MANAGER_PLUGIN,name:KETCH_CONSENT_MANAGER_PLUGIN,type:COOKIE_STORAGE,errorHandler:storeManager===null||storeManager===void 0?void 0:storeManager.errorHandler,logger:storeManager===null||storeManager===void 0?void 0:storeManager.logger});rawConsentCookieData=dataStore===null||dataStore===void 0?void 0:dataStore.engine.getItem(KETCH_CONSENT_COOKIE_NAME_V1);}catch(err){logger===null||logger===void 0||logger.error(KETCH_CONSENT_COOKIE_READ_ERROR(KETCH_CONSENT_MANAGER_PLUGIN),err);return undefined;}if(isNullOrUndefined(rawConsentCookieData)){return undefined;}// Decode and parse the cookie data to JSON
|
|
1300
|
+
let consentCookieData;try{consentCookieData=JSON.parse(fromBase64(rawConsentCookieData));}catch(err){logger===null||logger===void 0||logger.error(KETCH_CONSENT_COOKIE_PARSE_ERROR(KETCH_CONSENT_MANAGER_PLUGIN),err);return undefined;}if(!consentCookieData){return undefined;}// Convert the cookie data to consent data
|
|
1301
|
+
const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{const purposeCode=pEntry[0];const purposeValue=pEntry[1];consentPurposes[purposeCode]=(purposeValue===null||purposeValue===void 0?void 0:purposeValue.status)==='granted';});return consentPurposes;};/**
|
|
1229
1302
|
* Gets the consent data in the format expected by the application state
|
|
1230
1303
|
* @param ketchConsentData Consent data derived from the consent cookie
|
|
1231
1304
|
* @returns Consent data
|
|
@@ -1233,36 +1306,36 @@ const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{cons
|
|
|
1233
1306
|
|
|
1234
1307
|
const pluginName$3='KetchConsentManager';const KetchConsentManager=()=>({name:pluginName$3,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$3];},consentManager:{init(state,logger){// getKetchUserConsentedPurposes returns current ketch opted-in purposes
|
|
1235
1308
|
// This will be helpful for debugging
|
|
1236
|
-
globalThis.getKetchUserConsentedPurposes=()=>state.consents.data.value.allowedConsentIds
|
|
1309
|
+
globalThis.getKetchUserConsentedPurposes=()=>{var _state$consents$data$;return (_state$consents$data$=state.consents.data.value.allowedConsentIds)===null||_state$consents$data$===void 0?void 0:_state$consents$data$.slice();};// getKetchUserDeniedPurposes returns current ketch opted-out purposes
|
|
1237
1310
|
// This will be helpful for debugging
|
|
1238
|
-
globalThis.getKetchUserDeniedPurposes=()=>state.consents.data.value.deniedConsentIds
|
|
1311
|
+
globalThis.getKetchUserDeniedPurposes=()=>{var _state$consents$data$2;return (_state$consents$data$2=state.consents.data.value.deniedConsentIds)===null||_state$consents$data$2===void 0?void 0:_state$consents$data$2.slice();};// updateKetchConsent callback function to update current consent purpose state
|
|
1239
1312
|
// this will be called from ketch rudderstack plugin
|
|
1240
1313
|
globalThis.updateKetchConsent=ketchConsentData=>{updateConsentStateFromData(state,ketchConsentData);};},updateConsentsInfo(state,storeManager,logger){// retrieve consent data and update the state
|
|
1241
1314
|
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,consentManagement}=destConfig;const matchPredicate=consent=>allowedConsentIds.includes(consent);// Generic consent management
|
|
1242
|
-
if(consentManagement){
|
|
1243
|
-
const cmpConsents=consentManagement.find(c=>c.provider===state.consents.provider.value)
|
|
1315
|
+
if(consentManagement){var _consentManagement$fi;// Get the corresponding consents for the destination
|
|
1316
|
+
const cmpConsents=(_consentManagement$fi=consentManagement.find(c=>c.provider===state.consents.provider.value))===null||_consentManagement$fi===void 0?void 0:_consentManagement$fi.consents;// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1244
1317
|
if(!cmpConsents){return true;}const configuredConsents=cmpConsents.map(c=>c.consent.trim()).filter(n=>n);// match the configured consents with user provided consents as per
|
|
1245
1318
|
// the configured resolution strategy
|
|
1246
1319
|
switch(state.consents.resolutionStrategy.value){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}// Legacy cookie consent management
|
|
1247
1320
|
// TODO: To be removed once the source config API is updated to support generic consent management
|
|
1248
1321
|
}else if(ketchConsentPurposes){const configuredConsents=ketchConsentPurposes.map(p=>p.purpose.trim()).filter(n=>n);// Check if any of the destination's mapped ketch purposes are consented by the user in the browser.
|
|
1249
1322
|
return configuredConsents.some(matchPredicate)||configuredConsents.length===0;}// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1250
|
-
return true;}catch(err){errorHandler
|
|
1323
|
+
return true;}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:KETCH_CONSENT_MANAGER_PLUGIN,customMessage:DESTINATION_CONSENT_STATUS_ERROR$1});return true;}}}});
|
|
1251
1324
|
|
|
1252
1325
|
const ONETRUST_ACCESS_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to access OneTrust SDK resources. Please ensure that the OneTrust SDK is loaded successfully before RudderStack SDK.`;const DESTINATION_CONSENT_STATUS_ERROR=`Failed to determine the consent status for the destination. Please check the destination configuration and try again.`;
|
|
1253
1326
|
|
|
1254
1327
|
const ONETRUST_CONSENT_MANAGER_PLUGIN='OneTrustConsentManagerPlugin';
|
|
1255
1328
|
|
|
1256
1329
|
const pluginName$2='OneTrustConsentManager';const OneTrustConsentManager=()=>({name:pluginName$2,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$2];},consentManager:{init(state,logger){// Nothing to initialize
|
|
1257
|
-
},updateConsentsInfo(state,storeManager,logger){if(!globalThis.OneTrust||!globalThis.OnetrustActiveGroups){logger
|
|
1330
|
+
},updateConsentsInfo(state,storeManager,logger){if(!globalThis.OneTrust||!globalThis.OnetrustActiveGroups){logger===null||logger===void 0||logger.error(ONETRUST_ACCESS_ERROR(ONETRUST_CONSENT_MANAGER_PLUGIN));state.consents.initialized.value=false;return;}// Get the groups (cookie categorization), user has created in OneTrust account.
|
|
1258
1331
|
const oneTrustAllGroupsInfo=globalThis.OneTrust.GetDomainData().Groups;// OneTrustConsentManager SDK populates a data layer object OnetrustActiveGroups with
|
|
1259
1332
|
// the cookie categories Ids that the user has consented to.
|
|
1260
1333
|
// Eg: ',C0001,C0003,'
|
|
1261
1334
|
// We split it and save it as an array.
|
|
1262
1335
|
const allowedConsentIds=globalThis.OnetrustActiveGroups.split(',').filter(n=>n);const deniedConsentIds=[];oneTrustAllGroupsInfo.forEach(({CustomGroupId})=>{if(!allowedConsentIds.includes(CustomGroupId)){deniedConsentIds.push(CustomGroupId);}});state.consents.initialized.value=true;state.consents.data.value={allowedConsentIds,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
|
|
1263
1336
|
const{oneTrustCookieCategories,consentManagement}=destConfig;const matchPredicate=consent=>allowedConsentIds.includes(consent);// Generic consent management
|
|
1264
|
-
if(consentManagement){
|
|
1265
|
-
const cmpConsents=consentManagement.find(c=>c.provider===state.consents.provider.value)
|
|
1337
|
+
if(consentManagement){var _consentManagement$fi;// Get the corresponding consents for the destination
|
|
1338
|
+
const cmpConsents=(_consentManagement$fi=consentManagement.find(c=>c.provider===state.consents.provider.value))===null||_consentManagement$fi===void 0?void 0:_consentManagement$fi.consents;// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1266
1339
|
if(!cmpConsents){return true;}const configuredConsents=cmpConsents.map(c=>c.consent.trim()).filter(n=>n);// match the configured consents with user provided consents as per
|
|
1267
1340
|
// the configured resolution strategy
|
|
1268
1341
|
switch(state.consents.resolutionStrategy.value){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}// Legacy cookie consent management
|
|
@@ -1272,16 +1345,17 @@ switch(state.consents.resolutionStrategy.value){case 'or':return configuredConse
|
|
|
1272
1345
|
// ["Performance Cookies", "Functional Cookies"]
|
|
1273
1346
|
const configuredConsents=oneTrustCookieCategories.map(c=>c.oneTrustCookieCategory.trim()).filter(n=>n);// Check if all the destination's mapped cookie categories are consented by the user in the browser.
|
|
1274
1347
|
return configuredConsents.every(matchPredicate);}// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1275
|
-
return true;}catch(err){errorHandler
|
|
1348
|
+
return true;}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:ONETRUST_CONSENT_MANAGER_PLUGIN,customMessage:DESTINATION_CONSENT_STATUS_ERROR});return true;}}}});
|
|
1276
1349
|
|
|
1277
1350
|
const pluginName$1='StorageEncryption';const StorageEncryption=()=>({name:pluginName$1,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$1];},storage:{encrypt(value){return encryptBrowser(value);},decrypt(value){return decryptBrowser(value);}}});
|
|
1278
1351
|
|
|
1279
|
-
const DEFAULT_RETRY_QUEUE_OPTIONS={maxRetryDelay:
|
|
1352
|
+
const DEFAULT_RETRY_QUEUE_OPTIONS={maxRetryDelay:540000,minRetryDelay:1000,backoffFactor:2,backoffJitter:0.2,maxAttempts:30,// ~3h of retries at these delays
|
|
1353
|
+
maxItems:100};const REQUEST_TIMEOUT_MS=30*1000;// 30 seconds
|
|
1280
1354
|
const DATA_PLANE_API_VERSION='v1';const QUEUE_NAME='rudder';const XHR_QUEUE_PLUGIN='XhrQueuePlugin';
|
|
1281
1355
|
|
|
1282
1356
|
const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,originalErrorMsg)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s). Cause: ${originalErrorMsg}.`;
|
|
1283
1357
|
|
|
1284
|
-
const getBatchDeliveryPayload=(events,currentTime,logger)=>{const batchPayload={batch:events,sentAt:currentTime};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 logMessageOnFailure=(details,isRetryable,qItemProcessInfo,logger)=>{if(!logger){return;}let logMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,details
|
|
1358
|
+
const getBatchDeliveryPayload=(events,currentTime,logger)=>{const batchPayload={batch:events,sentAt:currentTime};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 logMessageOnFailure=(details,isRetryable,qItemProcessInfo,logger)=>{var _details$error$messag,_details$error;if(!logger){return;}let logMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,(_details$error$messag=details===null||details===void 0||(_details$error=details.error)===null||_details$error===void 0?void 0:_details$error.message)!==null&&_details$error$messag!==void 0?_details$error$messag:'Unknown');const dropMsg=`The event(s) will be dropped.`;if(isRetryable){if(qItemProcessInfo.willBeRetried){logMsg=`${logMsg} The event(s) will be retried.`;if(qItemProcessInfo.retryAttemptNumber>0){logMsg=`${logMsg} Retry attempt ${qItemProcessInfo.retryAttemptNumber} of ${qItemProcessInfo.maxRetryAttempts}.`;}// Use warning for retryable failures that will be retried
|
|
1285
1359
|
logger.warn(logMsg);}else {logger.error(`${logMsg} Retries exhausted (${qItemProcessInfo.maxRetryAttempts}). ${dropMsg}`);}}else {// Use error for non-retryable failures
|
|
1286
1360
|
logger.error(`${logMsg} ${dropMsg}`);}};const getRequestInfo=(itemData,state,qItemProcessInfo,logger)=>{let data;let headers;let url;const currentTime=getCurrentTimeFormatted();if(Array.isArray(itemData)){const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event,currentTime));data=getBatchDeliveryPayload(finalEvents,currentTime,logger);headers=itemData[0]?clone(itemData[0].headers):{};url=getBatchDeliveryUrl(state.lifecycle.activeDataplaneUrl.value);}else {const{url:eventUrl,event,headers:eventHeaders}=itemData;const finalEvent=getFinalEventForDeliveryMutator(event,currentTime);data=getDeliveryPayload(finalEvent,logger);headers=clone(eventHeaders);url=eventUrl;}// Add current timestamp as sentAt header
|
|
1287
1361
|
// The same value is added in the event payload as well
|
|
@@ -1303,11 +1377,11 @@ const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initial
|
|
|
1303
1377
|
* @param logger Logger instance
|
|
1304
1378
|
* @returns RetryQueue instance
|
|
1305
1379
|
*/init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;httpClient.setAuthHeader(writeKey);const finalQOpts=getNormalizedQueueOptions(state.loadOptions.value.queueOptions);const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
|
1306
|
-
`${QUEUE_NAME}_${writeKey}`,finalQOpts,(itemData,done,qItemProcessInfo)=>{const{data,url,headers}=getRequestInfo(itemData,state,qItemProcessInfo,logger);httpClient.getAsyncData({url,options:{method:'POST',headers,data:data,sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS,callback:(result,details)=>{
|
|
1307
|
-
if(isUndefined(details
|
|
1308
|
-
done(null);return;}const isRetryable=isErrRetryable(details
|
|
1309
|
-
done(null);}}});},storeManager,getStorageTypeForEventsPersistence(logger),logger,itemData=>{const currentTime=getCurrentTimeFormatted();const events=itemData.map(queueItemData=>queueItemData.event);// type casting to string as we know that the event has already been validated prior to enqueue
|
|
1310
|
-
return getBatchDeliveryPayload(events,currentTime,logger)
|
|
1380
|
+
`${QUEUE_NAME}_${writeKey}`,finalQOpts,(itemData,done,qItemProcessInfo)=>{const{data,url,headers}=getRequestInfo(itemData,state,qItemProcessInfo,logger);httpClient.getAsyncData({url,options:{method:'POST',headers,data:data,sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS,callback:(result,details)=>{var _details$xhr$status,_details$xhr;// If there is no error, we can consider the item as delivered
|
|
1381
|
+
if(isUndefined(details===null||details===void 0?void 0:details.error)){// null means item will not be processed further and will be removed from the queue (even from the storage)
|
|
1382
|
+
done(null);return;}const isRetryable=isErrRetryable((_details$xhr$status=details===null||details===void 0||(_details$xhr=details.xhr)===null||_details$xhr===void 0?void 0:_details$xhr.status)!==null&&_details$xhr$status!==void 0?_details$xhr$status:0);logMessageOnFailure(details,isRetryable,qItemProcessInfo,logger);if(isRetryable){var _details$xhr2;let retryReason=DEFAULT_RETRY_REASON;if(details!==null&&details!==void 0&&details.timedOut){retryReason=RETRY_REASON_CLIENT_TIMEOUT;}else if(isDefined(details===null||details===void 0||(_details$xhr2=details.xhr)===null||_details$xhr2===void 0?void 0:_details$xhr2.status)){retryReason=`server-${details.xhr.status}`;}done(details,{retryReason});}else {// null means item will not be processed further and will be removed from the queue (even from the storage)
|
|
1383
|
+
done(null);}}});},storeManager,getStorageTypeForEventsPersistence(logger),logger,itemData=>{var _getBatchDeliveryPayl;const currentTime=getCurrentTimeFormatted();const events=itemData.map(queueItemData=>queueItemData.event);// type casting to string as we know that the event has already been validated prior to enqueue
|
|
1384
|
+
return (_getBatchDeliveryPayl=getBatchDeliveryPayload(events,currentTime,logger))===null||_getBatchDeliveryPayl===void 0?void 0:_getBatchDeliveryPayl.length;});return eventsQueue;},/**
|
|
1311
1385
|
* Add event to the queue for delivery
|
|
1312
1386
|
* @param state Application state
|
|
1313
1387
|
* @param eventsQueue RetryQueue instance
|
|
@@ -1333,7 +1407,7 @@ AnonymousId:toBase64(event.anonymousId)};eventsQueue.addItem({url,headers,event}
|
|
|
1333
1407
|
* Map of optional plugin names and direct imports for legacy builds
|
|
1334
1408
|
*/const getOptionalPluginsMap=()=>{return getBundledBuildPluginImports();};/**
|
|
1335
1409
|
* Map of optional plugin names and dynamic imports for modern builds
|
|
1336
|
-
*/const getRemotePluginsMap=activePluginNames=>{{return {};}};const pluginsInventory={
|
|
1410
|
+
*/const getRemotePluginsMap=activePluginNames=>{{return {};}};const pluginsInventory=_objectSpread2(_objectSpread2({},getMandatoryPluginsMap()),getOptionalPluginsMap());const remotePluginsInventory=activePluginNames=>_objectSpread2({},getRemotePluginsMap());
|
|
1337
1411
|
|
|
1338
1412
|
// TODO: add retry mechanism for getting remote plugins
|
|
1339
1413
|
// TODO: add timeout error mechanism for marking remote plugins that failed to load as failed in state
|
|
@@ -1358,15 +1432,16 @@ const availablePlugins=[...Object.keys(pluginsInventory),...pluginNamesList];con
|
|
|
1358
1432
|
* Register plugins that are direct imports to PluginEngine
|
|
1359
1433
|
*/registerLocalPlugins(){const unavailablePlugins=[];Object.entries(pluginsInventory).forEach(([pluginName,localPlugin])=>{if(state.plugins.activePlugins.value.includes(pluginName)){if(isFunction(localPlugin)){this.register([localPlugin()]);}else {unavailablePlugins.push(pluginName);}}});if(unavailablePlugins.length>0){state.plugins.failedPlugins.value=[...state.plugins.failedPlugins.value,...unavailablePlugins];this.logger.error(UNAVAILABLE_PLUGINS_ERROR(PLUGINS_MANAGER,unavailablePlugins));}}/**
|
|
1360
1434
|
* Register plugins that are dynamic imports to PluginEngine
|
|
1361
|
-
*/registerRemotePlugins(){const remotePluginsList=remotePluginsInventory(state.plugins.activePlugins.value);const loadFailures=[];// Kept separate from state.plugins.failedPlugins, which also collects
|
|
1435
|
+
*/registerRemotePlugins(){const remotePluginsList=remotePluginsInventory(state.plugins.activePlugins.value);const pluginsCDNPath=state.lifecycle.pluginsCDNPath.value;const remoteEntryUrl=`${pluginsCDNPath}/${REMOTE_PLUGINS_ENTRY_FILE}`;const loadFailures=[];// Kept separate from state.plugins.failedPlugins, which also collects
|
|
1362
1436
|
// unknown plugins from setActivePlugins, unavailable local plugins from
|
|
1363
1437
|
// registerLocalPlugins and registration failures from register(). Reporting
|
|
1364
1438
|
// the global list would attribute those to this remote load incident.
|
|
1365
|
-
const failedRemotePlugins=[];return Promise.all(Object.keys(remotePluginsList).map(async remotePluginKey=>{await remotePluginsList[remotePluginKey]().then(remotePluginModule=>
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1439
|
+
const failedRemotePlugins=[];return Promise.all(Object.keys(remotePluginsList).map(async remotePluginKey=>{await remotePluginsList[remotePluginKey]().then(remotePluginModule=>{// An intercepted chunk can parse yet export nothing; calling the
|
|
1440
|
+
// undefined factory blind reports a per-build minified name.
|
|
1441
|
+
const pluginFactory=remotePluginModule===null||remotePluginModule===void 0?void 0:remotePluginModule.default;if(!isFunction(pluginFactory)){throw new Error(NO_PLUGIN_FACTORY_EXPORTED_REASON);}this.register([pluginFactory()]);}).catch(err=>{var _message;// TODO: add retry here if dynamic import fails
|
|
1442
|
+
failedRemotePlugins.push(remotePluginKey);state.plugins.failedPlugins.value=[...state.plugins.failedPlugins.value,remotePluginKey];// A rejection is not guaranteed to be an Error, so without the
|
|
1443
|
+
// fallback the log reads "- undefined".
|
|
1444
|
+
const reason=(_message=err===null||err===void 0?void 0:err.message)!==null&&_message!==void 0?_message:String(err);this.logger.error(REMOTE_PLUGIN_LOAD_ERROR(PLUGINS_MANAGER,remotePluginKey,reason));loadFailures.push(err);});})).then(()=>{// A failed remote entry rejects every plugin import at once, so the
|
|
1370
1445
|
// fan-out is one incident and gets one report, raised only after every
|
|
1371
1446
|
// import has settled so it names all of them.
|
|
1372
1447
|
//
|
|
@@ -1374,7 +1449,9 @@ err?.message??String(err)));loadFailures.push(err);});})).then(()=>{// A failed
|
|
|
1374
1449
|
// deliberate: a dynamic import has no timeout of its own, and holding a
|
|
1375
1450
|
// timer open to salvage a partial report would spend page resources on
|
|
1376
1451
|
// error reporting, which is the lowest priority thing the SDK does.
|
|
1377
|
-
if(failedRemotePlugins.length===0){return;}
|
|
1452
|
+
if(failedRemotePlugins.length===0){return;}this.onError(loadFailures[0],`Failed to load plugins: ${failedRemotePlugins.join(', ')}`,// Grouping on the message split one bug across two dozen groups: the
|
|
1453
|
+
// federation runtime names its own local, renamed by the host bundler per build.
|
|
1454
|
+
remoteEntryUrl);}).catch(err=>{this.onError(err);});}/**
|
|
1378
1455
|
* Extension point invoke that allows multiple plugins to be registered to it with error handling
|
|
1379
1456
|
*/invokeMultiple(extPoint,...args){try{return this.engine.invokeMultiple(extPoint,...args);}catch(e){this.onError(e,extPoint);return [];}}/**
|
|
1380
1457
|
* Extension point invoke that allows a single plugin to be registered to it with error handling
|
|
@@ -1393,8 +1470,8 @@ const legacyGetHostname=href=>{const l=document.createElement('a');l.href=href;r
|
|
|
1393
1470
|
* Levels returns all levels of the given url
|
|
1394
1471
|
*
|
|
1395
1472
|
* The method returns an empty array when the hostname is an ip.
|
|
1396
|
-
*/const levelsFunc=url=>{
|
|
1397
|
-
const host=typeof globalThis.URL!=='function'?legacyGetHostname(url):new URL(url).hostname;const parts=host
|
|
1473
|
+
*/const levelsFunc=url=>{var _host$split;// This is called before the polyfills load thus new URL cannot be used
|
|
1474
|
+
const host=typeof globalThis.URL!=='function'?legacyGetHostname(url):new URL(url).hostname;const parts=(_host$split=host===null||host===void 0?void 0:host.split('.'))!==null&&_host$split!==void 0?_host$split:[];const last=parts[parts.length-1];const levels=[];// Ip address.
|
|
1398
1475
|
if(parts.length===4&&last&&last===parseInt(last,10).toString()){return levels;}// Localhost.
|
|
1399
1476
|
if(parts.length<=1){// Fix to support localhost
|
|
1400
1477
|
if(parts[0]&&parts[0].indexOf('localhost')!==-1){return ['localhost'];}return levels;}// Create levels.
|
|
@@ -1410,16 +1487,16 @@ for(let i=parts.length-2;i>=0;i-=1){levels.push(parts.slice(i).join('.'));}retur
|
|
|
1410
1487
|
for(let i=0;i<levels.length;i+=1){const domain=levels[i];const cname=STORAGE_TEST_TOP_LEVEL_DOMAIN;const opts={domain:`${domain.indexOf('localhost')!==-1?'':'.'}${domain}`};try{// Set cookie on domain
|
|
1411
1488
|
cookie(cname,1,opts);// If successful
|
|
1412
1489
|
if(cookie(cname)){// Remove cookie from domain
|
|
1413
|
-
cookie(cname,null,opts);return domain;}}catch{// Silently continue to next domain level if cookie access is restricted or setting fails
|
|
1490
|
+
cookie(cname,null,opts);return domain;}}catch(_unused){// Silently continue to next domain level if cookie access is restricted or setting fails
|
|
1414
1491
|
// Best-effort cleanup to avoid leaking the test cookie
|
|
1415
|
-
try{cookie(cname,null,opts);}catch{// Ignore if we are unable to delete the cookie
|
|
1492
|
+
try{cookie(cname,null,opts);}catch(_unused2){// Ignore if we are unable to delete the cookie
|
|
1416
1493
|
}}}return '';};
|
|
1417
1494
|
|
|
1418
1495
|
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});
|
|
1419
1496
|
|
|
1420
1497
|
/**
|
|
1421
1498
|
* A storage utility to retain values in memory via Storage interface
|
|
1422
|
-
*/class InMemoryStorage{isEnabled
|
|
1499
|
+
*/class InMemoryStorage{constructor(logger){_defineProperty(this,"isEnabled",true);_defineProperty(this,"length",0);_defineProperty(this,"data",{});this.options=getDefaultInMemoryStorageOptions();this.logger=logger;}configure(options){this.options=mergeDeepRight(this.options,options!==null&&options!==void 0?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){var _curKeys$index;const curKeys=this.keys();return (_curKeys$index=curKeys[index])!==null&&_curKeys$index!==void 0?_curKeys$index:null;}keys(){return Object.keys(this.data);}}const defaultInMemoryStorage=new InMemoryStorage(defaultLogger);
|
|
1423
1500
|
|
|
1424
1501
|
function getDefaultExportFromCjs (x) {
|
|
1425
1502
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -1442,24 +1519,24 @@ const store = /*@__PURE__*/getDefaultExportFromCjs(storeExports);
|
|
|
1442
1519
|
// https://www.npmjs.com/package/storejs
|
|
1443
1520
|
/**
|
|
1444
1521
|
* A storage utility to persist values in localstorage via Storage interface
|
|
1445
|
-
*/class LocalStorage{isSupportAvailable
|
|
1446
|
-
getItem(key){const value=store.get(key);return isUndefined(value)?null:value;}removeItem(key){store.remove(key);this.length=store.len();}clear(){store.clear();this.length=0;}key(index){const curKeys=this.keys();return curKeys[index]
|
|
1522
|
+
*/class LocalStorage{constructor(logger){_defineProperty(this,"isSupportAvailable",true);_defineProperty(this,"isEnabled",true);_defineProperty(this,"length",0);this.options=getDefaultLocalStorageOptions();this.logger=logger;}configure(options){this.options=mergeDeepRight(this.options,options!==null&&options!==void 0?options:{});this.isSupportAvailable=isStorageAvailable(LOCAL_STORAGE);this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){store.set(key,value);this.length=store.len();}// eslint-disable-next-line class-methods-use-this
|
|
1523
|
+
getItem(key){const value=store.get(key);return isUndefined(value)?null:value;}removeItem(key){store.remove(key);this.length=store.len();}clear(){store.clear();this.length=0;}key(index){var _curKeys$index;const curKeys=this.keys();return (_curKeys$index=curKeys[index])!==null&&_curKeys$index!==void 0?_curKeys$index:null;}// eslint-disable-next-line class-methods-use-this
|
|
1447
1524
|
keys(){return store.keys();}}const defaultLocalStorage=new LocalStorage(defaultLogger);
|
|
1448
1525
|
|
|
1449
1526
|
/**
|
|
1450
1527
|
* A storage utility to persist values in SessionStorage via Storage interface
|
|
1451
|
-
*/class SessionStorage{isSupportAvailable
|
|
1452
|
-
if(this.isSupportAvailable){this.store=globalThis.sessionStorage;}this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){if(!this.store){return;}this.store.setItem(key,value);this.length=this.store.length;}getItem(key){if(!this.store){return null;}const value=this.store.getItem(key);return isUndefined(value)?null:value;}removeItem(key){if(!this.store){return;}this.store.removeItem(key);this.length=this.store.length;}clear(){this.store
|
|
1528
|
+
*/class SessionStorage{constructor(logger){_defineProperty(this,"isSupportAvailable",true);_defineProperty(this,"isEnabled",true);_defineProperty(this,"length",0);this.options=getDefaultSessionStorageOptions();this.logger=logger;}configure(options){this.options=mergeDeepRight(this.options,options!==null&&options!==void 0?options:{});this.isSupportAvailable=isStorageAvailable(SESSION_STORAGE);// when storage is blocked by the user, even accessing the property throws an error
|
|
1529
|
+
if(this.isSupportAvailable){this.store=globalThis.sessionStorage;}this.isEnabled=Boolean(this.options.enabled&&this.isSupportAvailable);return this.options;}setItem(key,value){if(!this.store){return;}this.store.setItem(key,value);this.length=this.store.length;}getItem(key){if(!this.store){return null;}const value=this.store.getItem(key);return isUndefined(value)?null:value;}removeItem(key){if(!this.store){return;}this.store.removeItem(key);this.length=this.store.length;}clear(){var _this$store;(_this$store=this.store)===null||_this$store===void 0||_this$store.clear();this.length=0;}key(index){var _this$store$key,_this$store2;return (_this$store$key=(_this$store2=this.store)===null||_this$store2===void 0?void 0:_this$store2.key(index))!==null&&_this$store$key!==void 0?_this$store$key:null;}keys(){const keys=[];if(!this.store){return keys;}for(let i=0;i<this.store.length;i+=1){const key=this.store.key(i);if(key!==null){keys.push(key);}}return keys;}}const defaultSessionStorage=new SessionStorage(defaultLogger);
|
|
1453
1530
|
|
|
1454
1531
|
/**
|
|
1455
1532
|
* A storage utility to persist values in cookies via Storage interface
|
|
1456
|
-
*/class CookieStorage{isSupportAvailable
|
|
1533
|
+
*/class CookieStorage{constructor(logger){_defineProperty(this,"isSupportAvailable",true);_defineProperty(this,"isEnabled",true);_defineProperty(this,"length",0);this.logger=logger;}configure(options){if(!this.options){this.options=getDefaultCookieOptions();}this.options=mergeDeepRight(this.options,options!==null&&options!==void 0?options:{});if(this.options.sameDomainCookiesOnly){delete this.options.domain;}this.isSupportAvailable=isStorageAvailable(COOKIE_STORAGE,this);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
|
|
1457
1534
|
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
|
|
1458
1535
|
clear(){// Not implemented
|
|
1459
1536
|
// getting a list of all cookie storage keys and remove all values
|
|
1460
1537
|
// sounds risky to do as it will take on all top domain cookies
|
|
1461
1538
|
// better to explicitly clear specific ones if needed
|
|
1462
|
-
}key(index){const curKeys=this.keys();return curKeys[index]
|
|
1539
|
+
}key(index){var _curKeys$index;const curKeys=this.keys();return (_curKeys$index=curKeys[index])!==null&&_curKeys$index!==void 0?_curKeys$index:null;}// eslint-disable-next-line class-methods-use-this
|
|
1463
1540
|
keys(){return Object.keys(cookie());}}const defaultCookieStorage=new CookieStorage(defaultLogger);
|
|
1464
1541
|
|
|
1465
1542
|
/**
|
|
@@ -1479,12 +1556,12 @@ state.storage.cookie.value={maxage:cookieStorageOptions.maxage,path:cookieStorag
|
|
|
1479
1556
|
|
|
1480
1557
|
/**
|
|
1481
1558
|
* Store Implementation with dedicated storage
|
|
1482
|
-
*/class Store{constructor(config,engine,pluginsManager){this.id=config.id;this.name=config.name;this.isEncrypted=config.isEncrypted
|
|
1559
|
+
*/class Store{constructor(config,engine,pluginsManager){var _config$isEncrypted,_config$validKeys;this.id=config.id;this.name=config.name;this.isEncrypted=(_config$isEncrypted=config.isEncrypted)!==null&&_config$isEncrypted!==void 0?_config$isEncrypted:false;this.validKeys=(_config$validKeys=config.validKeys)!==null&&_config$validKeys!==void 0?_config$validKeys:{};this.engine=engine;this.noKeyValidation=Object.keys(this.validKeys).length===0;this.noCompoundKey=config.noCompoundKey;this.noSwapOnQuota=config.noSwapOnQuota;this.originalEngine=this.engine;this.errorHandler=config.errorHandler;this.logger=config.logger;this.pluginsManager=pluginsManager;}/**
|
|
1483
1560
|
* Ensure the key is valid and with correct format
|
|
1484
1561
|
*/createValidKey(key){const{name,id,validKeys,noKeyValidation,noCompoundKey}=this;if(noKeyValidation){return noCompoundKey?key:[name,id,key].join('.');}// validate and return undefined if invalid key
|
|
1485
1562
|
let compoundKey;Object.values(validKeys).forEach(validKeyName=>{if(validKeyName===key){compoundKey=noCompoundKey?key:[name,id,key].join('.');}});return compoundKey;}/**
|
|
1486
1563
|
* Switch to inMemoryEngine, bringing any existing data with.
|
|
1487
|
-
*/swapQueueStoreToInMemoryEngine(){const{validKeys,noCompoundKey}=this;const inMemoryStorage=getStorageEngine(MEMORY_STORAGE)
|
|
1564
|
+
*/swapQueueStoreToInMemoryEngine(){const{validKeys,noCompoundKey,engine:durableEngine}=this;const inMemoryStorage=getStorageEngine(MEMORY_STORAGE);// grab existing data, but only for this page's queue instance, not all
|
|
1488
1565
|
// better to keep other queues in localstorage to be flushed later
|
|
1489
1566
|
// than to pull them into memory and remove them from durable storage
|
|
1490
1567
|
const existingEntries=Object.values(validKeys).map(storeKey=>[storeKey,this.get(storeKey)]);// Client data stores keep their durable copy. Dropping rl_user_id and the
|
|
@@ -1494,7 +1571,7 @@ const canDropDurableCopy=!noCompoundKey&&durableEngine!==inMemoryStorage;this.en
|
|
|
1494
1571
|
this.set(storeKey,value);// Only give up the durable copy once the value is readable from memory:
|
|
1495
1572
|
// set() swallows serialisation and storage failures, and get() returns
|
|
1496
1573
|
// null on a parse or decryption failure.
|
|
1497
|
-
const validKey=this.createValidKey(storeKey);if(canDropDurableCopy&&validKey&&!isNullOrUndefined(this.get(storeKey))){try{durableEngine.removeItem(validKey);}catch{// The durable engine can refuse a removal (NS_ERROR_STORAGE_BUSY). The
|
|
1574
|
+
const validKey=this.createValidKey(storeKey);if(canDropDurableCopy&&validKey&&!isNullOrUndefined(this.get(storeKey))){try{durableEngine.removeItem(validKey);}catch(_unused){// The durable engine can refuse a removal (NS_ERROR_STORAGE_BUSY). The
|
|
1498
1575
|
// value is already safe in memory, so leave the stale copy for a later
|
|
1499
1576
|
// cleanup rather than aborting the migration - this runs inside set()'s
|
|
1500
1577
|
// catch, and throwing here would lose the value that triggered it.
|
|
@@ -1505,8 +1582,18 @@ this.engine.setItem(validKey,this.encrypt(stringifyWithoutCircular(value,false,[
|
|
|
1505
1582
|
this.swapQueueStoreToInMemoryEngine();// and save it there
|
|
1506
1583
|
this.set(key,value);}else {const customMessage=STORE_DATA_SAVE_ERROR(key);this.onError(err,customMessage,customMessage);}}}/**
|
|
1507
1584
|
* Get by Key.
|
|
1508
|
-
*/get(key){const validKey=this.createValidKey(key);let decryptedValue;try{if(!validKey){return null;}
|
|
1509
|
-
return JSON.parse(decryptedValue);}catch(err){
|
|
1585
|
+
*/get(key){const validKey=this.createValidKey(key);let storedValue;let decryptedValue;let isRetrieved=false;try{if(!validKey){return null;}storedValue=this.engine.getItem(validKey);decryptedValue=this.decrypt(storedValue);if(isNullOrUndefined(decryptedValue)||decryptedValue===''){return null;}isRetrieved=true;// storejs that is used in localstorage engine already deserializes json strings but swallows errors
|
|
1586
|
+
return JSON.parse(decryptedValue);}catch(err){// Both encryption plugins, and `crypto` with no decrypt extension point registered, return
|
|
1587
|
+
// an unrecognised format untouched, so an unchanged value may still be readable; keep it.
|
|
1588
|
+
const isDecrypted=!this.isEncrypted||decryptedValue!==storedValue;// Drop a parse failure so a later read is a clean miss instead of the same error on every
|
|
1589
|
+
// poll, and only while the entry still holds what was read. Web Storage has no conditional
|
|
1590
|
+
// delete, so that narrows rather than closes the window in which another tab's write is
|
|
1591
|
+
// dropped; the cost there is a restarted reclaim handshake, since queued events are written
|
|
1592
|
+
// only by the context that owns the store. The compare is serialized because storejs
|
|
1593
|
+
// deserializes on every read, and uses `JSON.stringify` because `stringifyWithoutCircular`
|
|
1594
|
+
// returns null on failure, which would make two unserializable values compare equal.
|
|
1595
|
+
try{if(isRetrieved&&isDecrypted&&JSON.stringify(this.engine.getItem(validKey))===JSON.stringify(storedValue)){this.remove(key);}}catch(_unused2){// The engine can refuse the re-read or the removal; a later read retries.
|
|
1596
|
+
}const encryptionPluginName=state.storage.encryptionPluginName.value;// Skip error reporting only when the encryption plugin is configured but failed to load
|
|
1510
1597
|
const shouldReportError=!encryptionPluginName||!state.plugins.failedPlugins.value.includes(encryptionPluginName);if(shouldReportError){const customMessage=STORE_DATA_FETCH_ERROR(key);this.onError(err,customMessage,customMessage);}return null;}}/**
|
|
1511
1598
|
* Remove by Key.
|
|
1512
1599
|
*/remove(key){const validKey=this.createValidKey(key);if(validKey){this.engine.removeItem(validKey);}}/**
|
|
@@ -1517,31 +1604,31 @@ const shouldReportError=!encryptionPluginName||!state.plugins.failedPlugins.valu
|
|
|
1517
1604
|
* Encrypt value
|
|
1518
1605
|
*/encrypt(value){return this.crypto(value,'encrypt');}/**
|
|
1519
1606
|
* Extension point to use with encryption plugins
|
|
1520
|
-
*/crypto(value,mode){const noEncryption=!this.isEncrypted||!value||typeof value!=='string'||trim(value)==='';if(noEncryption){return value;}const extensionPointName=`storage.${mode}`;const formattedValue=this.pluginsManager?this.pluginsManager.invokeSingle(extensionPointName,value):value;return
|
|
1607
|
+
*/crypto(value,mode){const noEncryption=!this.isEncrypted||!value||typeof value!=='string'||trim(value)==='';if(noEncryption){return value;}const extensionPointName=`storage.${mode}`;const formattedValue=this.pluginsManager?this.pluginsManager.invokeSingle(extensionPointName,value):value;return formattedValue===undefined?value:formattedValue!==null&&formattedValue!==void 0?formattedValue:'';}/**
|
|
1521
1608
|
* Handle errors
|
|
1522
1609
|
*/onError(error,customMessage,groupingHash){this.errorHandler.onError({error,context:`Store ${this.id}`,customMessage,groupingHash});}}
|
|
1523
1610
|
|
|
1524
|
-
const getStorageTypeFromPreConsentIfApplicable=(state,sessionKey)=>{let overriddenStorageType;if(state.consents.preConsent.value.enabled){switch(state.consents.preConsent.value.storage
|
|
1611
|
+
const getStorageTypeFromPreConsentIfApplicable=(state,sessionKey)=>{let overriddenStorageType;if(state.consents.preConsent.value.enabled){var _state$consents$preCo;switch((_state$consents$preCo=state.consents.preConsent.value.storage)===null||_state$consents$preCo===void 0?void 0:_state$consents$preCo.strategy){case 'none':overriddenStorageType=NO_STORAGE;break;case 'session':if(sessionKey!=='sessionInfo'){overriddenStorageType=NO_STORAGE;}break;case 'anonymousId':if(sessionKey!=='anonymousId'){overriddenStorageType=NO_STORAGE;}break;}}return overriddenStorageType;};
|
|
1525
1612
|
|
|
1526
1613
|
/**
|
|
1527
1614
|
* A service to manage stores & available storage client configurations
|
|
1528
|
-
*/class StoreManager{
|
|
1615
|
+
*/class StoreManager{constructor(pluginsManager,errorHandler,logger){_defineProperty(this,"stores",{});_defineProperty(this,"isInitialized",false);this.errorHandler=errorHandler;this.logger=logger;this.pluginsManager=pluginsManager;}/**
|
|
1529
1616
|
* Configure available storage client instances
|
|
1530
|
-
*/init(){if(this.isInitialized){return;}const loadOptions=state.loadOptions.value;const config={cookieStorageOptions:{samesite:loadOptions.sameSiteCookie,secure:loadOptions.secureCookie,domain:loadOptions.setCookieDomain,sameDomainCookiesOnly:loadOptions.sameDomainCookiesOnly},localStorageOptions:{},inMemoryStorageOptions:{},sessionStorageOptions:{}};configureStorageEngines(removeUndefinedValues(mergeDeepRight(config.cookieStorageOptions
|
|
1617
|
+
*/init(){var _config$cookieStorage,_state$storage$cookie,_state$storage$cookie2;if(this.isInitialized){return;}const loadOptions=state.loadOptions.value;const config={cookieStorageOptions:{samesite:loadOptions.sameSiteCookie,secure:loadOptions.secureCookie,domain:loadOptions.setCookieDomain,sameDomainCookiesOnly:loadOptions.sameDomainCookiesOnly},localStorageOptions:{},inMemoryStorageOptions:{},sessionStorageOptions:{}};configureStorageEngines(removeUndefinedValues(mergeDeepRight((_config$cookieStorage=config.cookieStorageOptions)!==null&&_config$cookieStorage!==void 0?_config$cookieStorage:{},(_state$storage$cookie=(_state$storage$cookie2=state.storage.cookie)===null||_state$storage$cookie2===void 0?void 0:_state$storage$cookie2.value)!==null&&_state$storage$cookie!==void 0?_state$storage$cookie:{})),removeUndefinedValues(config.localStorageOptions),removeUndefinedValues(config.inMemoryStorageOptions),removeUndefinedValues(config.sessionStorageOptions));this.initClientDataStores();this.isInitialized=true;}/**
|
|
1531
1618
|
* Create store to persist data used by the SDK like session, used details etc
|
|
1532
1619
|
*/initClientDataStores(){this.initializeStorageState();// TODO: fill in extra config values and bring them in from StoreManagerOptions if needed
|
|
1533
1620
|
// TODO: should we pass the keys for all in order to validate or leave free as v1.1?
|
|
1534
1621
|
// Initializing all the enabled store because previous user data might be in different storage
|
|
1535
1622
|
// that needs auto migration
|
|
1536
|
-
const storageTypes=[MEMORY_STORAGE,LOCAL_STORAGE,COOKIE_STORAGE,SESSION_STORAGE];storageTypes.forEach(storageType=>{if(getStorageEngine(storageType)
|
|
1537
|
-
const postConsentStorageOpts=state.consents.postConsent.value.storage;if(isDefined(postConsentStorageOpts
|
|
1623
|
+
const storageTypes=[MEMORY_STORAGE,LOCAL_STORAGE,COOKIE_STORAGE,SESSION_STORAGE];storageTypes.forEach(storageType=>{var _getStorageEngine;if((_getStorageEngine=getStorageEngine(storageType))!==null&&_getStorageEngine!==void 0&&_getStorageEngine.isEnabled){this.setStore({id:storageClientDataStoreNameMap[storageType],name:storageClientDataStoreNameMap[storageType],isEncrypted:true,noCompoundKey:true,type:storageType,errorHandler:this.errorHandler,logger:this.logger});}});}initializeStorageState(){var _state$loadOptions$va,_state$loadOptions$va2,_preConsentOpts$stora;let globalStorageType=(_state$loadOptions$va=state.loadOptions.value.storage)===null||_state$loadOptions$va===void 0?void 0:_state$loadOptions$va.type;let entriesOptions=(_state$loadOptions$va2=state.loadOptions.value.storage)===null||_state$loadOptions$va2===void 0?void 0:_state$loadOptions$va2.entries;// Use the storage options from post consent if anything is defined
|
|
1624
|
+
const postConsentStorageOpts=state.consents.postConsent.value.storage;if(isDefined(postConsentStorageOpts===null||postConsentStorageOpts===void 0?void 0:postConsentStorageOpts.type)||isDefined(postConsentStorageOpts===null||postConsentStorageOpts===void 0?void 0:postConsentStorageOpts.entries)){globalStorageType=postConsentStorageOpts===null||postConsentStorageOpts===void 0?void 0:postConsentStorageOpts.type;entriesOptions=postConsentStorageOpts===null||postConsentStorageOpts===void 0?void 0:postConsentStorageOpts.entries;}// Without the deprecated pre-consent storage strategy, the storage options decide what is
|
|
1538
1625
|
// persisted before consent is given. Only the fallback changes: nothing is persisted unless
|
|
1539
1626
|
// a storage type has been explicitly configured.
|
|
1540
|
-
const preConsentOpts=state.consents.preConsent.value;const isStorageFromLoadOptionsBeforeConsent=preConsentOpts.enabled===true&&!preConsentOpts.storage
|
|
1627
|
+
const preConsentOpts=state.consents.preConsent.value;const isStorageFromLoadOptionsBeforeConsent=preConsentOpts.enabled===true&&!((_preConsentOpts$stora=preConsentOpts.storage)!==null&&_preConsentOpts$stora!==void 0&&_preConsentOpts$stora.strategy);const defaultStorageType=isStorageFromLoadOptionsBeforeConsent?NO_STORAGE:DEFAULT_STORAGE_TYPE;// The unsupported values are reported where the options enter the SDK, so they are only
|
|
1541
1628
|
// resolved here, against the default that applies to the current consent phase
|
|
1542
|
-
if(globalStorageType!==undefined&&!SUPPORTED_STORAGE_TYPES.includes(globalStorageType)){globalStorageType=undefined;}let trulyAnonymousTracking=true;let storageEntries={};USER_SESSION_KEYS.forEach(sessionKey=>{const key=sessionKey;const storageKey=sessionKey;const configuredStorageType=entriesOptions
|
|
1543
|
-
let storageType=preConsentStorageType
|
|
1544
|
-
if(getStorageEngine(COOKIE_STORAGE)
|
|
1629
|
+
if(globalStorageType!==undefined&&!SUPPORTED_STORAGE_TYPES.includes(globalStorageType)){globalStorageType=undefined;}let trulyAnonymousTracking=true;let storageEntries={};USER_SESSION_KEYS.forEach(sessionKey=>{var _entriesOptions,_ref,_ref2;const key=sessionKey;const storageKey=sessionKey;const configuredStorageType=(_entriesOptions=entriesOptions)===null||_entriesOptions===void 0||(_entriesOptions=_entriesOptions[key])===null||_entriesOptions===void 0?void 0:_entriesOptions.type;const preConsentStorageType=getStorageTypeFromPreConsentIfApplicable(state,sessionKey);// Storage type precedence order: pre-consent strategy > entry type > global type > default
|
|
1630
|
+
let storageType=(_ref=(_ref2=preConsentStorageType!==null&&preConsentStorageType!==void 0?preConsentStorageType:configuredStorageType)!==null&&_ref2!==void 0?_ref2:globalStorageType)!==null&&_ref!==void 0?_ref:defaultStorageType;if(!SUPPORTED_STORAGE_TYPES.includes(storageType)){storageType=defaultStorageType;}const finalStorageType=this.getResolvedStorageTypeForEntry(storageType,sessionKey);if(finalStorageType!==NO_STORAGE){trulyAnonymousTracking=false;}storageEntries=_objectSpread2(_objectSpread2({},storageEntries),{},{[sessionKey]:{type:finalStorageType,key:COOKIE_KEYS[storageKey]}});});n(()=>{state.storage.entries.value=storageEntries;state.storage.trulyAnonymousTracking.value=trulyAnonymousTracking;});}getResolvedStorageTypeForEntry(storageType,sessionKey){var _getStorageEngine2,_getStorageEngine3,_getStorageEngine4,_getStorageEngine5,_getStorageEngine6;let finalStorageType=storageType;switch(storageType){case LOCAL_STORAGE:if(!((_getStorageEngine2=getStorageEngine(LOCAL_STORAGE))!==null&&_getStorageEngine2!==void 0&&_getStorageEngine2.isEnabled)){finalStorageType=MEMORY_STORAGE;}break;case SESSION_STORAGE:if(!((_getStorageEngine3=getStorageEngine(SESSION_STORAGE))!==null&&_getStorageEngine3!==void 0&&_getStorageEngine3.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
|
|
1631
|
+
if((_getStorageEngine4=getStorageEngine(COOKIE_STORAGE))!==null&&_getStorageEngine4!==void 0&&_getStorageEngine4.isEnabled){finalStorageType=COOKIE_STORAGE;}else if((_getStorageEngine5=getStorageEngine(LOCAL_STORAGE))!==null&&_getStorageEngine5!==void 0&&_getStorageEngine5.isEnabled){finalStorageType=LOCAL_STORAGE;}else if((_getStorageEngine6=getStorageEngine(SESSION_STORAGE))!==null&&_getStorageEngine6!==void 0&&_getStorageEngine6.isEnabled){finalStorageType=SESSION_STORAGE;}else {finalStorageType=MEMORY_STORAGE;}break;}if(finalStorageType!==storageType){this.logger.warn(STORAGE_UNAVAILABLE_WARNING(STORE_MANAGER,sessionKey,storageType,finalStorageType));}return finalStorageType;}/**
|
|
1545
1632
|
* Create a new store
|
|
1546
1633
|
*/setStore(storeConfig){const storageEngine=getStorageEngine(storeConfig.type);this.stores[storeConfig.id]=new Store(storeConfig,storageEngine,this.pluginsManager);return this.stores[storeConfig.id];}/**
|
|
1547
1634
|
* Retrieve a store
|
|
@@ -1553,7 +1640,7 @@ const isValidSourceConfig=res=>isObjectLiteralAndNotNull(res)&&isObjectLiteralAn
|
|
|
1553
1640
|
* @param storageOpts Storage options from the load API options or the consent API options
|
|
1554
1641
|
* @param context Logger context
|
|
1555
1642
|
* @param logger Logger instance
|
|
1556
|
-
*/const validateStorageOptions=(storageOpts,context,logger)=>{if(!isObjectLiteralAndNotNull(storageOpts)){return;}const{type,entries}=storageOpts;if(isDefined(type)&&!isValidStorageType(type)){logger
|
|
1643
|
+
*/const validateStorageOptions=(storageOpts,context,logger)=>{if(!isObjectLiteralAndNotNull(storageOpts)){return;}const{type,entries}=storageOpts;if(isDefined(type)&&!isValidStorageType(type)){logger===null||logger===void 0||logger.warn(STORAGE_TYPE_VALIDATION_WARNING(context,type));}if(entries){Object.entries(entries).forEach(([entryKey,entryOpts])=>{const entryType=entryOpts===null||entryOpts===void 0?void 0:entryOpts.type;if(isDefined(entryType)&&!isValidStorageType(entryType)){logger===null||logger===void 0||logger.warn(UNSUPPORTED_STORAGE_ENTRY_TYPE_WARNING(context,entryKey,entryType));}});}};/**
|
|
1557
1644
|
* Parses a URL without the URL constructor, which is unavailable on legacy JS engines
|
|
1558
1645
|
* until the polyfills load.
|
|
1559
1646
|
*/const legacyParseUrl=url=>{const anchor=document.createElement('a');anchor.href=url;return {host:anchor.host,protocol:anchor.protocol};};const getTopDomain=url=>{// Extract the host and protocol. This runs before the polyfills load,
|
|
@@ -1577,11 +1664,11 @@ if(hostOnlyCookies||!webpageTopDomain){return dataServiceHostname===globalThis.l
|
|
|
1577
1664
|
* Removes trailing slash from url
|
|
1578
1665
|
* @param url
|
|
1579
1666
|
* @returns url
|
|
1580
|
-
*/const removeTrailingSlashes=url=>url
|
|
1667
|
+
*/const removeTrailingSlashes=url=>url!==null&&url!==void 0&&url.endsWith('/')?removeTrailingSlashes(url.substring(0,url.length-1)):url;const getDomain=url=>{try{const urlObj=new URL(url);return urlObj.host;}catch(error){return null;}};const getHostname=url=>{try{const urlObj=new URL(url);return urlObj.hostname;}catch(error){return null;}};/**
|
|
1581
1668
|
* Get the referring domain from the referrer URL
|
|
1582
1669
|
* @param referrer Page referrer
|
|
1583
1670
|
* @returns Page referring domain
|
|
1584
|
-
*/const getReferringDomain=referrer=>getDomain(referrer)
|
|
1671
|
+
*/const getReferringDomain=referrer=>{var _getDomain;return (_getDomain=getDomain(referrer))!==null&&_getDomain!==void 0?_getDomain:'';};/**
|
|
1585
1672
|
* Extracts UTM parameters from the URL
|
|
1586
1673
|
* @param url Page URL
|
|
1587
1674
|
* @returns UTM parameters
|
|
@@ -1596,7 +1683,7 @@ if(utmParam==='campaign'){utmParam='name';}result[utmParam]=value;}});}catch(err
|
|
|
1596
1683
|
|
|
1597
1684
|
const DEFAULT_PRE_CONSENT_STORAGE_STRATEGY='none';const DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE='immediate';
|
|
1598
1685
|
|
|
1599
|
-
const isErrorReportingEnabled=sourceConfig=>sourceConfig
|
|
1686
|
+
const isErrorReportingEnabled=sourceConfig=>{var _sourceConfig$statsCo;return (sourceConfig===null||sourceConfig===void 0||(_sourceConfig$statsCo=sourceConfig.statsCollection)===null||_sourceConfig$statsCo===void 0||(_sourceConfig$statsCo=_sourceConfig$statsCo.errors)===null||_sourceConfig$statsCo===void 0?void 0:_sourceConfig$statsCo.enabled)===true;};const isMetricsReportingEnabled=sourceConfig=>{var _sourceConfig$statsCo2;return (sourceConfig===null||sourceConfig===void 0||(_sourceConfig$statsCo2=sourceConfig.statsCollection)===null||_sourceConfig$statsCo2===void 0||(_sourceConfig$statsCo2=_sourceConfig$statsCo2.metrics)===null||_sourceConfig$statsCo2===void 0?void 0:_sourceConfig$statsCo2.enabled)===true;};
|
|
1600
1687
|
|
|
1601
1688
|
/**
|
|
1602
1689
|
* Validates and normalizes the consent options provided by the user
|
|
@@ -1620,7 +1707,7 @@ provider=undefined;}return {provider,consentManagerPluginName};};/**
|
|
|
1620
1707
|
* @param consentManagementOpts Consent management options provided by the user
|
|
1621
1708
|
* @param logger logger instance
|
|
1622
1709
|
* @returns An object containing the consent manager plugin name, initialized, enabled and consents data
|
|
1623
|
-
*/const getConsentManagementData=(consentManagementOpts,logger)=>{let consentManagerPluginName;let allowedConsentIds=[];let deniedConsentIds=[];let initialized=false;let provider;let enabled=consentManagementOpts
|
|
1710
|
+
*/const getConsentManagementData=(consentManagementOpts,logger)=>{let consentManagerPluginName;let allowedConsentIds=[];let deniedConsentIds=[];let initialized=false;let provider;let enabled=(consentManagementOpts===null||consentManagementOpts===void 0?void 0:consentManagementOpts.enabled)===true;if(isNonEmptyObject(consentManagementOpts)&&enabled){// Get the corresponding plugin name of the selected consent manager from the supported consent managers
|
|
1624
1711
|
({provider,consentManagerPluginName}=getConsentManagerInfo(consentManagementOpts,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
|
|
1625
1712
|
enabled=enabled&&Boolean(consentManagerPluginName);return {provider,consentManagerPluginName,initialized,enabled,consentsData};};
|
|
1626
1713
|
|
|
@@ -1656,11 +1743,11 @@ const cookieDomain=removeLeadingPeriod(providedCookieDomain).toLowerCase();/**
|
|
|
1656
1743
|
* The cookie domain also has to sit at or below the browser-verified domain of the webpage.
|
|
1657
1744
|
* Anything above it is a public suffix, ex: 'co.uk', which the browser refuses to scope
|
|
1658
1745
|
* cookies to however well it matches as a string suffix.
|
|
1659
|
-
*/if(!isDomainMatch(dataServiceHostname,cookieDomain)||!isDomainMatch(webpage.hostname,cookieDomain)||webpage.topDomain&&!isDomainMatch(cookieDomain,webpage.topDomain)){logger.error(SERVER_SIDE_COOKIE_FEATURE_OVERRIDE_ERROR(CONFIG_MANAGER,providedCookieDomain,webpage.hostname));return false;}return true;};const getServerSideCookiesStateData=logger=>{const{useServerSideCookies,dataServiceEndpoint,storage:storageOptsFromLoad,setCookieDomain,sameDomainCookiesOnly}=state.loadOptions.value;let cookieOptions=storageOptsFromLoad
|
|
1746
|
+
*/if(!isDomainMatch(dataServiceHostname,cookieDomain)||!isDomainMatch(webpage.hostname,cookieDomain)||webpage.topDomain&&!isDomainMatch(cookieDomain,webpage.topDomain)){logger.error(SERVER_SIDE_COOKIE_FEATURE_OVERRIDE_ERROR(CONFIG_MANAGER,providedCookieDomain,webpage.hostname));return false;}return true;};const getServerSideCookiesStateData=logger=>{const{useServerSideCookies,dataServiceEndpoint,storage:storageOptsFromLoad,setCookieDomain,sameDomainCookiesOnly}=state.loadOptions.value;let cookieOptions=storageOptsFromLoad===null||storageOptsFromLoad===void 0?void 0:storageOptsFromLoad.cookie;let sscEnabled=false;let finalDataServiceUrl;if(useServerSideCookies){var _cookieOptions$domain;sscEnabled=useServerSideCookies;const providedCookieDomain=(_cookieOptions$domain=cookieOptions.domain)!==null&&_cookieOptions$domain!==void 0?_cookieOptions$domain:setCookieDomain;/**
|
|
1660
1747
|
* Based on the following conditions, we decide whether to use the exact domain or not to determine the data service URL:
|
|
1661
1748
|
* 1. If the cookie domain is provided and it is not a top-level domain, then use the exact domain
|
|
1662
1749
|
* 2. If the sameDomainCookiesOnly flag is set to true, then use the exact domain
|
|
1663
|
-
*/const useExactDomain=isDefined(providedCookieDomain)&&!isWebpageTopLevelDomain(removeLeadingPeriod(providedCookieDomain))||sameDomainCookiesOnly;const{hostname:webpageHostname}=globalThis.location;const{topDomain:webpageTopDomain,topHost:webpageTopHost}=getWebpageTopDomain();const dataServiceUrl=getDataServiceUrl(dataServiceEndpoint
|
|
1750
|
+
*/const useExactDomain=isDefined(providedCookieDomain)&&!isWebpageTopLevelDomain(removeLeadingPeriod(providedCookieDomain))||sameDomainCookiesOnly;const{hostname:webpageHostname}=globalThis.location;const{topDomain:webpageTopDomain,topHost:webpageTopHost}=getWebpageTopDomain();const dataServiceUrl=getDataServiceUrl(dataServiceEndpoint!==null&&dataServiceEndpoint!==void 0?dataServiceEndpoint:DEFAULT_DATA_SERVICE_ENDPOINT,useExactDomain,webpageTopHost);// The hostname is unavailable on legacy JS engines without the URL polyfill,
|
|
1664
1751
|
// in which case the data service host cannot be verified
|
|
1665
1752
|
const dataServiceHostname=getHostname(dataServiceUrl);if(isValidURL(dataServiceUrl)&&dataServiceHostname){finalDataServiceUrl=removeTrailingSlashes(dataServiceUrl);sscEnabled=isServerSideCookiesUsable(dataServiceHostname,providedCookieDomain,{hostname:webpageHostname,topDomain:webpageTopDomain},sameDomainCookiesOnly,logger);// If the current hostname is different from the data service hostname, then it is a
|
|
1666
1753
|
// cross-site request. Cookies are not isolated by port, hence it plays no part here.
|
|
@@ -1668,29 +1755,29 @@ const dataServiceHostname=getHostname(dataServiceUrl);if(isValidURL(dataServiceU
|
|
|
1668
1755
|
// One round of cookie options manipulation is taking place here
|
|
1669
1756
|
// Based on these(setCookieDomain/storage.cookie or sameDomainCookiesOnly) two load-options, final cookie options are set in the storage module
|
|
1670
1757
|
// TODO: Refactor the cookie options manipulation logic in one place
|
|
1671
|
-
if(sscEnabled&&webpageHostname!==dataServiceHostname){cookieOptions={
|
|
1672
|
-
logger.error(DATA_SERVER_URL_INVALID_ERROR(CONFIG_MANAGER,dataServiceUrl));sscEnabled=false;}}return {sscEnabled,cookieOptions,finalDataServiceUrl};};const updateStorageStateFromLoadOptions=logger=>{const{storage:storageOptsFromLoad}=state.loadOptions.value;// Only reported here. The applicable default depends on the consent phase, so the unsupported
|
|
1758
|
+
if(sscEnabled&&webpageHostname!==dataServiceHostname){cookieOptions=_objectSpread2(_objectSpread2({},cookieOptions),{},{samesite:'None',secure:true});}}else {// A malformed dataServiceEndpoint reaches here, ex: a typo in an absolute URL
|
|
1759
|
+
logger.error(DATA_SERVER_URL_INVALID_ERROR(CONFIG_MANAGER,dataServiceUrl));sscEnabled=false;}}return {sscEnabled,cookieOptions,finalDataServiceUrl};};const updateStorageStateFromLoadOptions=logger=>{var _storageOptsFromLoad$;const{storage:storageOptsFromLoad}=state.loadOptions.value;// Only reported here. The applicable default depends on the consent phase, so the unsupported
|
|
1673
1760
|
// values are resolved in the store manager.
|
|
1674
|
-
validateStorageOptions(storageOptsFromLoad,CONFIG_MANAGER,logger);let storageEncryptionVersion=storageOptsFromLoad
|
|
1761
|
+
validateStorageOptions(storageOptsFromLoad,CONFIG_MANAGER,logger);let storageEncryptionVersion=storageOptsFromLoad===null||storageOptsFromLoad===void 0||(_storageOptsFromLoad$=storageOptsFromLoad.encryption)===null||_storageOptsFromLoad$===void 0?void 0:_storageOptsFromLoad$.version;const encryptionPluginName=storageEncryptionVersion&&StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];if(!isUndefined(storageEncryptionVersion)&&isUndefined(encryptionPluginName)){// set the default encryption plugin
|
|
1675
1762
|
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
|
|
1676
|
-
const configuredMigrationValue=storageOptsFromLoad
|
|
1677
|
-
const preConsentOpts=state.loadOptions.value.preConsent;const configuredStrategy=preConsentOpts
|
|
1763
|
+
const configuredMigrationValue=storageOptsFromLoad===null||storageOptsFromLoad===void 0?void 0: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));}const{sscEnabled,finalDataServiceUrl,cookieOptions}=getServerSideCookiesStateData(logger);n(()=>{state.storage.cookie.value=cookieOptions;state.serverCookies.isEnabledServerSideCookies.value=sscEnabled;state.serverCookies.dataServiceUrl.value=finalDataServiceUrl;state.storage.encryptionPluginName.value=StorageEncryptionVersionsToPluginNameMap[storageEncryptionVersion];state.storage.migrate.value=finalMigrationVal;});};const updateConsentsStateFromLoadOptions=logger=>{var _preConsentOpts$stora,_preConsentOpts$stora2,_preConsentOpts$event,_preConsentOpts$event2;const{provider,consentManagerPluginName,initialized,enabled,consentsData}=getConsentManagementData(state.loadOptions.value.consentManagement,logger);// Pre-consent
|
|
1764
|
+
const preConsentOpts=state.loadOptions.value.preConsent;const configuredStrategy=preConsentOpts===null||preConsentOpts===void 0||(_preConsentOpts$stora=preConsentOpts.storage)===null||_preConsentOpts$stora===void 0?void 0:_preConsentOpts$stora.strategy;if(isDefined(configuredStrategy)){logger.warn(DEPRECATED_PRE_CONSENT_STORAGE_STRATEGY(CONFIG_MANAGER));}// The storage load API options drive the pre-consent phase only when it is explicitly enabled,
|
|
1678
1765
|
// so an existing configuration keeps persisting nothing before consent is given. Enabling it
|
|
1679
1766
|
// takes precedence over the deprecated strategy, otherwise a migration that leaves the strategy
|
|
1680
1767
|
// in place would silently do nothing.
|
|
1681
|
-
let storageStrategy;if(preConsentOpts
|
|
1768
|
+
let storageStrategy;if((preConsentOpts===null||preConsentOpts===void 0||(_preConsentOpts$stora2=preConsentOpts.storage)===null||_preConsentOpts$stora2===void 0?void 0:_preConsentOpts$stora2.enabled)!==true){storageStrategy=configuredStrategy!==null&&configuredStrategy!==void 0?configuredStrategy:DEFAULT_PRE_CONSENT_STORAGE_STRATEGY;const StorageStrategies=['none','session','anonymousId'];if(!StorageStrategies.includes(storageStrategy)){storageStrategy=DEFAULT_PRE_CONSENT_STORAGE_STRATEGY;logger.warn(UNSUPPORTED_PRE_CONSENT_STORAGE_STRATEGY(CONFIG_MANAGER,configuredStrategy,DEFAULT_PRE_CONSENT_STORAGE_STRATEGY));}}let eventsDeliveryType=(_preConsentOpts$event=preConsentOpts===null||preConsentOpts===void 0||(_preConsentOpts$event2=preConsentOpts.events)===null||_preConsentOpts$event2===void 0?void 0:_preConsentOpts$event2.delivery)!==null&&_preConsentOpts$event!==void 0?_preConsentOpts$event:DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE;const deliveryTypes=['immediate','buffer'];if(isDefined(eventsDeliveryType)&&!deliveryTypes.includes(eventsDeliveryType)){var _preConsentOpts$event3;eventsDeliveryType=DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE;logger.warn(UNSUPPORTED_PRE_CONSENT_EVENTS_DELIVERY_TYPE(CONFIG_MANAGER,preConsentOpts===null||preConsentOpts===void 0||(_preConsentOpts$event3=preConsentOpts.events)===null||_preConsentOpts$event3===void 0?void 0:_preConsentOpts$event3.delivery,DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE));}n(()=>{var _state$loadOptions$va;state.consents.activeConsentManagerPluginName.value=consentManagerPluginName;state.consents.initialized.value=initialized;state.consents.enabled.value=enabled;state.consents.data.value=consentsData;state.consents.provider.value=provider;state.consents.preConsent.value={// Only enable pre-consent if it is explicitly enabled and
|
|
1682
1769
|
// if it is not already initialized and
|
|
1683
1770
|
// if consent management is enabled
|
|
1684
|
-
enabled:state.loadOptions.value.preConsent
|
|
1771
|
+
enabled:((_state$loadOptions$va=state.loadOptions.value.preConsent)===null||_state$loadOptions$va===void 0?void 0:_state$loadOptions$va.enabled)===true&&initialized===false&&enabled===true,storage:{strategy:storageStrategy},events:{delivery:eventsDeliveryType}};});};/**
|
|
1685
1772
|
* Determines the consent management state variables from the source config data
|
|
1686
1773
|
* @param resp Source config response
|
|
1687
1774
|
* @param logger Logger instance
|
|
1688
|
-
*/const updateConsentsState=resp=>{let resolutionStrategy=state.consents.resolutionStrategy.value;let cmpMetadata;if(isObjectLiteralAndNotNull(resp.consentManagementMetadata)){if(state.consents.provider.value){resolutionStrategy=resp.consentManagementMetadata.providers.find(p=>p.provider===state.consents.provider.value)
|
|
1775
|
+
*/const updateConsentsState=resp=>{let resolutionStrategy=state.consents.resolutionStrategy.value;let cmpMetadata;if(isObjectLiteralAndNotNull(resp.consentManagementMetadata)){if(state.consents.provider.value){var _resp$consentManageme,_resp$consentManageme2;resolutionStrategy=(_resp$consentManageme=(_resp$consentManageme2=resp.consentManagementMetadata.providers.find(p=>p.provider===state.consents.provider.value))===null||_resp$consentManageme2===void 0?void 0:_resp$consentManageme2.resolutionStrategy)!==null&&_resp$consentManageme!==void 0?_resp$consentManageme:state.consents.resolutionStrategy.value;}cmpMetadata=resp.consentManagementMetadata;}// If the provider is custom, then the resolution strategy is not applicable
|
|
1689
1776
|
if(state.consents.provider.value==='custom'){resolutionStrategy=undefined;}n(()=>{state.consents.metadata.value=clone(cmpMetadata);state.consents.resolutionStrategy.value=resolutionStrategy;});};const updateDataPlaneEventsStateFromLoadOptions=logger=>{if(state.dataPlaneEvents.deliveryEnabled.value){const defaultEventsQueuePluginName='XhrQueue';let eventsQueuePluginName=defaultEventsQueuePluginName;if(state.loadOptions.value.useBeacon){if(state.capabilities.isBeaconAvailable.value){eventsQueuePluginName='BeaconQueue';}else {eventsQueuePluginName=defaultEventsQueuePluginName;logger.warn(UNSUPPORTED_BEACON_API_WARNING(CONFIG_MANAGER));}}n(()=>{state.dataPlaneEvents.eventsQueuePluginName.value=eventsQueuePluginName;});}};const getSourceConfigURL=(configUrl,writeKey,lockIntegrationsVersion,lockPluginsVersion,logger)=>{const defSearchParams=new URLSearchParams({p:MODULE_TYPE,v:APP_VERSION,build:BUILD_TYPE,writeKey,lockIntegrationsVersion:lockIntegrationsVersion.toString(),lockPluginsVersion:lockPluginsVersion.toString()});let origin=DEFAULT_CONFIG_BE_URL;let searchParams=defSearchParams;let pathname='/sourceConfig/';let hash='';if(isValidURL(configUrl)){const configUrlInstance=new URL(configUrl);if(!removeTrailingSlashes(configUrlInstance.pathname).endsWith('/sourceConfig')){configUrlInstance.pathname=`${removeTrailingSlashes(configUrlInstance.pathname)}/sourceConfig/`;}configUrlInstance.pathname=removeDuplicateSlashes(configUrlInstance.pathname);defSearchParams.forEach((value,key)=>{if(configUrlInstance.searchParams.get(key)===null){configUrlInstance.searchParams.set(key,value);}});origin=configUrlInstance.origin;pathname=configUrlInstance.pathname;searchParams=configUrlInstance.searchParams;hash=configUrlInstance.hash;}else {logger.warn(INVALID_CONFIG_URL_WARNING(CONFIG_MANAGER,configUrl));}return `${origin}${pathname}?${searchParams}${hash}`;};/**
|
|
1690
1777
|
* Transforms destinations config from source config response to Destination format
|
|
1691
1778
|
* @param destinations Array of destination items from config response
|
|
1692
1779
|
* @returns Array of transformed Destination objects
|
|
1693
|
-
*/const getDestinationsFromConfig=destinations=>destinations.map(destination=>
|
|
1780
|
+
*/const getDestinationsFromConfig=destinations=>destinations.map(destination=>{var _destination$shouldAp,_destination$propagat;return {id:destination.id,displayName:destination.destinationDefinition.displayName,enabled:destination.enabled,config:destination.config,shouldApplyDeviceModeTransformation:(_destination$shouldAp=destination.shouldApplyDeviceModeTransformation)!==null&&_destination$shouldAp!==void 0?_destination$shouldAp:false,propagateEventsUntransformedOnError:(_destination$propagat=destination.propagateEventsUntransformedOnError)!==null&&_destination$propagat!==void 0?_destination$propagat:false,userFriendlyId:getDestinationUserFriendlyId(destination.destinationDefinition.displayName,destination.id),isCustomIntegration:destination.destinationDefinition.displayName===CUSTOM_DEVICE_MODE_DESTINATION_DISPLAY_NAME};});
|
|
1694
1781
|
|
|
1695
1782
|
/**
|
|
1696
1783
|
* A function that determines the base URL for the integrations or plugins SDK
|
|
@@ -1735,10 +1822,10 @@ state.nativeDestinations.loadOnlyIntegrations.value=integrations;});this.getConf
|
|
|
1735
1822
|
if(!isDefined(response)){if(isDefined(details)){this.onError(details.error,SOURCE_CONFIG_FETCH_ERROR);}else {this.onError(new Error(SOURCE_CONFIG_FETCH_ERROR));}return;}let res;try{if(isString(response)){res=JSON.parse(response);}else {res=response;}}catch(err){this.onError(err,SOURCE_CONFIG_RESOLUTION_ERROR);return;}if(!isValidSourceConfig(res)){this.onError(new Error(SOURCE_CONFIG_RESOLUTION_ERROR));return;}// Log error and abort if source is disabled
|
|
1736
1823
|
if(res.source.enabled===false){this.logger.error(SOURCE_DISABLED_ERROR);return;}// set the values in state for reporting slice
|
|
1737
1824
|
updateReportingState(res);const nativeDestinations=res.source.destinations.length>0?getDestinationsFromConfig(res.source.destinations):[];// set in the state --> source, destination, lifecycle, reporting
|
|
1738
|
-
n(()=>{
|
|
1825
|
+
n(()=>{var _state$loadOptions$va;// set source related information in state
|
|
1739
1826
|
state.source.value={config:res.source.config,name:res.source.name,id:res.source.id,workspaceId:res.source.workspaceId};// set device mode destination related information in state
|
|
1740
1827
|
state.nativeDestinations.configuredDestinations.value=nativeDestinations;// set the desired optional plugins
|
|
1741
|
-
state.plugins.pluginsToLoadFromConfig.value=state.loadOptions.value.plugins
|
|
1828
|
+
state.plugins.pluginsToLoadFromConfig.value=(_state$loadOptions$va=state.loadOptions.value.plugins)!==null&&_state$loadOptions$va!==void 0?_state$loadOptions$va:[];updateConsentsState(res);// set application lifecycle state
|
|
1742
1829
|
state.lifecycle.status.value='configured';});}/**
|
|
1743
1830
|
* A function to fetch source config either from /sourceConfig endpoint
|
|
1744
1831
|
* or from getSourceConfig load option
|
|
@@ -1753,19 +1840,19 @@ this.httpClient.getAsyncData({url:state.lifecycle.sourceConfigUrl.value,options:
|
|
|
1753
1840
|
* @returns string
|
|
1754
1841
|
*/const getTimezone=()=>{// Not susceptible to super-linear backtracking
|
|
1755
1842
|
// eslint-disable-next-line sonarjs/slow-regex
|
|
1756
|
-
const timezone=/([A-Z]+[+-]\d+)/.exec(new Date().toString());return timezone
|
|
1843
|
+
const timezone=/([A-Z]+[+-]\d+)/.exec(new Date().toString());return timezone!==null&&timezone!==void 0&&timezone[1]?timezone[1]:'NA';};
|
|
1757
1844
|
|
|
1758
1845
|
/**
|
|
1759
1846
|
* Get the referrer URL
|
|
1760
1847
|
* @returns The referrer URL
|
|
1761
|
-
*/const getReferrer=(getDocument=()=>document)=>getDocument()
|
|
1848
|
+
*/const getReferrer=(getDocument=()=>document)=>{var _getDocument;return ((_getDocument=getDocument())===null||_getDocument===void 0?void 0:_getDocument.referrer)||'$direct';};/**
|
|
1762
1849
|
* To get the canonical URL of the page
|
|
1763
1850
|
* @returns canonical URL
|
|
1764
|
-
*/const getCanonicalUrl=(getDocument=()=>document)=>{const docInstance=getDocument();const tags=docInstance.getElementsByTagName('link');let canonicalUrl='';for(let i=0;tags[i];i+=1){const tag=tags[i];if(tag.getAttribute('rel')==='canonical'&&!canonicalUrl){canonicalUrl=tag.getAttribute('href')
|
|
1851
|
+
*/const getCanonicalUrl=(getDocument=()=>document)=>{const docInstance=getDocument();const tags=docInstance.getElementsByTagName('link');let canonicalUrl='';for(let i=0;tags[i];i+=1){const tag=tags[i];if(tag.getAttribute('rel')==='canonical'&&!canonicalUrl){var _tag$getAttribute;canonicalUrl=(_tag$getAttribute=tag.getAttribute('href'))!==null&&_tag$getAttribute!==void 0?_tag$getAttribute:'';break;}}return canonicalUrl;};const getUserAgent=(getNavigator=()=>globalThis.navigator)=>{const navigator=getNavigator();if(isUndefined(navigator)){return null;}let{userAgent}=navigator;const{brave}=navigator;// For supporting Brave browser detection,
|
|
1765
1852
|
// add "Brave/<version>" to the user agent with the version value from the Chrome component
|
|
1766
1853
|
if(brave&&Object.getPrototypeOf(brave).isBrave){// Example:
|
|
1767
1854
|
// Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36
|
|
1768
|
-
const matchedArr=userAgent.match(/(chrome)\/([\w.]+)/i);if(matchedArr){userAgent=`${userAgent} Brave/${matchedArr[2]}`;}}return userAgent;};const getLanguage=(getNavigator=()=>globalThis.navigator)=>{const navigator=getNavigator();if(isUndefined(navigator)){return null;}return navigator.language
|
|
1855
|
+
const matchedArr=userAgent.match(/(chrome)\/([\w.]+)/i);if(matchedArr){userAgent=`${userAgent} Brave/${matchedArr[2]}`;}}return userAgent;};const getLanguage=(getNavigator=()=>globalThis.navigator)=>{var _navigator$language;const navigator=getNavigator();if(isUndefined(navigator)){return null;}return (_navigator$language=navigator.language)!==null&&_navigator$language!==void 0?_navigator$language:navigator.browserLanguage;};/**
|
|
1769
1856
|
* Default page properties
|
|
1770
1857
|
* @returns Default page properties
|
|
1771
1858
|
*/const getDefaultPageProperties=(getLocation=()=>globalThis.location,getDocument=()=>document)=>{const location=getLocation();const canonicalUrl=getCanonicalUrl(getDocument);let path=location.pathname;const{href:tabUrl}=location;let pageUrl=tabUrl;const{search}=location;// If valid canonical URL is provided use this as page URL.
|
|
@@ -1773,17 +1860,7 @@ if(canonicalUrl){try{const urlObj=new URL(canonicalUrl);// If existing, query pa
|
|
|
1773
1860
|
if(urlObj.search===''){pageUrl=canonicalUrl+search;}else {pageUrl=canonicalUrl;}path=urlObj.pathname;}catch(err){// Do nothing
|
|
1774
1861
|
}}const url=getUrlWithoutHash(pageUrl);const{title}=getDocument();const referrer=getReferrer(getDocument);return {path,referrer,referring_domain:getReferringDomain(referrer),search,title,url,tab_url:tabUrl};};
|
|
1775
1862
|
|
|
1776
|
-
const getUserAgentClientHint=(callback,level='none')=>{if(level==='none'){callback(undefined);}if(level==='default'){callback(navigator.userAgentData);}if(level==='full'){navigator.userAgentData
|
|
1777
|
-
|
|
1778
|
-
const isDatasetAvailable=()=>{const testElement=globalThis.document.createElement('div');testElement.setAttribute('data-a-b','c');return testElement.dataset?testElement.dataset.aB==='c':false;};const legacyJSEngineRequiredPolyfills={// Ideally, we should separate the checks for URL and URLSearchParams but
|
|
1779
|
-
// the polyfill service serves them under the same feature name, "URL".
|
|
1780
|
-
URL:()=>!isFunction(globalThis.URL)||!isFunction(globalThis.URLSearchParams),Promise:()=>!isFunction(globalThis.Promise),'Number.isNaN':()=>!isFunction(globalThis.Number.isNaN),'Number.isInteger':()=>!isFunction(globalThis.Number.isInteger),'Array.from':()=>!isFunction(globalThis.Array.from),'Array.prototype.find':()=>!isFunction(globalThis.Array.prototype.find),'Array.prototype.includes':()=>!isFunction(globalThis.Array.prototype.includes),'String.prototype.endsWith':()=>!isFunction(globalThis.String.prototype.endsWith),'String.prototype.startsWith':()=>!isFunction(globalThis.String.prototype.startsWith),'String.prototype.includes':()=>!isFunction(globalThis.String.prototype.includes),'String.prototype.replaceAll':()=>!isFunction(globalThis.String.prototype.replaceAll),'String.fromCodePoint':()=>!isFunction(globalThis.String.fromCodePoint),'Object.entries':()=>!isFunction(globalThis.Object.entries),'Object.values':()=>!isFunction(globalThis.Object.values),'Object.assign':()=>!isFunction(globalThis.Object.assign),'Object.fromEntries':()=>!isFunction(globalThis.Object.fromEntries),'Element.prototype.dataset':()=>!isDatasetAvailable(),// Ideally, we should separate the checks for TextEncoder and TextDecoder but
|
|
1781
|
-
// the polyfill service serves them under the same feature name, "TextEncoder".
|
|
1782
|
-
TextEncoder:()=>!isFunction(globalThis.TextEncoder)||!isFunction(globalThis.TextDecoder),requestAnimationFrame:()=>!isFunction(globalThis.requestAnimationFrame)||!isFunction(globalThis.cancelAnimationFrame),CustomEvent:()=>!isFunction(globalThis.CustomEvent),'navigator.sendBeacon':()=>!isFunction(globalThis.navigator.sendBeacon),// Note, the polyfill service serves both ArrayBuffer and Uint8Array under the same feature name, "ArrayBuffer".
|
|
1783
|
-
ArrayBuffer:()=>!isFunction(globalThis.Uint8Array),Set:()=>!isFunction(globalThis.Set),atob:()=>!isFunction(globalThis.atob)};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;};
|
|
1784
|
-
|
|
1785
|
-
const polyfillIoSdkUrl='https://polyfill-fastly.io/v3/polyfill.min.js';const POLYFILL_URL=`${polyfillIoSdkUrl}?version=3.111.0&features=${Object.keys(legacyJSEngineRequiredPolyfills).join('%2C')}`;const POLYFILL_LOAD_TIMEOUT=10*1000;// 10 seconds
|
|
1786
|
-
const POLYFILL_SCRIPT_ID='rudderstackPolyfill';
|
|
1863
|
+
const getUserAgentClientHint=(callback,level='none')=>{if(level==='none'){callback(undefined);}if(level==='default'){callback(navigator.userAgentData);}if(level==='full'){var _navigator$userAgentD;(_navigator$userAgentD=navigator.userAgentData)===null||_navigator$userAgentD===void 0||_navigator$userAgentD.getHighEntropyValues(['architecture','bitness','brands','mobile','model','platform','platformVersion','uaFullVersion','fullVersionList','wow64']).then(ua=>{callback(ua);}).catch(()=>{callback();});}};
|
|
1787
1864
|
|
|
1788
1865
|
const detectAdBlockers=httpClient=>{state.capabilities.isAdBlockerDetectionInProgress.value=true;try{// Apparently, '?view=ad' is a query param that is blocked by majority of adblockers
|
|
1789
1866
|
// Use source config URL here as it is very unlikely to be blocked by adblockers
|
|
@@ -1791,9 +1868,9 @@ const detectAdBlockers=httpClient=>{state.capabilities.isAdBlockerDetectionInPro
|
|
|
1791
1868
|
// This will work even if the users proxies it.
|
|
1792
1869
|
// The edge case where this doesn't work is when HEAD method is not allowed by the server (user's)
|
|
1793
1870
|
const baseUrl=new URL(state.lifecycle.sourceConfigUrl.value);const url=`${baseUrl.origin}${baseUrl.pathname}?view=ad`;httpClient.getAsyncData({url,options:{// We actually don't need the response from the request, so we are using HEAD
|
|
1794
|
-
method:'HEAD',headers:{'Content-Type':undefined}},isRawResponse:true,callback:(result,details)=>{state.capabilities.isAdBlockerDetectionInProgress.value=false;// not ad blocked if the request is successful or it is not internally redirected on the client side
|
|
1871
|
+
method:'HEAD',headers:{'Content-Type':undefined}},isRawResponse:true,callback:(result,details)=>{var _details$xhr;state.capabilities.isAdBlockerDetectionInProgress.value=false;// not ad blocked if the request is successful or it is not internally redirected on the client side
|
|
1795
1872
|
// Often adblockers instead of blocking the request, they redirect it to an internal URL
|
|
1796
|
-
state.capabilities.isAdBlocked.value=details
|
|
1873
|
+
state.capabilities.isAdBlocked.value=(details===null||details===void 0?void 0:details.error)!==undefined||(details===null||details===void 0||(_details$xhr=details.xhr)===null||_details$xhr===void 0?void 0:_details$xhr.responseURL)!==url;}});}catch(err){// Reset the flag to prevent blocking future detection attempts
|
|
1797
1874
|
state.capabilities.isAdBlockerDetectionInProgress.value=false;// Re-throw the error to be handled by the caller
|
|
1798
1875
|
throw err;}};
|
|
1799
1876
|
|
|
@@ -1811,10 +1888,13 @@ state.capabilities.isBeaconAvailable.value=hasBeacon();state.capabilities.isUaCH
|
|
|
1811
1888
|
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
|
|
1812
1889
|
j(()=>{if(state.loadOptions.value.sendAdblockPage===true&&state.lifecycle.sourceConfigUrl.value!==undefined){detectAdBlockers(this.httpClient);}});}/**
|
|
1813
1890
|
* Detect if polyfills are required and then load script from polyfill URL
|
|
1814
|
-
*/prepareBrowserCapabilities(){
|
|
1815
|
-
//
|
|
1816
|
-
|
|
1817
|
-
|
|
1891
|
+
*/prepareBrowserCapabilities(){// The snippet only hands the modern build to engines that ship every polyfill-list API the
|
|
1892
|
+
// SDK and integrations call (replaceAll is listed but unused), so this is legacy-only.
|
|
1893
|
+
{this.onReady();return;}}/**
|
|
1894
|
+
* Report the features that the polyfill script did not apply and then set the
|
|
1895
|
+
* lifecycle status to next phase
|
|
1896
|
+
*/onPolyfillLoaded(){// Guarded too so the detection list is dropped from the modern bundle
|
|
1897
|
+
this.onReady();}/**
|
|
1818
1898
|
* Attach listeners to window to observe event that update capabilities state values
|
|
1819
1899
|
*/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));}/**
|
|
1820
1900
|
* Set the lifecycle status to next phase
|
|
@@ -1822,7 +1902,7 @@ delete globalThis[polyfillCallbackName];};globalThis[polyfillCallbackName]=polyf
|
|
|
1822
1902
|
onReady(){this.detectBrowserCapabilities();state.lifecycle.status.value='browserCapabilitiesReady';}/**
|
|
1823
1903
|
* Handles error
|
|
1824
1904
|
* @param error The error object
|
|
1825
|
-
*/onError(error,groupingHash){this.errorHandler.onError({error,context:CAPABILITIES_MANAGER,groupingHash});}}
|
|
1905
|
+
*/onError(error,groupingHash){void this.errorHandler.onError({error,context:CAPABILITIES_MANAGER,groupingHash});}}
|
|
1826
1906
|
|
|
1827
1907
|
const CHANNEL='web';// These are the top-level elements in the standard RudderStack event spec
|
|
1828
1908
|
const TOP_LEVEL_ELEMENTS=['integrations','anonymousId','originalTimestamp'];// Reserved elements in the context of standard RudderStack event spec
|
|
@@ -1830,7 +1910,7 @@ const TOP_LEVEL_ELEMENTS=['integrations','anonymousId','originalTimestamp'];// R
|
|
|
1830
1910
|
const CONTEXT_RESERVED_ELEMENTS=['library','consentManagement','userAgent','ua-ch','screen'];// Reserved elements in the standard RudderStack event spec
|
|
1831
1911
|
const RESERVED_ELEMENTS=['id','anonymous_id','user_id','sent_at','timestamp','received_at','original_timestamp','event','event_text','channel','context_ip','context_request_ip','context_passed_ip','group_id','previous_id'];
|
|
1832
1912
|
|
|
1833
|
-
const CUSTOM_CONTEXT='CustomContext';const PROTOTYPE_POLLUTION_KEYS=new Set(['__proto__','constructor','prototype']);const OBJECT_CONSTRUCTOR_SOURCE=Function.prototype.toString.call(Object);const isPlainObject=value=>{if(!isObjectLiteralAndNotNull(value)){return false;}const prototype=Object.getPrototypeOf(value);if(prototype===null){return true;}const constructor=Object.prototype.hasOwnProperty.call(prototype,'constructor')?prototype.constructor:undefined;return typeof constructor==='function'&&constructor.prototype===prototype&&Function.prototype.toString.call(constructor)===OBJECT_CONSTRUCTOR_SOURCE;};const containsPrototypePollutionKey=(value,visitedObjects=new Set())=>{if(!isObjectLiteralAndNotNull(value)&&!Array.isArray(value)){return false;}const traversableValue=value;if(visitedObjects.has(traversableValue)){return false;}visitedObjects.add(traversableValue);return Object.keys(traversableValue).some(key=>{return PROTOTYPE_POLLUTION_KEYS.has(key)||containsPrototypePollutionKey(traversableValue[key],visitedObjects);});};const filterReservedCustomContextKeys=(context,logger)=>{const retainedContext={};Object.keys(context).forEach(key=>{if(CONTEXT_RESERVED_ELEMENTS.includes(key)){logger.warn(RESERVED_CUSTOM_CONTEXT_KEY_WARNING(CUSTOM_CONTEXT,key));return;}Object.defineProperty(retainedContext,key,{configurable:true,enumerable:true,value:context[key]===context?retainedContext:context[key],writable:true});});return retainedContext;};const prepareCustomContextUpdate=(input,logger)=>{try{if(!isPlainObject(input)){logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}const acceptedInput=filterReservedCustomContextKeys(input,logger);if(containsPrototypePollutionKey(acceptedInput)){logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}const sanitizedContext=getSanitizedValue(acceptedInput,logger);return clone(sanitizedContext);}catch{logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}};
|
|
1913
|
+
const CUSTOM_CONTEXT='CustomContext';const PROTOTYPE_POLLUTION_KEYS=new Set(['__proto__','constructor','prototype']);const OBJECT_CONSTRUCTOR_SOURCE=Function.prototype.toString.call(Object);const isPlainObject=value=>{if(!isObjectLiteralAndNotNull(value)){return false;}const prototype=Object.getPrototypeOf(value);if(prototype===null){return true;}const constructor=Object.prototype.hasOwnProperty.call(prototype,'constructor')?prototype.constructor:undefined;return typeof constructor==='function'&&constructor.prototype===prototype&&Function.prototype.toString.call(constructor)===OBJECT_CONSTRUCTOR_SOURCE;};const containsPrototypePollutionKey=(value,visitedObjects=new Set())=>{if(!isObjectLiteralAndNotNull(value)&&!Array.isArray(value)){return false;}const traversableValue=value;if(visitedObjects.has(traversableValue)){return false;}visitedObjects.add(traversableValue);return Object.keys(traversableValue).some(key=>{return PROTOTYPE_POLLUTION_KEYS.has(key)||containsPrototypePollutionKey(traversableValue[key],visitedObjects);});};const filterReservedCustomContextKeys=(context,logger)=>{const retainedContext={};Object.keys(context).forEach(key=>{if(CONTEXT_RESERVED_ELEMENTS.includes(key)){logger.warn(RESERVED_CUSTOM_CONTEXT_KEY_WARNING(CUSTOM_CONTEXT,key));return;}Object.defineProperty(retainedContext,key,{configurable:true,enumerable:true,value:context[key]===context?retainedContext:context[key],writable:true});});return retainedContext;};const prepareCustomContextUpdate=(input,logger)=>{try{if(!isPlainObject(input)){logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}const acceptedInput=filterReservedCustomContextKeys(input,logger);if(containsPrototypePollutionKey(acceptedInput)){logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}const sanitizedContext=getSanitizedValue(acceptedInput,logger);return clone(sanitizedContext);}catch(_unused){logger.warn(INVALID_CUSTOM_CONTEXT_WARNING(CUSTOM_CONTEXT));return undefined;}};
|
|
1834
1914
|
|
|
1835
1915
|
class CustomContextStore{constructor(state,logger){this.state=state;this.logger=logger;}set(context){const update=prepareCustomContextUpdate(context,this.logger);if(!update){return;}const mergedContext=mergeDeepRight(clone(this.state.value),update);this.state.value=removeUndefinedAndNullValues(mergedContext);}get(){return clone(this.state.value);}clear(){this.state.value={};}}
|
|
1836
1916
|
|
|
@@ -1849,7 +1929,7 @@ class CustomContextStore{constructor(state,logger){this.state=state;this.logger=
|
|
|
1849
1929
|
* @returns boolean
|
|
1850
1930
|
*/const isPositiveInteger=num=>isNumber(num)&&num>=0&&Number.isInteger(num);
|
|
1851
1931
|
|
|
1852
|
-
const MIN_SESSION_ID_LENGTH=10;const isCutOffTimeExceeded=sessionInfo=>{const{cutOff}=sessionInfo;const timestamp=Date.now();return Boolean(cutOff
|
|
1932
|
+
const _excluded$1=["entries"];const MIN_SESSION_ID_LENGTH=10;const isCutOffTimeExceeded=sessionInfo=>{const{cutOff}=sessionInfo;const timestamp=Date.now();return Boolean((cutOff===null||cutOff===void 0?void 0:cutOff.enabled)&&cutOff.expiresAt&×tamp>cutOff.expiresAt);};/**
|
|
1853
1933
|
* A function to validate whether the current auto tracking session has expired or not.
|
|
1854
1934
|
* It checks for the current session expiry and the cut off time expiry.
|
|
1855
1935
|
* @param sessionInfo session info
|
|
@@ -1862,13 +1942,13 @@ const MIN_SESSION_ID_LENGTH=10;const isCutOffTimeExceeded=sessionInfo=>{const{cu
|
|
|
1862
1942
|
* @param {number} sessionId
|
|
1863
1943
|
* @param logger logger
|
|
1864
1944
|
* @returns
|
|
1865
|
-
*/const isManualSessionIdValid=(sessionId,logger)=>{if(!sessionId||!isPositiveInteger(sessionId)||!hasMinLength(MIN_SESSION_ID_LENGTH,sessionId)){logger.warn(INVALID_SESSION_ID_WARNING(USER_SESSION_MANAGER,sessionId,MIN_SESSION_ID_LENGTH));return false;}return true;};const getCutOffExpirationTimestamp=cutOff=>{if(!cutOff
|
|
1945
|
+
*/const isManualSessionIdValid=(sessionId,logger)=>{if(!sessionId||!isPositiveInteger(sessionId)||!hasMinLength(MIN_SESSION_ID_LENGTH,sessionId)){logger.warn(INVALID_SESSION_ID_WARNING(USER_SESSION_MANAGER,sessionId,MIN_SESSION_ID_LENGTH));return false;}return true;};const getCutOffExpirationTimestamp=cutOff=>{var _cutOff$expiresAt;if(!(cutOff!==null&&cutOff!==void 0&&cutOff.enabled)){return undefined;}return (_cutOff$expiresAt=cutOff.expiresAt)!==null&&_cutOff$expiresAt!==void 0?_cutOff$expiresAt:isPositiveInteger(cutOff.duration)?Date.now()+cutOff.duration:undefined;};/**
|
|
1866
1946
|
* A function to generate new auto tracking session
|
|
1867
1947
|
* @param sessionInfo session info
|
|
1868
1948
|
* @returns SessionInfo
|
|
1869
|
-
*/const generateAutoTrackingSession=sessionInfo=>{const{timeout,cutOff}=sessionInfo;const timestamp=Date.now();return {id:timestamp,// set the current timestamp
|
|
1949
|
+
*/const generateAutoTrackingSession=sessionInfo=>{const{timeout,cutOff}=sessionInfo;const timestamp=Date.now();return _objectSpread2({id:timestamp,// set the current timestamp
|
|
1870
1950
|
expiresAt:timestamp+timeout,// set the expiry time of the session
|
|
1871
|
-
timeout,autoTrack:true
|
|
1951
|
+
timeout,autoTrack:true},cutOff&&{cutOff});};/**
|
|
1872
1952
|
* A function to generate new manual tracking session
|
|
1873
1953
|
* @param id Provided sessionId
|
|
1874
1954
|
* @param logger Logger module
|
|
@@ -1877,19 +1957,19 @@ timeout,autoTrack:true,...(cutOff&&{cutOff})};};/**
|
|
|
1877
1957
|
* Generate a new anonymousId
|
|
1878
1958
|
* @returns string anonymousID
|
|
1879
1959
|
*/const generateAnonymousId=()=>generateUUID();const isKnownResetEntry=key=>Object.prototype.hasOwnProperty.call(DEFAULT_RESET_OPTIONS.entries,key);const getFinalResetOptions=options=>{// Legacy behavior: toggle only anonymousId without mutating defaults
|
|
1880
|
-
if(isBoolean(options)){const{entries
|
|
1881
|
-
if(isObjectLiteralAndNotNull(options)&&isObjectLiteralAndNotNull(options.entries)){const optionEntries=options.entries;const validEntries=Object.keys(optionEntries).reduce((entries,key)=>{if(isKnownResetEntry(key)){const value=optionEntries[key];if(isBoolean(value)){entries[key]=value;}}return entries;},{});return mergeDeepRight(DEFAULT_RESET_OPTIONS,{entries:validEntries});}return {
|
|
1960
|
+
if(isBoolean(options)){const{entries}=DEFAULT_RESET_OPTIONS,rest=_objectWithoutProperties(DEFAULT_RESET_OPTIONS,_excluded$1);return _objectSpread2(_objectSpread2({},rest),{},{entries:_objectSpread2(_objectSpread2({},entries),{},{anonymousId:options})});}// Override any defaults with the user provided options
|
|
1961
|
+
if(isObjectLiteralAndNotNull(options)&&isObjectLiteralAndNotNull(options.entries)){const optionEntries=options.entries;const validEntries=Object.keys(optionEntries).reduce((entries,key)=>{if(isKnownResetEntry(key)){const value=optionEntries[key];if(isBoolean(value)){entries[key]=value;}}return entries;},{});return mergeDeepRight(DEFAULT_RESET_OPTIONS,{entries:validEntries});}return _objectSpread2({},DEFAULT_RESET_OPTIONS);};
|
|
1882
1962
|
|
|
1883
1963
|
/**
|
|
1884
1964
|
* To get the page properties for context object
|
|
1885
1965
|
* @param pageProps Page properties
|
|
1886
1966
|
* @returns page properties object for context
|
|
1887
1967
|
*/const getContextPageProperties=pageProps=>{// Need to get updated page details on each event as an event to notify on SPA URL changes does not seem to exist
|
|
1888
|
-
const curPageProps=getDefaultPageProperties();const ctxPageProps={};Object.keys(curPageProps).forEach(key=>{ctxPageProps[key]=pageProps
|
|
1968
|
+
const curPageProps=getDefaultPageProperties();const ctxPageProps={};Object.keys(curPageProps).forEach(key=>{ctxPageProps[key]=(pageProps===null||pageProps===void 0?void 0:pageProps[key])||curPageProps[key];});ctxPageProps.initial_referrer=(pageProps===null||pageProps===void 0?void 0:pageProps.initial_referrer)||state.session.initialReferrer.value;ctxPageProps.initial_referring_domain=(pageProps===null||pageProps===void 0?void 0:pageProps.initial_referring_domain)||state.session.initialReferringDomain.value;return ctxPageProps;};/**
|
|
1889
1969
|
* Add any missing default page properties using values from options and defaults
|
|
1890
1970
|
* @param properties Input page properties
|
|
1891
1971
|
* @param options API options
|
|
1892
|
-
*/const getUpdatedPageProperties=(properties,options)=>{const optionsPageProps=options
|
|
1972
|
+
*/const getUpdatedPageProperties=(properties,options)=>{const optionsPageProps=(options===null||options===void 0?void 0:options.page)||{};const pageProps=properties;// Need to get updated page details on each event as an event to notify on SPA URL changes does not seem to exist
|
|
1893
1973
|
const curPageProps=getDefaultPageProperties();Object.keys(curPageProps).forEach(key=>{if(isUndefined(pageProps[key])){pageProps[key]=optionsPageProps[key]||curPageProps[key];}});if(isUndefined(pageProps.initial_referrer)){pageProps.initial_referrer=optionsPageProps.initial_referrer||state.session.initialReferrer.value;}if(isUndefined(pageProps.initial_referring_domain)){pageProps.initial_referring_domain=optionsPageProps.initial_referring_domain||state.session.initialReferringDomain.value;}return pageProps;};/**
|
|
1894
1974
|
* Utility to check for reserved keys in the input object
|
|
1895
1975
|
* @param obj Generic object
|
|
@@ -1922,20 +2002,18 @@ rudderEvent.context=getMergedContext(rudderEvent.context,options,logger);}};/**
|
|
|
1922
2002
|
* Returns the final integrations config for the event based on the global config and event's config
|
|
1923
2003
|
* @param integrationsConfig Event's integrations config
|
|
1924
2004
|
* @returns Final integrations config
|
|
1925
|
-
*/const getEventIntegrationsConfig=integrationsConfig=>{let finalIntgConfig;if(state.loadOptions.value.useGlobalIntegrationsConfigInEvents){
|
|
1926
|
-
finalIntgConfig=state.consents.postConsent.value.integrations
|
|
2005
|
+
*/const getEventIntegrationsConfig=integrationsConfig=>{let finalIntgConfig;if(state.loadOptions.value.useGlobalIntegrationsConfigInEvents){var _state$consents$postC;// Prefer the integrations object from the consent API response over the load API integrations object
|
|
2006
|
+
finalIntgConfig=(_state$consents$postC=state.consents.postConsent.value.integrations)!==null&&_state$consents$postC!==void 0?_state$consents$postC:state.nativeDestinations.loadOnlyIntegrations.value;}else if(integrationsConfig){finalIntgConfig=integrationsConfig;}else {finalIntgConfig=DEFAULT_INTEGRATIONS_CONFIG;}return clone(finalIntgConfig);};/**
|
|
1927
2007
|
* Enrich the base event object with data from state and the API options
|
|
1928
2008
|
* @param rudderEvent RudderEvent object
|
|
1929
2009
|
* @param options API options
|
|
1930
2010
|
* @param pageProps Page properties
|
|
1931
2011
|
* @param logger logger
|
|
1932
2012
|
* @returns Enriched RudderEvent object
|
|
1933
|
-
*/const getEnrichedEvent=(rudderEvent,options,pageProps,logger,customContext={})=>{const commonEventData={channel:CHANNEL,context:{traits:clone(state.session.userTraits.value),sessionId:state.session.sessionInfo.value.id||undefined,sessionStart:state.session.sessionInfo.value.sessionStart||undefined
|
|
1934
|
-
...(state.consents.enabled.value&&{consentManagement:{deniedConsentIds:clone(state.consents.data.value.deniedConsentIds),allowedConsentIds:clone(state.consents.data.value.allowedConsentIds),provider:state.consents.provider.value,resolutionStrategy:state.consents.resolutionStrategy.value}}),'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,// Add auto tracking information
|
|
1935
|
-
...(state.autoTrack.enabled.value&&{autoTrack:{...(state.autoTrack.pageLifecycle.enabled.value&&{page:{pageViewId:state.autoTrack.pageLifecycle.pageViewId.value}})}})},originalTimestamp:getCurrentTimeFormatted(),messageId:generateUUID(),userId:rudderEvent.userId||state.session.userId.value};if(!isStorageTypeValidForStoringData(state.storage.entries.value.anonymousId?.type)){// Generate new anonymous id for each request
|
|
2013
|
+
*/const getEnrichedEvent=(rudderEvent,options,pageProps,logger,customContext={})=>{var _state$storage$entrie;const commonEventData={channel:CHANNEL,context:_objectSpread2(_objectSpread2({traits:clone(state.session.userTraits.value),sessionId:state.session.sessionInfo.value.id||undefined,sessionStart:state.session.sessionInfo.value.sessionStart||undefined},state.consents.enabled.value&&{consentManagement:{deniedConsentIds:clone(state.consents.data.value.deniedConsentIds),allowedConsentIds:clone(state.consents.data.value.allowedConsentIds),provider:state.consents.provider.value,resolutionStrategy:state.consents.resolutionStrategy.value}}),{},{'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},state.autoTrack.enabled.value&&{autoTrack:_objectSpread2({},state.autoTrack.pageLifecycle.enabled.value&&{page:{pageViewId:state.autoTrack.pageLifecycle.pageViewId.value}})}),originalTimestamp:getCurrentTimeFormatted(),messageId:generateUUID(),userId:rudderEvent.userId||state.session.userId.value};if(!isStorageTypeValidForStoringData((_state$storage$entrie=state.storage.entries.value.anonymousId)===null||_state$storage$entrie===void 0?void 0:_state$storage$entrie.type)){// Generate new anonymous id for each request
|
|
1936
2014
|
commonEventData.anonymousId=generateAnonymousId();}else {// Type casting to string as the user session manager will take care of initializing the value
|
|
1937
2015
|
commonEventData.anonymousId=state.session.anonymousId.value;}// set truly anonymous tracking flag
|
|
1938
|
-
if(state.storage.trulyAnonymousTracking.value){commonEventData.context.trulyAnonymousTracking=true;}if(rudderEvent.type==='identify'){commonEventData.context.traits=state.storage.entries.value.userTraits
|
|
2016
|
+
if(state.storage.trulyAnonymousTracking.value){commonEventData.context.trulyAnonymousTracking=true;}if(rudderEvent.type==='identify'){var _state$storage$entrie2;commonEventData.context.traits=((_state$storage$entrie2=state.storage.entries.value.userTraits)===null||_state$storage$entrie2===void 0?void 0:_state$storage$entrie2.type)!==NO_STORAGE?clone(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){var _state$storage$entrie3;commonEventData.traits=((_state$storage$entrie3=state.storage.entries.value.groupTraits)===null||_state$storage$entrie3===void 0?void 0:_state$storage$entrie3.type)!==NO_STORAGE?clone(state.session.groupTraits.value):rudderEvent.traits;}}const sdkBuiltEvent=mergeDeepRight(rudderEvent,commonEventData);const processedEvent=mergeDeepRight(sdkBuiltEvent,{context:customContext});// Set the default values for the event properties
|
|
1939
2017
|
// matching with v1.1 payload
|
|
1940
2018
|
if(processedEvent.event===undefined){processedEvent.event=null;}if(processedEvent.properties===undefined){processedEvent.properties=null;}processOptions(processedEvent,options,logger);checkForReservedElements(processedEvent,logger);// Update the integrations config for the event
|
|
1941
2019
|
processedEvent.integrations=getEventIntegrationsConfig(processedEvent.integrations);return processedEvent;};
|
|
@@ -1946,7 +2024,7 @@ class RudderEventFactory{constructor(logger){this.logger=logger;}/**
|
|
|
1946
2024
|
* @param name Page name
|
|
1947
2025
|
* @param properties Page properties
|
|
1948
2026
|
* @param options API options
|
|
1949
|
-
*/generatePageEvent(category,name,properties,options,customContext={}){let props=properties
|
|
2027
|
+
*/generatePageEvent(category,name,properties,options,customContext={}){let props=properties!==null&&properties!==void 0?properties:{};props=getUpdatedPageProperties(props,options);const pageEvent={properties:props,name,category,type:'page'};return getEnrichedEvent(pageEvent,options,props,this.logger,customContext);}/**
|
|
1950
2028
|
* Generate a 'track' event based on the user-input fields
|
|
1951
2029
|
* @param event The event name
|
|
1952
2030
|
* @param properties Event properties
|
|
@@ -1962,7 +2040,7 @@ class RudderEventFactory{constructor(logger){this.logger=logger;}/**
|
|
|
1962
2040
|
* @param from Old user ID
|
|
1963
2041
|
* @param options API options
|
|
1964
2042
|
*/generateAliasEvent(to,from,options,customContext={}){const aliasEvent={previousId:from,type:'alias'};const enrichedEvent=getEnrichedEvent(aliasEvent,options,undefined,this.logger,customContext);// override the User ID from the API inputs
|
|
1965
|
-
enrichedEvent.userId=to
|
|
2043
|
+
enrichedEvent.userId=to!==null&&to!==void 0?to:enrichedEvent.userId;return enrichedEvent;}/**
|
|
1966
2044
|
* Generate a 'group' event based on the user-input fields
|
|
1967
2045
|
* @param groupId New group ID
|
|
1968
2046
|
* @param traits new group traits
|
|
@@ -2003,16 +2081,16 @@ class UserSessionManager{/**
|
|
|
2003
2081
|
* Initialize User session with values from storage
|
|
2004
2082
|
*/init(){this.syncStorageDataToState();// Register the effect to sync with storage
|
|
2005
2083
|
this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
|
|
2006
|
-
this.setUserId(this.getUserId());this.setUserTraits(this.getUserTraits());this.setGroupId(this.getGroupId());this.setGroupTraits(this.getGroupTraits());const{externalAnonymousIdCookieName,anonymousIdOptions}=state.loadOptions.value;let externalAnonymousId;if(isDefinedAndNotNull(externalAnonymousIdCookieName)&&typeof externalAnonymousIdCookieName==='string'){externalAnonymousId=this.getExternalAnonymousIdByCookieName(externalAnonymousIdCookieName);}this.setAnonymousId(externalAnonymousId
|
|
2084
|
+
this.setUserId(this.getUserId());this.setUserTraits(this.getUserTraits());this.setGroupId(this.getGroupId());this.setGroupTraits(this.getGroupTraits());const{externalAnonymousIdCookieName,anonymousIdOptions}=state.loadOptions.value;let externalAnonymousId;if(isDefinedAndNotNull(externalAnonymousIdCookieName)&&typeof externalAnonymousIdCookieName==='string'){externalAnonymousId=this.getExternalAnonymousIdByCookieName(externalAnonymousIdCookieName);}this.setAnonymousId(externalAnonymousId!==null&&externalAnonymousId!==void 0?externalAnonymousId:this.getAnonymousId(anonymousIdOptions));this.setAuthToken(this.getAuthToken());this.setInitialReferrerInfo();this.configureSessionTracking();}configureSessionTracking(){let sessionInfo;if(this.isPersistenceEnabledForStorageEntry('sessionInfo')){var _this$getSessionInfo,_configuredSessionTra;const configuredSessionTrackingInfo=this.getConfiguredSessionTrackingInfo();const initialSessionInfo=(_this$getSessionInfo=this.getSessionInfo())!==null&&_this$getSessionInfo!==void 0?_this$getSessionInfo:DEFAULT_USER_SESSION_VALUES.sessionInfo;// Merge the session info from the storage and the configuration
|
|
2007
2085
|
sessionInfo={// If manualTrack is set to true in the storage, then do not enable auto tracking even if configured.
|
|
2008
2086
|
// Once manual tracking ends (endSession is called), auto tracking will be enabled in the next SDK run.
|
|
2009
2087
|
autoTrack:configuredSessionTrackingInfo.autoTrack&&initialSessionInfo.manualTrack!==true,timeout:configuredSessionTrackingInfo.timeout,manualTrack:initialSessionInfo.manualTrack,expiresAt:initialSessionInfo.expiresAt,id:initialSessionInfo.id,sessionStart:initialSessionInfo.sessionStart};// If both autoTrack and manualTrack are disabled, reset the session info to default values
|
|
2010
|
-
if(!sessionInfo.autoTrack&&sessionInfo.manualTrack!==true){sessionInfo=DEFAULT_USER_SESSION_VALUES.sessionInfo;}else if(configuredSessionTrackingInfo.cutOff
|
|
2011
|
-
if(state.session.sessionInfo.value.autoTrack){this.startOrRenewAutoTracking(state.session.sessionInfo.value);}}setInitialReferrerInfo(){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));}}isPersistenceEnabledForStorageEntry(entryName){return isStorageTypeValidForStoringData(state.storage.entries.value[entryName]
|
|
2088
|
+
if(!sessionInfo.autoTrack&&sessionInfo.manualTrack!==true){sessionInfo=DEFAULT_USER_SESSION_VALUES.sessionInfo;}else if(((_configuredSessionTra=configuredSessionTrackingInfo.cutOff)===null||_configuredSessionTra===void 0?void 0:_configuredSessionTra.enabled)===true){var _initialSessionInfo$c;sessionInfo.cutOff={enabled:true,duration:configuredSessionTrackingInfo.cutOff.duration,expiresAt:(_initialSessionInfo$c=initialSessionInfo.cutOff)===null||_initialSessionInfo$c===void 0?void 0:_initialSessionInfo$c.expiresAt};}}else {sessionInfo=DEFAULT_USER_SESSION_VALUES.sessionInfo;}state.session.sessionInfo.value=sessionInfo;// If auto session tracking is enabled start the session tracking
|
|
2089
|
+
if(state.session.sessionInfo.value.autoTrack){this.startOrRenewAutoTracking(state.session.sessionInfo.value);}}setInitialReferrerInfo(){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));}}isPersistenceEnabledForStorageEntry(entryName){var _state$storage$entrie;return isStorageTypeValidForStoringData((_state$storage$entrie=state.storage.entries.value[entryName])===null||_state$storage$entrie===void 0?void 0:_state$storage$entrie.type);}migrateDataFromPreviousStorage(){const entries=state.storage.entries.value;const storageTypesForMigration=[COOKIE_STORAGE,LOCAL_STORAGE,SESSION_STORAGE];Object.keys(entries).forEach(entry=>{var _entries$key,_this$storeManager;const key=entry;const currentStorage=(_entries$key=entries[key])===null||_entries$key===void 0?void 0:_entries$key.type;const curStore=(_this$storeManager=this.storeManager)===null||_this$storeManager===void 0?void 0:_this$storeManager.getStore(storageClientDataStoreNameMap[currentStorage]);if(curStore){storageTypesForMigration.forEach(storage=>{var _this$storeManager2;const store=(_this$storeManager2=this.storeManager)===null||_this$storeManager2===void 0?void 0:_this$storeManager2.getStore(storageClientDataStoreNameMap[storage]);if(store&&storage!==currentStorage){const value=store.get(COOKIE_KEYS[key]);if(isDefinedNotNullAndNotEmptyString(value)){curStore.set(COOKIE_KEYS[key],value);}store.remove(COOKIE_KEYS[key]);}});}});}migrateStorageIfNeeded(stores,keys){if(!state.storage.migrate.value){return;}let storesToMigrate=stores!==null&&stores!==void 0?stores:[];if(storesToMigrate.length===0){const persistentStoreNames=[CLIENT_DATA_STORE_COOKIE,CLIENT_DATA_STORE_LS,CLIENT_DATA_STORE_SESSION];persistentStoreNames.forEach(storeName=>{var _this$storeManager3;const store=(_this$storeManager3=this.storeManager)===null||_this$storeManager3===void 0?void 0:_this$storeManager3.getStore(storeName);if(store){storesToMigrate.push(store);}});}let keysToMigrate=keys!==null&&keys!==void 0?keys:Object.keys(COOKIE_KEYS);keysToMigrate.forEach(storageKey=>{const storageEntry=COOKIE_KEYS[storageKey];storesToMigrate.forEach(store=>{var _this$pluginsManager;const migratedVal=(_this$pluginsManager=this.pluginsManager)===null||_this$pluginsManager===void 0?void 0:_this$pluginsManager.invokeSingle('storage.migrate',storageEntry,store.engine,this.errorHandler,this.logger);// Skip setting the value if it is null or undefined
|
|
2012
2090
|
// as those values indicate there is no need for migration or
|
|
2013
2091
|
// migration failed
|
|
2014
|
-
if(!isNullOrUndefined(migratedVal)){store.set(storageEntry,migratedVal);}});});}getConfiguredSessionTrackingInfo(){let autoTrack=state.loadOptions.value.sessions.autoTrack!==false;// Do not validate any further if autoTrack is disabled
|
|
2015
|
-
if(!autoTrack){return {autoTrack};}let timeout;const configuredSessionTimeout=state.loadOptions.value.sessions
|
|
2092
|
+
if(!isNullOrUndefined(migratedVal)){store.set(storageEntry,migratedVal);}});});}getConfiguredSessionTrackingInfo(){var _state$loadOptions$va;let autoTrack=state.loadOptions.value.sessions.autoTrack!==false;// Do not validate any further if autoTrack is disabled
|
|
2093
|
+
if(!autoTrack){return {autoTrack};}let timeout;const configuredSessionTimeout=(_state$loadOptions$va=state.loadOptions.value.sessions)===null||_state$loadOptions$va===void 0?void 0:_state$loadOptions$va.timeout;if(!isPositiveInteger(configuredSessionTimeout)){this.logger.warn(TIMEOUT_NOT_NUMBER_WARNING(USER_SESSION_MANAGER,configuredSessionTimeout,DEFAULT_SESSION_TIMEOUT_MS));timeout=DEFAULT_SESSION_TIMEOUT_MS;}else {timeout=configuredSessionTimeout;}if(timeout===0){this.logger.warn(TIMEOUT_ZERO_WARNING(USER_SESSION_MANAGER));autoTrack=false;}// In case user provides a timeout value greater than 0 but less than 10 seconds SDK will show a warning
|
|
2016
2094
|
// and will proceed with it
|
|
2017
2095
|
if(timeout>0&&timeout<MIN_SESSION_TIMEOUT_MS){this.logger.warn(TIMEOUT_NOT_RECOMMENDED_WARNING(USER_SESSION_MANAGER,timeout,MIN_SESSION_TIMEOUT_MS));}const cutOff=this.getCutOffInfo(timeout);return {timeout,autoTrack,cutOff};}getCutOffInfo(sessionTimeout){const cutOff=state.loadOptions.value.sessions.cutOff;let cutOffDuration;let cutOffEnabled=false;if(cutOff.enabled===true){cutOffDuration=cutOff.duration;cutOffEnabled=true;if(!isPositiveInteger(cutOffDuration)){this.logger.warn(CUT_OFF_DURATION_NOT_NUMBER_WARNING(USER_SESSION_MANAGER,cutOffDuration,DEFAULT_SESSION_CUT_OFF_DURATION_MS));// Use the default value for cut off duration
|
|
2018
2096
|
cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessionTimeout){this.logger.warn(CUT_OFF_DURATION_LESS_THAN_TIMEOUT_WARNING(USER_SESSION_MANAGER,cutOffDuration,sessionTimeout));cutOffEnabled=false;}}return {enabled:cutOffEnabled,duration:cutOffDuration};}/**
|
|
@@ -2023,23 +2101,23 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
|
|
|
2023
2101
|
* @param cookiesData
|
|
2024
2102
|
* @param store
|
|
2025
2103
|
* @returns
|
|
2026
|
-
*/getEncryptedCookieData(cookiesData,store){const encryptedCookieData=[];cookiesData.forEach(cData=>{const encryptedValue=store
|
|
2104
|
+
*/getEncryptedCookieData(cookiesData,store){const encryptedCookieData=[];cookiesData.forEach(cData=>{const encryptedValue=store===null||store===void 0?void 0:store.encrypt(stringifyWithoutCircular(cData.value,false,[],this.logger));if(isDefinedAndNotNull(encryptedValue)){encryptedCookieData.push({name:cData.name,value:encryptedValue});}});return encryptedCookieData;}/**
|
|
2027
2105
|
* A function that makes request to data service to set the cookie
|
|
2028
2106
|
* @param encryptedCookieData
|
|
2029
2107
|
* @param callback
|
|
2030
|
-
*/makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient
|
|
2108
|
+
*/makeRequestToSetCookie(encryptedCookieData,callback){var _this$httpClient,_state$source$value,_state$storage$cookie,_state$storage$cookie2,_state$storage$cookie3,_state$storage$cookie4,_state$storage$cookie5,_state$storage$cookie6;(_this$httpClient=this.httpClient)===null||_this$httpClient===void 0||_this$httpClient.getAsyncData({url:state.serverCookies.dataServiceUrl.value,options:{method:'POST',data:stringifyWithoutCircular({reqType:'setCookies',workspaceId:(_state$source$value=state.source.value)===null||_state$source$value===void 0?void 0:_state$source$value.workspaceId,data:{options:{maxAge:(_state$storage$cookie=state.storage.cookie.value)===null||_state$storage$cookie===void 0?void 0:_state$storage$cookie.maxage,path:(_state$storage$cookie2=state.storage.cookie.value)===null||_state$storage$cookie2===void 0?void 0:_state$storage$cookie2.path,domain:(_state$storage$cookie3=state.storage.cookie.value)===null||_state$storage$cookie3===void 0?void 0:_state$storage$cookie3.domain,sameSite:(_state$storage$cookie4=state.storage.cookie.value)===null||_state$storage$cookie4===void 0?void 0:_state$storage$cookie4.samesite,secure:(_state$storage$cookie5=state.storage.cookie.value)===null||_state$storage$cookie5===void 0?void 0:_state$storage$cookie5.secure,expires:(_state$storage$cookie6=state.storage.cookie.value)===null||_state$storage$cookie6===void 0?void 0:_state$storage$cookie6.expires},cookies:encryptedCookieData}}),sendRawData:true,withCredentials:true},isRawResponse:true,callback});}/**
|
|
2031
2109
|
* A function to make an external request to set the cookie from server side
|
|
2032
2110
|
* @param sessionToCookiesMap map of session key to cookie name
|
|
2033
2111
|
* @param cb callback function to be called when the cookie is set
|
|
2034
2112
|
* @param store store to be used to get the cookie value
|
|
2035
2113
|
*/setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
|
|
2036
2114
|
const sessionKeys=Object.keys(sessionToCookiesMap);const getCurrentCookieValuesFromState=()=>{return sessionKeys.map(sessionKey=>{return {name:sessionToCookiesMap[sessionKey].name,value:state.session[sessionKey].value};});};// Preserve the current cookie values
|
|
2037
|
-
const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store
|
|
2115
|
+
const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store===null||store===void 0?void 0:store.get(sessionToCookiesMap[sessionKey].name);});const clearInProgressFlags=()=>{sessionKeys.forEach(sessionKey=>{this.serverSideCookiesRequestInProgress[sessionKey]=false;});};const setCookiesClientSide=()=>{getCurrentCookieValuesFromState().forEach(each=>{if(cb){cb(each.name,each.value);}});};try{const expectedCookieValues={};sessionKeys.forEach(sessionKey=>{expectedCookieValues[sessionToCookiesMap[sessionKey].name]=state.session[sessionKey].value;});// encrypt cookies values
|
|
2038
2116
|
const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
|
|
2039
|
-
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{
|
|
2040
|
-
clearInProgressFlags();if(details
|
|
2117
|
+
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{var _details$xhr;// Mark the cookie req status as done
|
|
2118
|
+
clearInProgressFlags();if((details===null||details===void 0||(_details$xhr=details.xhr)===null||_details$xhr===void 0?void 0:_details$xhr.status)===200){// Only the cookies that were actually sent can be reported as unapplied, so
|
|
2041
2119
|
// both halves of the diagnostic are drawn from the same set
|
|
2042
|
-
const sentCookieNames=new Set(encryptedCookieData.map(each=>each.name));const unappliedCookies=[];getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store
|
|
2120
|
+
const sentCookieNames=new Set(encryptedCookieData.map(each=>each.name));const unappliedCookies=[];getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store===null||store===void 0?void 0:store.get(cData.name);// Check if the expected cookie values are set.
|
|
2043
2121
|
if(stringifyWithoutCircular(expectedCookieValues[cData.name],false,[])!==stringifyWithoutCircular(currentCookieVal,false,[])){// It's fine if the values don't match as other active SDK sessions might have updated the cookie values
|
|
2044
2122
|
// or other cookie requests might have updated the cookie value.
|
|
2045
2123
|
// Left exactly as the request found it, so the server did not apply this
|
|
@@ -2057,7 +2135,7 @@ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED
|
|
|
2057
2135
|
// attributes usually leave none of them set.
|
|
2058
2136
|
// Counted from what was actually sent, not from the queued keys: encryption can
|
|
2059
2137
|
// drop a key, and reporting it as sent would overstate the batch.
|
|
2060
|
-
if(encryptedCookieData.length>1&&unappliedCookies.length>0&&!state.serverCookies.isCollapsedBatchErrorLogged.value){state.serverCookies.isCollapsedBatchErrorLogged.value=true;this.logger.error(COLLAPSED_COOKIE_BATCH_ERROR(unappliedCookies,encryptedCookieData.length));}}else {this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details
|
|
2138
|
+
if(encryptedCookieData.length>1&&unappliedCookies.length>0&&!state.serverCookies.isCollapsedBatchErrorLogged.value){state.serverCookies.isCollapsedBatchErrorLogged.value=true;this.logger.error(COLLAPSED_COOKIE_BATCH_ERROR(unappliedCookies,encryptedCookieData.length));}}else {var _details$xhr2;this.logger.error(DATA_SERVER_REQUEST_FAIL_ERROR(details===null||details===void 0||(_details$xhr2=details.xhr)===null||_details$xhr2===void 0?void 0:_details$xhr2.status));setCookiesClientSide();}});}else {setCookiesClientSide();// Mark the cookie req status as done
|
|
2061
2139
|
clearInProgressFlags();}}catch(e){this.onError(e,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR,FAILED_SETTING_COOKIE_FROM_SERVER_GLOBAL_ERROR);setCookiesClientSide();// Mark the cookie req status as done
|
|
2062
2140
|
clearInProgressFlags();}}/**
|
|
2063
2141
|
* A function to send every queued server-side cookie as a single request
|
|
@@ -2065,10 +2143,10 @@ clearInProgressFlags();}}/**
|
|
|
2065
2143
|
this.serverSideCookiesDebounceTimer=0;const sessionToCookiesMap=Object.entries(this.serverSideCookiesPending).reduce((acc,[sessionKey,cookieName])=>{acc[sessionKey]={name:cookieName};return acc;},{});// Drain before sending, so anything that changes while the request is in flight is
|
|
2066
2144
|
// queued for the next batch rather than being sent twice
|
|
2067
2145
|
this.serverSideCookiesPending={};if(Object.keys(sessionToCookiesMap).length===0){return;}// Every batched key is backed by cookie storage by construction, so they share a store
|
|
2068
|
-
const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[COOKIE_STORAGE]);this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore
|
|
2146
|
+
const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[COOKIE_STORAGE]);this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore===null||curStore===void 0||curStore.set(cookieName,cookieValue);},curStore);}/**
|
|
2069
2147
|
* A function to sync values in storage
|
|
2070
2148
|
* @param sessionKey
|
|
2071
|
-
*/syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]
|
|
2149
|
+
*/syncValueToStorage(sessionKey){var _entries$sessionKey;const entries=state.storage.entries.value;const storageType=(_entries$sessionKey=entries[sessionKey])===null||_entries$sessionKey===void 0?void 0:_entries$sessionKey.type;if(isStorageTypeValidForStoringData(storageType)){var _entries$sessionKey2;const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[storageType]);const cookieName=(_entries$sessionKey2=entries[sessionKey])===null||_entries$sessionKey2===void 0?void 0:_entries$sessionKey2.key;const cookieValue=state.session[sessionKey].value;if(cookieValue&&(isString(cookieValue)||isNonEmptyObject(cookieValue))){// if useServerSideCookies load option is set to true
|
|
2072
2150
|
// set the cookie from server side
|
|
2073
2151
|
if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
|
|
2074
2152
|
this.serverSideCookiesRequestInProgress[sessionKey]=true;// Queue this key and restart the shared debounce, so everything that changes in
|
|
@@ -2077,7 +2155,7 @@ this.serverSideCookiesPending[sessionKey]=cookieName;// Restarting the shared ti
|
|
|
2077
2155
|
// keep postponing the flush for every other key, where per-key timers only ever
|
|
2078
2156
|
// delayed their own. That needs changes arriving closer together than the
|
|
2079
2157
|
// debounce, continuously, so it is accepted rather than capped with a max wait.
|
|
2080
|
-
if(this.serverSideCookiesDebounceTimer){globalThis.clearTimeout(this.serverSideCookiesDebounceTimer);}this.serverSideCookiesDebounceTimer=globalThis.setTimeout(()=>{this.flushServerSideCookies();},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore
|
|
2158
|
+
if(this.serverSideCookiesDebounceTimer){globalThis.clearTimeout(this.serverSideCookiesDebounceTimer);}this.serverSideCookiesDebounceTimer=globalThis.setTimeout(()=>{this.flushServerSideCookies();},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore===null||curStore===void 0||curStore.set(cookieName,cookieValue);}}else {curStore===null||curStore===void 0||curStore.remove(cookieName);}}}/**
|
|
2081
2159
|
* Function to update storage whenever state value changes
|
|
2082
2160
|
*/registerEffects(){// This will work as long as the user session entry key names are same as the state keys
|
|
2083
2161
|
USER_SESSION_KEYS.forEach(sessionKey=>{j(()=>{// Read before syncing so the effect subscribes to the signal, and record after
|
|
@@ -2089,16 +2167,16 @@ const value=state.session[sessionKey].value;this.syncValueToStorage(sessionKey);
|
|
|
2089
2167
|
* 2. rudderAmpLinkerParam: value generated from linker query parm (rudderstack)
|
|
2090
2168
|
* using parseLinker util.
|
|
2091
2169
|
* 3. generateUUID: A new unique id is generated and assigned.
|
|
2092
|
-
*/setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;if(!isString(anonymousId)||!finalAnonymousId){finalAnonymousId=undefined;}if(this.isPersistenceEnabledForStorageEntry('anonymousId')){if(!finalAnonymousId&&rudderAmpLinkerParam){const linkerPluginsResult=this.pluginsManager
|
|
2170
|
+
*/setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;if(!isString(anonymousId)||!finalAnonymousId){finalAnonymousId=undefined;}if(this.isPersistenceEnabledForStorageEntry('anonymousId')){if(!finalAnonymousId&&rudderAmpLinkerParam){var _this$pluginsManager2;const linkerPluginsResult=(_this$pluginsManager2=this.pluginsManager)===null||_this$pluginsManager2===void 0?void 0:_this$pluginsManager2.invokeSingle('userSession.anonymousIdGoogleLinker',rudderAmpLinkerParam);finalAnonymousId=linkerPluginsResult;}finalAnonymousId=finalAnonymousId||generateAnonymousId();}else {finalAnonymousId=DEFAULT_USER_SESSION_VALUES.anonymousId;}state.session.anonymousId.value=finalAnonymousId;}/**
|
|
2093
2171
|
* Fetches anonymousId
|
|
2094
2172
|
* @param options option to fetch it from external source
|
|
2095
2173
|
* @returns anonymousId
|
|
2096
|
-
*/getAnonymousId(options){const storage=state.storage.entries.value.anonymousId
|
|
2097
|
-
if(!persistedAnonymousId||persistedAnonymousId===DEFAULT_USER_SESSION_VALUES.anonymousId){persistedAnonymousId=this.getEntryValue('anonymousId');}if(!persistedAnonymousId&&options){
|
|
2098
|
-
const autoCapturedAnonymousId=this.pluginsManager
|
|
2174
|
+
*/getAnonymousId(options){var _state$storage$entrie2;const storage=(_state$storage$entrie2=state.storage.entries.value.anonymousId)===null||_state$storage$entrie2===void 0?void 0:_state$storage$entrie2.type;if(isStorageTypeValidForStoringData(storage)){let persistedAnonymousId=state.session.anonymousId.value;// If the anonymous ID is the default value, fetch it from storage
|
|
2175
|
+
if(!persistedAnonymousId||persistedAnonymousId===DEFAULT_USER_SESSION_VALUES.anonymousId){persistedAnonymousId=this.getEntryValue('anonymousId');}if(!persistedAnonymousId&&options){var _this$pluginsManager3;// fetch anonymousId from external source
|
|
2176
|
+
const autoCapturedAnonymousId=(_this$pluginsManager3=this.pluginsManager)===null||_this$pluginsManager3===void 0?void 0:_this$pluginsManager3.invokeSingle('storage.getAnonymousId',getStorageEngine,options);persistedAnonymousId=autoCapturedAnonymousId;}state.session.anonymousId.value=persistedAnonymousId||generateAnonymousId();}return state.session.anonymousId.value;}getEntryValue(sessionKey){var _entries$sessionKey3;const entries=state.storage.entries.value;const storageType=(_entries$sessionKey3=entries[sessionKey])===null||_entries$sessionKey3===void 0?void 0:_entries$sessionKey3.type;if(isStorageTypeValidForStoringData(storageType)){var _this$storeManager4,_entries$sessionKey4,_store$get;const store=(_this$storeManager4=this.storeManager)===null||_this$storeManager4===void 0?void 0:_this$storeManager4.getStore(storageClientDataStoreNameMap[storageType]);// Migrate the storage data before fetching the value
|
|
2099
2177
|
// This is needed for entries that are fetched from the storage
|
|
2100
2178
|
// during the current session (for example, session info)
|
|
2101
|
-
this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]
|
|
2179
|
+
this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=(_entries$sessionKey4=entries[sessionKey])===null||_entries$sessionKey4===void 0?void 0:_entries$sessionKey4.key;return (_store$get=store===null||store===void 0?void 0:store.get(storageKey))!==null&&_store$get!==void 0?_store$get:null;}return null;}getExternalAnonymousIdByCookieName(key){const storageEngine=getStorageEngine(COOKIE_STORAGE);if(storageEngine!==null&&storageEngine!==void 0&&storageEngine.isEnabled){var _storageEngine$getIte;return (_storageEngine$getIte=storageEngine.getItem(key))!==null&&_storageEngine$getIte!==void 0?_storageEngine$getIte:null;}return null;}/**
|
|
2102
2180
|
* Fetches the value for a session key. Preferably from storage, so that changes made by
|
|
2103
2181
|
* other tabs are picked up. Falls back to the state whenever storage is known to be
|
|
2104
2182
|
* behind it.
|
|
@@ -2147,20 +2225,20 @@ return this.getEntryValue(sessionKey);}/**
|
|
|
2147
2225
|
*/getAuthToken(){return this.getUserSessionValue('authToken');}/**
|
|
2148
2226
|
* If session is active it returns the sessionId
|
|
2149
2227
|
* @returns
|
|
2150
|
-
*/getSessionId(){const sessionInfo=this.getSessionInfo()
|
|
2228
|
+
*/getSessionId(){var _this$getSessionInfo2;const sessionInfo=(_this$getSessionInfo2=this.getSessionInfo())!==null&&_this$getSessionInfo2!==void 0?_this$getSessionInfo2:DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack&&!hasSessionExpired(sessionInfo)||sessionInfo.manualTrack){var _sessionInfo$id;return (_sessionInfo$id=sessionInfo.id)!==null&&_sessionInfo$id!==void 0?_sessionInfo$id:null;}return null;}/**
|
|
2151
2229
|
* A function to keep the session information up to date in the state
|
|
2152
2230
|
* before using it for building event payloads.
|
|
2153
|
-
*/refreshSession(){let sessionInfo=this.getSessionInfo()
|
|
2231
|
+
*/refreshSession(){var _this$getSessionInfo3;let sessionInfo=(_this$getSessionInfo3=this.getSessionInfo())!==null&&_this$getSessionInfo3!==void 0?_this$getSessionInfo3:DEFAULT_USER_SESSION_VALUES.sessionInfo;if(sessionInfo.autoTrack||sessionInfo.manualTrack){if(sessionInfo.autoTrack){this.startOrRenewAutoTracking(sessionInfo);sessionInfo=state.session.sessionInfo.value;}// Note that if sessionStart is false, then it's an active session.
|
|
2154
2232
|
// So, we needn't update the session info.
|
|
2155
2233
|
//
|
|
2156
2234
|
// For other scenarios,
|
|
2157
2235
|
// 1. If sessionStart is undefined, then it's a new session.
|
|
2158
2236
|
// Mark it as sessionStart.
|
|
2159
2237
|
// 2. If sessionStart is true, then need to flip it for the future events.
|
|
2160
|
-
if(sessionInfo.sessionStart===undefined){sessionInfo={
|
|
2238
|
+
if(sessionInfo.sessionStart===undefined){sessionInfo=_objectSpread2(_objectSpread2({},sessionInfo),{},{sessionStart:true});}else if(sessionInfo.sessionStart){sessionInfo=_objectSpread2(_objectSpread2({},sessionInfo),{},{sessionStart:false});}}// Always write to state (in-turn to storage) to keep the session info up to date.
|
|
2161
2239
|
state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
|
|
2162
2240
|
// when processing preload buffered requests
|
|
2163
|
-
this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={
|
|
2241
|
+
this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo=_objectSpread2(_objectSpread2({},DEFAULT_USER_SESSION_VALUES.sessionInfo),{},{timeout});if(cutOff){sessionInfo.cutOff={enabled:cutOff.enabled,duration:cutOff.duration};}session.sessionInfo.value=sessionInfo;this.startOrRenewAutoTracking(session.sessionInfo.value);}else if(manualTrack){this.startManualTrackingInternal();}}/**
|
|
2164
2242
|
* Reset state values
|
|
2165
2243
|
* @param options options for reset
|
|
2166
2244
|
* @returns
|
|
@@ -2170,13 +2248,13 @@ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session
|
|
|
2170
2248
|
*/setUserId(userId){state.session.userId.value=this.isPersistenceEnabledForStorageEntry('userId')&&userId?userId:DEFAULT_USER_SESSION_VALUES.userId;}/**
|
|
2171
2249
|
* Set user traits
|
|
2172
2250
|
* @param traits
|
|
2173
|
-
*/setUserTraits(traits){state.session.userTraits.value=this.isPersistenceEnabledForStorageEntry('userTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight(state.session.userTraits.value
|
|
2251
|
+
*/setUserTraits(traits){var _state$session$userTr;state.session.userTraits.value=this.isPersistenceEnabledForStorageEntry('userTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight((_state$session$userTr=state.session.userTraits.value)!==null&&_state$session$userTr!==void 0?_state$session$userTr:DEFAULT_USER_SESSION_VALUES.userTraits,traits):DEFAULT_USER_SESSION_VALUES.userTraits;}/**
|
|
2174
2252
|
* Set group Id
|
|
2175
2253
|
* @param groupId
|
|
2176
2254
|
*/setGroupId(groupId){state.session.groupId.value=this.isPersistenceEnabledForStorageEntry('groupId')&&groupId?groupId:DEFAULT_USER_SESSION_VALUES.groupId;}/**
|
|
2177
2255
|
* Set group traits
|
|
2178
2256
|
* @param traits
|
|
2179
|
-
*/setGroupTraits(traits){state.session.groupTraits.value=this.isPersistenceEnabledForStorageEntry('groupTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight(state.session.groupTraits.value
|
|
2257
|
+
*/setGroupTraits(traits){var _state$session$groupT;state.session.groupTraits.value=this.isPersistenceEnabledForStorageEntry('groupTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight((_state$session$groupT=state.session.groupTraits.value)!==null&&_state$session$groupT!==void 0?_state$session$groupT:DEFAULT_USER_SESSION_VALUES.groupTraits,traits):DEFAULT_USER_SESSION_VALUES.groupTraits;}/**
|
|
2180
2258
|
* Set initial referrer
|
|
2181
2259
|
* @param referrer
|
|
2182
2260
|
*/setInitialReferrer(referrer){state.session.initialReferrer.value=this.isPersistenceEnabledForStorageEntry('initialReferrer')&&referrer?referrer:DEFAULT_USER_SESSION_VALUES.initialReferrer;}/**
|
|
@@ -2207,7 +2285,7 @@ state.session.sessionInfo.value=finalSessionInfo;}/**
|
|
|
2207
2285
|
const liteExcludedPlugins=['GoogleLinker'];const defaultOptionalPluginsList=allOptionalPlugins.filter(plugin=>!liteExcludedPlugins.includes(plugin));
|
|
2208
2286
|
|
|
2209
2287
|
const normalizeLoadOptions=(loadOptionsFromState,loadOptions)=>{// TODO: Maybe add warnings for invalid values
|
|
2210
|
-
const normalizedLoadOpts=clone(loadOptions);if(!isString(normalizedLoadOpts.setCookieDomain)){normalizedLoadOpts.setCookieDomain=undefined;}const cookieSameSiteValues=['Strict','Lax','None'];if(!cookieSameSiteValues.includes(normalizedLoadOpts.sameSiteCookie)){normalizedLoadOpts.sameSiteCookie=undefined;}normalizedLoadOpts.secureCookie=getNormalizedBooleanValue(normalizedLoadOpts.secureCookie,loadOptionsFromState.secureCookie);normalizedLoadOpts.sameDomainCookiesOnly=getNormalizedBooleanValue(normalizedLoadOpts.sameDomainCookiesOnly,loadOptionsFromState.sameDomainCookiesOnly);const uaChTrackLevels=['none','default','full'];if(!uaChTrackLevels.includes(normalizedLoadOpts.uaChTrackLevel)){normalizedLoadOpts.uaChTrackLevel=undefined;}normalizedLoadOpts.integrations=getNormalizedObjectValue(normalizedLoadOpts.integrations);if(!Array.isArray(normalizedLoadOpts.plugins)){normalizedLoadOpts.plugins=defaultOptionalPluginsList;}normalizedLoadOpts.useGlobalIntegrationsConfigInEvents=getNormalizedBooleanValue(normalizedLoadOpts.useGlobalIntegrationsConfigInEvents,loadOptionsFromState.useGlobalIntegrationsConfigInEvents);normalizedLoadOpts.bufferDataPlaneEventsUntilReady=getNormalizedBooleanValue(normalizedLoadOpts.bufferDataPlaneEventsUntilReady,loadOptionsFromState.bufferDataPlaneEventsUntilReady);normalizedLoadOpts.sendAdblockPage=getNormalizedBooleanValue(normalizedLoadOpts.sendAdblockPage,loadOptionsFromState.sendAdblockPage);normalizedLoadOpts.useServerSideCookies=getNormalizedBooleanValue(normalizedLoadOpts.useServerSideCookies,loadOptionsFromState.useServerSideCookies);if(!isString(normalizedLoadOpts.dataServiceEndpoint)){normalizedLoadOpts.dataServiceEndpoint=undefined;}normalizedLoadOpts.sendAdblockPageOptions=getNormalizedObjectValue(normalizedLoadOpts.sendAdblockPageOptions);normalizedLoadOpts.loadIntegration=getNormalizedBooleanValue(normalizedLoadOpts.loadIntegration,loadOptionsFromState.loadIntegration);if(!isNonEmptyObject(normalizedLoadOpts.storage)){normalizedLoadOpts.storage=undefined;}else {normalizedLoadOpts.storage.migrate=getNormalizedBooleanValue(normalizedLoadOpts.storage.migrate,loadOptionsFromState.storage
|
|
2288
|
+
const normalizedLoadOpts=clone(loadOptions);if(!isString(normalizedLoadOpts.setCookieDomain)){normalizedLoadOpts.setCookieDomain=undefined;}const cookieSameSiteValues=['Strict','Lax','None'];if(!cookieSameSiteValues.includes(normalizedLoadOpts.sameSiteCookie)){normalizedLoadOpts.sameSiteCookie=undefined;}normalizedLoadOpts.secureCookie=getNormalizedBooleanValue(normalizedLoadOpts.secureCookie,loadOptionsFromState.secureCookie);normalizedLoadOpts.sameDomainCookiesOnly=getNormalizedBooleanValue(normalizedLoadOpts.sameDomainCookiesOnly,loadOptionsFromState.sameDomainCookiesOnly);const uaChTrackLevels=['none','default','full'];if(!uaChTrackLevels.includes(normalizedLoadOpts.uaChTrackLevel)){normalizedLoadOpts.uaChTrackLevel=undefined;}normalizedLoadOpts.integrations=getNormalizedObjectValue(normalizedLoadOpts.integrations);if(!Array.isArray(normalizedLoadOpts.plugins)){normalizedLoadOpts.plugins=defaultOptionalPluginsList;}normalizedLoadOpts.useGlobalIntegrationsConfigInEvents=getNormalizedBooleanValue(normalizedLoadOpts.useGlobalIntegrationsConfigInEvents,loadOptionsFromState.useGlobalIntegrationsConfigInEvents);normalizedLoadOpts.bufferDataPlaneEventsUntilReady=getNormalizedBooleanValue(normalizedLoadOpts.bufferDataPlaneEventsUntilReady,loadOptionsFromState.bufferDataPlaneEventsUntilReady);normalizedLoadOpts.sendAdblockPage=getNormalizedBooleanValue(normalizedLoadOpts.sendAdblockPage,loadOptionsFromState.sendAdblockPage);normalizedLoadOpts.useServerSideCookies=getNormalizedBooleanValue(normalizedLoadOpts.useServerSideCookies,loadOptionsFromState.useServerSideCookies);if(!isString(normalizedLoadOpts.dataServiceEndpoint)){normalizedLoadOpts.dataServiceEndpoint=undefined;}normalizedLoadOpts.sendAdblockPageOptions=getNormalizedObjectValue(normalizedLoadOpts.sendAdblockPageOptions);normalizedLoadOpts.loadIntegration=getNormalizedBooleanValue(normalizedLoadOpts.loadIntegration,loadOptionsFromState.loadIntegration);if(!isNonEmptyObject(normalizedLoadOpts.storage)){normalizedLoadOpts.storage=undefined;}else {var _loadOptionsFromState;normalizedLoadOpts.storage.migrate=getNormalizedBooleanValue(normalizedLoadOpts.storage.migrate,(_loadOptionsFromState=loadOptionsFromState.storage)===null||_loadOptionsFromState===void 0?void 0:_loadOptionsFromState.migrate);normalizedLoadOpts.storage.cookie=getNormalizedObjectValue(normalizedLoadOpts.storage.cookie);normalizedLoadOpts.storage.encryption=getNormalizedObjectValue(normalizedLoadOpts.storage.encryption);normalizedLoadOpts.storage=removeUndefinedAndNullValues(normalizedLoadOpts.storage);}normalizedLoadOpts.destinationsQueueOptions=getNormalizedObjectValue(normalizedLoadOpts.destinationsQueueOptions);normalizedLoadOpts.queueOptions=getNormalizedObjectValue(normalizedLoadOpts.queueOptions);normalizedLoadOpts.lockIntegrationsVersion=getNormalizedBooleanValue(normalizedLoadOpts.lockIntegrationsVersion,loadOptionsFromState.lockIntegrationsVersion);normalizedLoadOpts.lockPluginsVersion=getNormalizedBooleanValue(normalizedLoadOpts.lockPluginsVersion,loadOptionsFromState.lockPluginsVersion);if(!isNumber(normalizedLoadOpts.dataPlaneEventsBufferTimeout)){normalizedLoadOpts.dataPlaneEventsBufferTimeout=undefined;}normalizedLoadOpts.beaconQueueOptions=getNormalizedObjectValue(normalizedLoadOpts.beaconQueueOptions);normalizedLoadOpts.preConsent=getNormalizedObjectValue(normalizedLoadOpts.preConsent);normalizedLoadOpts.sourceConfigurationOverride=getNormalizedObjectValue(normalizedLoadOpts.sourceConfigurationOverride);const mergedLoadOptions=mergeDeepRight(loadOptionsFromState,removeUndefinedAndNullValues(normalizedLoadOpts));return mergedLoadOptions;};
|
|
2211
2289
|
|
|
2212
2290
|
const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATIONS_QUEUE_EXT_POINT_PREFIX='destinationsEventsQueue';const DMT_EXT_POINT_PREFIX='transformEvent';
|
|
2213
2291
|
|
|
@@ -2223,7 +2301,7 @@ const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATION
|
|
|
2223
2301
|
* @returns Mutated event with final integrations config
|
|
2224
2302
|
*/const getFinalEvent=(event,state)=>{const finalEvent=clone(event);// Merge the destination specific integrations config with the event's integrations config
|
|
2225
2303
|
// In general, the preference is given to the event's integrations config
|
|
2226
|
-
const destinationsIntgConfig=state.nativeDestinations.integrationsConfig.value;const overriddenIntgOpts=getOverriddenIntegrationOptions(event.integrations,destinationsIntgConfig);finalEvent.integrations=mergeDeepRight(destinationsIntgConfig,overriddenIntgOpts);return finalEvent;};const shouldBufferEventsForPreConsent=state=>state.consents.preConsent.value.enabled&&state.consents.preConsent.value.events
|
|
2304
|
+
const destinationsIntgConfig=state.nativeDestinations.integrationsConfig.value;const overriddenIntgOpts=getOverriddenIntegrationOptions(event.integrations,destinationsIntgConfig);finalEvent.integrations=mergeDeepRight(destinationsIntgConfig,overriddenIntgOpts);return finalEvent;};const shouldBufferEventsForPreConsent=state=>{var _state$consents$preCo;return state.consents.preConsent.value.enabled&&((_state$consents$preCo=state.consents.preConsent.value.events)===null||_state$consents$preCo===void 0?void 0:_state$consents$preCo.delivery)==='buffer';};
|
|
2227
2305
|
|
|
2228
2306
|
const safelyInvokeCallback=(callback,args,apiName,logger)=>{if(!isDefined(callback)){return;}if(isFunction(callback)){try{callback(...args);}catch(error){logger.error(CALLBACK_INVOKE_ERROR(apiName),error);}}else {logger.error(INVALID_CALLBACK_FN_ERROR(apiName));}};
|
|
2229
2307
|
|
|
@@ -2238,12 +2316,12 @@ const safelyInvokeCallback=(callback,args,apiName,logger)=>{if(!isDefined(callba
|
|
|
2238
2316
|
*/constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.pluginsManager=pluginsManager;this.errorHandler=errorHandler;this.httpClient=httpClient;this.logger=logger;this.storeManager=storeManager;}/**
|
|
2239
2317
|
* Initializes the event repository
|
|
2240
2318
|
*/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
|
|
2241
|
-
j(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){this.destinationsEventsQueue
|
|
2319
|
+
j(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){var _this$destinationsEve,_this$dmtEventsQueue;(_this$destinationsEve=this.destinationsEventsQueue)===null||_this$destinationsEve===void 0||_this$destinationsEve.start();(_this$dmtEventsQueue=this.dmtEventsQueue)===null||_this$dmtEventsQueue===void 0||_this$dmtEventsQueue.start();}});const bufferEventsBeforeConsent=shouldBufferEventsForPreConsent(state);// Start the queue processing only when the destinations are ready or hybrid mode destinations exist
|
|
2242
2320
|
// However, events will be enqueued for now.
|
|
2243
2321
|
// At the time of processing the events, the integrations config data from destinations
|
|
2244
2322
|
// is merged into the event object
|
|
2245
|
-
let timeoutId;j(()=>{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)&&!bufferEventsBeforeConsent&&this.dataplaneEventsQueue
|
|
2246
|
-
if(state.loadOptions.value.bufferDataPlaneEventsUntilReady===true){timeoutId=globalThis.setTimeout(()=>{if(this.dataplaneEventsQueue
|
|
2323
|
+
let timeoutId;j(()=>{var _this$dataplaneEvents;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)&&!bufferEventsBeforeConsent&&((_this$dataplaneEvents=this.dataplaneEventsQueue)===null||_this$dataplaneEvents===void 0?void 0:_this$dataplaneEvents.scheduleTimeoutActive)!==true){var _this$dataplaneEvents2;globalThis.clearTimeout(timeoutId);(_this$dataplaneEvents2=this.dataplaneEventsQueue)===null||_this$dataplaneEvents2===void 0||_this$dataplaneEvents2.start();}});// Force start the data plane events queue processing after a timeout
|
|
2324
|
+
if(state.loadOptions.value.bufferDataPlaneEventsUntilReady===true){timeoutId=globalThis.setTimeout(()=>{var _this$dataplaneEvents3;if(((_this$dataplaneEvents3=this.dataplaneEventsQueue)===null||_this$dataplaneEvents3===void 0?void 0:_this$dataplaneEvents3.scheduleTimeoutActive)!==true){var _this$dataplaneEvents4;(_this$dataplaneEvents4=this.dataplaneEventsQueue)===null||_this$dataplaneEvents4===void 0||_this$dataplaneEvents4.start();}},state.loadOptions.value.dataPlaneEventsBufferTimeout);}}resume(){var _this$dataplaneEvents5;if(((_this$dataplaneEvents5=this.dataplaneEventsQueue)===null||_this$dataplaneEvents5===void 0?void 0:_this$dataplaneEvents5.scheduleTimeoutActive)!==true){var _this$dataplaneEvents7;if(state.consents.postConsent.value.discardPreConsentEvents){var _this$dataplaneEvents6,_this$destinationsEve2;(_this$dataplaneEvents6=this.dataplaneEventsQueue)===null||_this$dataplaneEvents6===void 0||_this$dataplaneEvents6.clear();(_this$destinationsEve2=this.destinationsEventsQueue)===null||_this$destinationsEve2===void 0||_this$destinationsEve2.clear();}(_this$dataplaneEvents7=this.dataplaneEventsQueue)===null||_this$dataplaneEvents7===void 0||_this$dataplaneEvents7.start();}}/**
|
|
2247
2325
|
* Enqueues the event for processing
|
|
2248
2326
|
* @param event RudderEvent object
|
|
2249
2327
|
* @param callback API callback function
|
|
@@ -2252,22 +2330,22 @@ const apiName=`${event.type.charAt(0).toUpperCase()}${event.type.slice(1)}${API_
|
|
|
2252
2330
|
|
|
2253
2331
|
const dispatchSDKEvent=event=>{const customEvent=new CustomEvent(event,{detail:{analyticsInstance:globalThis.rudderanalytics},bubbles:true,cancelable:true,composed:true});globalThis.document.dispatchEvent(customEvent);};const isWriteKeyValid=writeKey=>isString(writeKey)&&writeKey.trim().length>0;const isDataPlaneUrlValid=dataPlaneUrl=>isValidURL(dataPlaneUrl);
|
|
2254
2332
|
|
|
2255
|
-
|
|
2333
|
+
const _excluded=["context"];/*
|
|
2256
2334
|
* Analytics class with lifecycle based on state ad user triggered events
|
|
2257
2335
|
*/class Analytics{/**
|
|
2258
2336
|
* Initialize services and components or use default ones if singletons
|
|
2259
|
-
*/constructor(){this.preloadBuffer=new BufferQueue();this.initialized=false;this.errorHandler=defaultErrorHandler;this.logger=defaultLogger;this.customContextStore=new CustomContextStore(state.customContext,this.logger);this.externalSrcLoader=new ExternalSrcLoader(this.logger);this.httpClient=defaultHttpClient;this.httpClient.init(this.errorHandler);this.capabilitiesManager=new CapabilitiesManager(this.httpClient,this.errorHandler,this.logger);}/**
|
|
2337
|
+
*/constructor(){this.preloadBuffer=new BufferQueue();this.initialized=false;this.isDrainingBuffer=false;this.errorHandler=defaultErrorHandler;this.logger=defaultLogger;this.customContextStore=new CustomContextStore(state.customContext,this.logger);this.externalSrcLoader=new ExternalSrcLoader(this.logger);this.httpClient=defaultHttpClient;this.httpClient.init(this.errorHandler);this.capabilitiesManager=new CapabilitiesManager(this.httpClient,this.errorHandler,this.logger);}/**
|
|
2260
2338
|
* Start application lifecycle if not already started
|
|
2261
|
-
*/load(writeKey,dataPlaneUrl,loadOptions={}){if(state.lifecycle.status.value){return;}if(!isWriteKeyValid(writeKey)){this.logger.error(WRITE_KEY_VALIDATION_ERROR(ANALYTICS_CORE,writeKey));return;}if(!isDataPlaneUrlValid(dataPlaneUrl)){this.logger.error(DATA_PLANE_URL_VALIDATION_ERROR(ANALYTICS_CORE,dataPlaneUrl));return;}const{context:customContext
|
|
2339
|
+
*/load(writeKey,dataPlaneUrl,loadOptions={}){var _state$loadOptions$va;if(state.lifecycle.status.value){return;}if(!isWriteKeyValid(writeKey)){this.logger.error(WRITE_KEY_VALIDATION_ERROR(ANALYTICS_CORE,writeKey));return;}if(!isDataPlaneUrlValid(dataPlaneUrl)){this.logger.error(DATA_PLANE_URL_VALIDATION_ERROR(ANALYTICS_CORE,dataPlaneUrl));return;}const{context:customContext}=loadOptions,loadOptionsWithoutContext=_objectWithoutProperties(loadOptions,_excluded);const sanitizedLoadOptions=getSanitizedValue(loadOptionsWithoutContext);if(customContext!==undefined){this.customContextStore.set(customContext);}// Set initial state values
|
|
2262
2340
|
n(()=>{state.lifecycle.writeKey.value=clone(writeKey);state.lifecycle.dataPlaneUrl.value=clone(dataPlaneUrl);state.loadOptions.value=normalizeLoadOptions(state.loadOptions.value,sanitizedLoadOptions);state.lifecycle.status.value='mounted';});// set log level as early as possible
|
|
2263
|
-
this.logger.setMinLogLevel(state.loadOptions.value.logLevel
|
|
2341
|
+
this.logger.setMinLogLevel((_state$loadOptions$va=state.loadOptions.value.logLevel)!==null&&_state$loadOptions$va!==void 0?_state$loadOptions$va:POST_LOAD_LOG_LEVEL);// Expose state to global objects
|
|
2264
2342
|
setExposedGlobal('state',state,writeKey);// Configure initial config of any services or components here
|
|
2265
2343
|
// State application lifecycle
|
|
2266
|
-
this.startLifecycle();}setCustomContext(context){if(
|
|
2344
|
+
this.startLifecycle();}setCustomContext(context,isBufferedInvocation=false){if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['setCustomContext',context]];return;}this.customContextStore.set(context);}getCustomContext(){return this.customContextStore.get();}clearCustomContext(isBufferedInvocation=false){if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['clearCustomContext']];return;}this.customContextStore.clear();}// Start lifecycle methods
|
|
2267
2345
|
/**
|
|
2268
2346
|
* Orchestrate the lifecycle of the application phases/status
|
|
2269
|
-
*/startLifecycle(){j(()=>{try{switch(state.lifecycle.status.value){case 'mounted':this.onMounted();break;case 'browserCapabilitiesReady':this.onBrowserCapabilitiesReady();break;case 'configured':this.onConfigured();break;case 'pluginsLoading':break;case 'pluginsReady':this.onPluginsReady();break;case 'initialized':this.onInitialized();break;case 'loaded':this.onLoaded();break;case 'destinationsLoading':break;case 'destinationsReady':this.onDestinationsReady();break;case 'ready':this.onReady();break;case 'readyExecuted':default:break;}}catch(err){const issue='Failed to load the SDK';this.errorHandler.onError({error:err,context:ANALYTICS_CORE,customMessage:issue,groupingHash:issue});}});}onBrowserCapabilitiesReady(){// initialize the preloaded events enqueuing
|
|
2270
|
-
retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig();}onLoaded(){
|
|
2347
|
+
*/startLifecycle(){j(()=>{try{switch(state.lifecycle.status.value){case 'mounted':this.onMounted();break;case 'browserCapabilitiesReady':this.onBrowserCapabilitiesReady();break;case 'configured':this.onConfigured();break;case 'pluginsLoading':break;case 'pluginsReady':this.onPluginsReady();break;case 'initialized':this.onInitialized();break;case 'loaded':this.onLoaded();break;case 'destinationsLoading':break;case 'destinationsReady':this.onDestinationsReady();break;case 'ready':this.onReady();break;case 'readyExecuted':default:break;}}catch(err){const issue='Failed to load the SDK';void this.errorHandler.onError({error:err,context:ANALYTICS_CORE,customMessage:issue,groupingHash:issue});}});}onBrowserCapabilitiesReady(){// initialize the preloaded events enqueuing
|
|
2348
|
+
retrievePreloadBufferEvents(this);this.prepareInternalServices();this.loadConfig();}onLoaded(){// Short-circuit the life cycle and move to the ready state if pre-consent behavior is enabled
|
|
2271
2349
|
if(state.consents.preConsent.value.enabled===true){state.lifecycle.status.value='ready';}else {this.loadDestinations();}}/**
|
|
2272
2350
|
* Load browser polyfill if required
|
|
2273
2351
|
*/onMounted(){this.capabilitiesManager.init();}/**
|
|
@@ -2276,21 +2354,24 @@ if(state.consents.preConsent.value.enabled===true){state.lifecycle.status.value=
|
|
|
2276
2354
|
* Process the buffer preloaded events by passing their arguments to the respective facade methods
|
|
2277
2355
|
*/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.pluginsManager,this.storeManager,this.httpClient,this.errorHandler,this.logger);this.eventRepository=new EventRepository(this.pluginsManager,this.storeManager,this.httpClient,this.errorHandler,this.logger);this.eventManager=new EventManager(this.eventRepository,this.userSessionManager,this.errorHandler,this.logger);}/**
|
|
2278
2356
|
* Load configuration
|
|
2279
|
-
*/loadConfig(){if(state.lifecycle.writeKey.value){this.httpClient.setAuthHeader(state.lifecycle.writeKey.value);}this.configManager
|
|
2357
|
+
*/loadConfig(){var _this$configManager;if(state.lifecycle.writeKey.value){this.httpClient.setAuthHeader(state.lifecycle.writeKey.value);}(_this$configManager=this.configManager)===null||_this$configManager===void 0||_this$configManager.init();}/**
|
|
2280
2358
|
* Initialize the storage and event queue
|
|
2281
|
-
*/onPluginsReady(){
|
|
2282
|
-
this.storeManager
|
|
2283
|
-
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager
|
|
2284
|
-
this.eventManager
|
|
2359
|
+
*/onPluginsReady(){var _this$storeManager,_this$userSessionMana,_this$eventManager;// Initialize storage
|
|
2360
|
+
(_this$storeManager=this.storeManager)===null||_this$storeManager===void 0||_this$storeManager.init();(_this$userSessionMana=this.userSessionManager)===null||_this$userSessionMana===void 0||_this$userSessionMana.init();// Initialize the appropriate consent manager plugin
|
|
2361
|
+
if(state.consents.enabled.value&&!state.consents.initialized.value){var _this$pluginsManager;(_this$pluginsManager=this.pluginsManager)===null||_this$pluginsManager===void 0||_this$pluginsManager.invokeSingle(`consentManager.init`,state,this.logger);if(state.consents.preConsent.value.enabled===false){var _this$pluginsManager2;(_this$pluginsManager2=this.pluginsManager)===null||_this$pluginsManager2===void 0||_this$pluginsManager2.invokeSingle(`consentManager.updateConsentsInfo`,state,this.storeManager,this.logger);}}// Initialize event manager
|
|
2362
|
+
(_this$eventManager=this.eventManager)===null||_this$eventManager===void 0||_this$eventManager.init();// Mark the SDK as initialized
|
|
2285
2363
|
state.lifecycle.status.value='initialized';}/**
|
|
2286
2364
|
* Load plugins
|
|
2287
|
-
*/onConfigured(){this.pluginsManager
|
|
2365
|
+
*/onConfigured(){var _this$pluginsManager3;(_this$pluginsManager3=this.pluginsManager)===null||_this$pluginsManager3===void 0||_this$pluginsManager3.init();// TODO: are we going to enable custom plugins to be passed as load options?
|
|
2288
2366
|
// registerCustomPlugins(state.loadOptions.value.customPlugins);
|
|
2289
2367
|
}/**
|
|
2290
2368
|
* Trigger onLoaded callback if any is provided in config & emit initialised event
|
|
2291
|
-
*/onInitialized(){//
|
|
2292
|
-
|
|
2293
|
-
|
|
2369
|
+
*/onInitialized(){// Preloaded calls were made before the ones buffered while initializing, so queue them first.
|
|
2370
|
+
// Exception: they stay behind any consent call made while initializing, so that consent still
|
|
2371
|
+
// applies to them as it always has (see SDK-5623)
|
|
2372
|
+
const callsDuringInitialization=state.eventBuffer.toBeProcessedArray.value;state.eventBuffer.toBeProcessedArray.value=[];this.processDataInPreloadBuffer();const lastConsentIndex=callsDuringInitialization.map(([type])=>type).lastIndexOf('consent');state.eventBuffer.toBeProcessedArray.value=[...callsDuringInitialization.slice(0,lastConsentIndex+1),...state.eventBuffer.toBeProcessedArray.value,...callsDuringInitialization.slice(lastConsentIndex+1)];// Set lifecycle state
|
|
2373
|
+
n(()=>{state.lifecycle.loaded.value=true;state.lifecycle.status.value='loaded';});this.initialized=true;// Calls made while draining (e.g., from event callbacks) are queued behind the buffered ones
|
|
2374
|
+
this.isDrainingBuffer=true;try{this.processBufferedEvents();}finally{this.isDrainingBuffer=false;}// Execute onLoaded callback if provided in load options
|
|
2294
2375
|
const onLoadedCallbackFn=state.loadOptions.value.onLoaded;// TODO: we need to avoid passing the window object to the callback function
|
|
2295
2376
|
// as this will prevent us from supporting multiple SDK instances in the same page
|
|
2296
2377
|
safelyInvokeCallback(onLoadedCallbackFn,[globalThis.rudderanalytics],LOAD_API,this.logger);// Emit an event to use as substitute to the onLoaded callback
|
|
@@ -2303,12 +2384,16 @@ dispatchSDKEvent('RSA_Ready');}/**
|
|
|
2303
2384
|
*/processBufferedEvents(){// This logic has been intentionally implemented without a simple
|
|
2304
2385
|
// for-loop as the individual events that are processed may
|
|
2305
2386
|
// add more events to the buffer (this is needed for the consent API)
|
|
2306
|
-
let bufferedEvents=state.eventBuffer.toBeProcessedArray.value;while(bufferedEvents.length>0){const bufferedEvent=bufferedEvents.shift();state.eventBuffer.toBeProcessedArray.value=bufferedEvents;if(bufferedEvent){
|
|
2387
|
+
let bufferedEvents=state.eventBuffer.toBeProcessedArray.value;while(bufferedEvents.length>0){const bufferedEvent=bufferedEvents.shift();state.eventBuffer.toBeProcessedArray.value=bufferedEvents;if(bufferedEvent){// A failing call must not stop the rest of the buffer or the load notifications
|
|
2388
|
+
try{this.processBufferedEvent(bufferedEvent);}catch(err){const issue='Failed to process a buffered API call';void this.errorHandler.onError({error:err,context:ANALYTICS_CORE,customMessage:issue,groupingHash:issue});}}bufferedEvents=state.eventBuffer.toBeProcessedArray.value;}}processBufferedEvent(bufferedEvent){switch(bufferedEvent[0]){case 'setCustomContext':this.setCustomContext(bufferedEvent[1],true);break;case 'clearCustomContext':this.clearCustomContext(true);break;case 'ready':this.ready(bufferedEvent[1],true);break;case 'page':this.page(bufferedEvent[1],true,bufferedEvent[2]);break;case 'track':this.track(bufferedEvent[1],true,bufferedEvent[2]);break;case 'identify':this.identify(bufferedEvent[1],true,bufferedEvent[2]);break;case 'alias':this.alias(bufferedEvent[1],true,bufferedEvent[2]);break;case 'group':this.group(bufferedEvent[1],true,bufferedEvent[2]);break;case 'reset':this.reset(bufferedEvent[1],true);break;case 'setAnonymousId':this.setAnonymousId(bufferedEvent[1],bufferedEvent[2],true);break;case 'startSession':this.startSession(bufferedEvent[1],true);break;case 'endSession':this.endSession(true);break;case 'consent':this.consent(bufferedEvent[1],true);break;case 'addCustomIntegration':this.addCustomIntegration(bufferedEvent[1],bufferedEvent[2],true);break;default:{const unsupportedEvent=bufferedEvent;return unsupportedEvent;}}}/**
|
|
2389
|
+
* Whether an API call must be queued instead of executed now: either the SDK is not loaded yet,
|
|
2390
|
+
* or the buffer is being drained and this call was not replayed from it
|
|
2391
|
+
*/shouldBuffer(isBufferedInvocation){return !state.lifecycle.loaded.value||this.isDrainingBuffer&&!isBufferedInvocation;}getInvocationContext(preservedCustomContext){var _ref;if(preservedCustomContext===undefined){return this.customContextStore.get();}const preparedContext=prepareCustomContextUpdate(preservedCustomContext,this.logger);return (_ref=preparedContext)!==null&&_ref!==void 0?_ref:{};}/**
|
|
2307
2392
|
* Load device mode destinations
|
|
2308
|
-
*/loadDestinations(){
|
|
2393
|
+
*/loadDestinations(){var _this$pluginsManager4,_this$pluginsManager5;// If the integrations load is already triggered or completed, skip the rest of the logic
|
|
2309
2394
|
if(state.lifecycle.status.value==='destinationsLoading'||state.nativeDestinations.clientDestinationsReady.value===true){return;}// Set in state the desired activeDestinations to inject in DOM
|
|
2310
|
-
this.pluginsManager
|
|
2311
|
-
state.lifecycle.status.value='destinationsLoading';this.pluginsManager
|
|
2395
|
+
(_this$pluginsManager4=this.pluginsManager)===null||_this$pluginsManager4===void 0||_this$pluginsManager4.invokeSingle('nativeDestinations.setActiveDestinations',state,this.pluginsManager,this.errorHandler,this.logger);const totalDestinationsToLoad=state.nativeDestinations.activeDestinations.value.length;if(totalDestinationsToLoad===0){n(()=>{state.nativeDestinations.clientDestinationsReady.value=true;state.lifecycle.status.value='destinationsReady';});return;}// Start loading native integration scripts and create instances
|
|
2396
|
+
state.lifecycle.status.value='destinationsLoading';(_this$pluginsManager5=this.pluginsManager)===null||_this$pluginsManager5===void 0||_this$pluginsManager5.invokeSingle('nativeDestinations.load',state,this.externalSrcLoader,this.errorHandler,this.logger);// Progress to next lifecycle phase if all native destinations are initialized or failed
|
|
2312
2397
|
j(()=>{const areAllDestinationsReady=state.nativeDestinations.initializedDestinations.value.length+state.nativeDestinations.failedDestinations.value.length===totalDestinationsToLoad;if(areAllDestinationsReady){n(()=>{state.lifecycle.status.value='destinationsReady';state.nativeDestinations.clientDestinationsReady.value=true;});}});}/**
|
|
2313
2398
|
* Move to the ready state
|
|
2314
2399
|
*/// eslint-disable-next-line class-methods-use-this
|
|
@@ -2316,35 +2401,38 @@ onDestinationsReady(){// May be do any destination specific actions here
|
|
|
2316
2401
|
// Mark the ready status if not already done
|
|
2317
2402
|
if(state.lifecycle.status.value!=='ready'){n(()=>{state.lifecycle.status.value='ready';});}}// End lifecycle methods
|
|
2318
2403
|
// Start consumer exposed methods
|
|
2319
|
-
ready(callback,isBufferedInvocation=false){const type='ready';if(
|
|
2404
|
+
ready(callback,isBufferedInvocation=false){const type='ready';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,callback]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);if(!isFunction(callback)){this.logger.error(INVALID_CALLBACK_FN_ERROR(READY_API));return;}/**
|
|
2320
2405
|
* If destinations are loaded or no integration is available for loading
|
|
2321
2406
|
* execute the callback immediately else push the callbacks to a queue that
|
|
2322
2407
|
* will be executed after loading completes
|
|
2323
|
-
*/if(state.lifecycle.status.value==='readyExecuted'){safelyInvokeCallback(callback,[],READY_API,this.logger);}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false,preservedCustomContext){const type='page';if(
|
|
2408
|
+
*/if(state.lifecycle.status.value==='readyExecuted'){safelyInvokeCallback(callback,[],READY_API,this.logger);}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false,preservedCustomContext){var _this$eventManager2;const type='page';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}const invocationContext=this.getInvocationContext(preservedCustomContext);this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;(_this$eventManager2=this.eventManager)===null||_this$eventManager2===void 0||_this$eventManager2.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback},invocationContext);// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
|
|
2324
2409
|
// Send automatic ad blocked page event if ad-blockers are detected on the page
|
|
2325
2410
|
// Check page category to avoid infinite loop
|
|
2326
2411
|
if(state.capabilities.isAdBlocked.value===true&&payload.category!==ADBLOCK_PAGE_CATEGORY){this.page(pageArgumentsToCallOptions(ADBLOCK_PAGE_CATEGORY,ADBLOCK_PAGE_NAME,{// 'title' is intentionally omitted as it does not make sense
|
|
2327
2412
|
// in v3 implementation
|
|
2328
|
-
path:ADBLOCK_PAGE_PATH},state.loadOptions.value.sendAdblockPageOptions),isBufferedInvocation,invocationContext);}}track(payload,isBufferedInvocation=false,preservedCustomContext){const type='track';if(
|
|
2329
|
-
|
|
2330
|
-
if(!isNull(payload.
|
|
2331
|
-
if(!
|
|
2413
|
+
path:ADBLOCK_PAGE_PATH},state.loadOptions.value.sendAdblockPageOptions),isBufferedInvocation,invocationContext);}}track(payload,isBufferedInvocation=false,preservedCustomContext){var _this$eventManager3;const type='track';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}const invocationContext=this.getInvocationContext(preservedCustomContext);this.errorHandler.leaveBreadcrumb(`New ${type} event - ${payload.name}`);state.metrics.triggered.value+=1;(_this$eventManager3=this.eventManager)===null||_this$eventManager3===void 0||_this$eventManager3.addEvent({type,name:payload.name||undefined,properties:payload.properties,options:payload.options,callback:payload.callback},invocationContext);}identify(payload,isBufferedInvocation=false,preservedCustomContext){var _this$userSessionMana3,_this$eventManager4;const type='identify';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}const invocationContext=this.getInvocationContext(preservedCustomContext);this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;const shouldResetSession=Boolean(payload.userId&&state.session.userId.value&&payload.userId!==state.session.userId.value);if(shouldResetSession){// Part of this identify call, so it must not be deferred behind other buffered calls
|
|
2414
|
+
this.reset(undefined,true);}// `null` value indicates that previous user ID needs to be retained
|
|
2415
|
+
if(!isNull(payload.userId)){var _this$userSessionMana2;(_this$userSessionMana2=this.userSessionManager)===null||_this$userSessionMana2===void 0||_this$userSessionMana2.setUserId(payload.userId);}(_this$userSessionMana3=this.userSessionManager)===null||_this$userSessionMana3===void 0||_this$userSessionMana3.setUserTraits(payload.traits);(_this$eventManager4=this.eventManager)===null||_this$eventManager4===void 0||_this$eventManager4.addEvent({type,userId:payload.userId,traits:payload.traits,options:payload.options,callback:payload.callback},invocationContext);}alias(payload,isBufferedInvocation=false,preservedCustomContext){var _payload$from,_this$userSessionMana4,_this$eventManager5;const type='alias';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}const invocationContext=this.getInvocationContext(preservedCustomContext);this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;const previousId=(_payload$from=payload.from)!==null&&_payload$from!==void 0?_payload$from:this.getUserId()||((_this$userSessionMana4=this.userSessionManager)===null||_this$userSessionMana4===void 0?void 0:_this$userSessionMana4.getAnonymousId());(_this$eventManager5=this.eventManager)===null||_this$eventManager5===void 0||_this$eventManager5.addEvent({type,to:payload.to,from:previousId,options:payload.options,callback:payload.callback},invocationContext);}group(payload,isBufferedInvocation=false,preservedCustomContext){var _this$userSessionMana6,_this$eventManager6;const type='group';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}const invocationContext=this.getInvocationContext(preservedCustomContext);this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;// `null` value indicates that previous group ID needs to be retained
|
|
2416
|
+
if(!isNull(payload.groupId)){var _this$userSessionMana5;(_this$userSessionMana5=this.userSessionManager)===null||_this$userSessionMana5===void 0||_this$userSessionMana5.setGroupId(payload.groupId);}(_this$userSessionMana6=this.userSessionManager)===null||_this$userSessionMana6===void 0||_this$userSessionMana6.setGroupTraits(payload.traits);(_this$eventManager6=this.eventManager)===null||_this$eventManager6===void 0||_this$eventManager6.addEvent({type,groupId:payload.groupId,traits:payload.traits,options:payload.options,callback:payload.callback},invocationContext);}reset(options,isBufferedInvocation=false){var _this$userSessionMana7;const type='reset';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,options]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);(_this$userSessionMana7=this.userSessionManager)===null||_this$userSessionMana7===void 0||_this$userSessionMana7.reset(options);}getAnonymousId(options){var _this$userSessionMana8;return (_this$userSessionMana8=this.userSessionManager)===null||_this$userSessionMana8===void 0?void 0:_this$userSessionMana8.getAnonymousId(options);}setAnonymousId(anonymousId,rudderAmpLinkerParam,isBufferedInvocation=false){var _this$userSessionMana9;const type='setAnonymousId';// Buffering is needed as setting the anonymous ID may require invoking the GoogleLinker plugin
|
|
2417
|
+
if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,anonymousId,rudderAmpLinkerParam]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);(_this$userSessionMana9=this.userSessionManager)===null||_this$userSessionMana9===void 0||_this$userSessionMana9.setAnonymousId(anonymousId,rudderAmpLinkerParam);}// eslint-disable-next-line class-methods-use-this
|
|
2332
2418
|
getUserId(){return state.session.userId.value;}// eslint-disable-next-line class-methods-use-this
|
|
2333
2419
|
getUserTraits(){return state.session.userTraits.value;}// eslint-disable-next-line class-methods-use-this
|
|
2334
2420
|
getGroupId(){return state.session.groupId.value;}// eslint-disable-next-line class-methods-use-this
|
|
2335
|
-
getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId,isBufferedInvocation=false){const type='startSession';if(
|
|
2336
|
-
getSessionId(){const sessionId=this.userSessionManager
|
|
2337
|
-
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager
|
|
2338
|
-
this.storeManager
|
|
2339
|
-
this.userSessionManager
|
|
2340
|
-
this.eventManager
|
|
2421
|
+
getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId,isBufferedInvocation=false){var _this$userSessionMana0;const type='startSession';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,sessionId]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);(_this$userSessionMana0=this.userSessionManager)===null||_this$userSessionMana0===void 0||_this$userSessionMana0.start(sessionId);}endSession(isBufferedInvocation=false){var _this$userSessionMana1;const type='endSession';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);(_this$userSessionMana1=this.userSessionManager)===null||_this$userSessionMana1===void 0||_this$userSessionMana1.end();}// eslint-disable-next-line class-methods-use-this
|
|
2422
|
+
getSessionId(){var _this$userSessionMana10;const sessionId=(_this$userSessionMana10=this.userSessionManager)===null||_this$userSessionMana10===void 0?void 0:_this$userSessionMana10.getSessionId();return sessionId!==null&&sessionId!==void 0?sessionId:null;}consent(options,isBufferedInvocation=false){var _this$storeManager2,_this$userSessionMana11,_this$eventManager7;const type='consent';if(this.shouldBuffer(isBufferedInvocation)){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,options]];return;}this.errorHandler.leaveBreadcrumb(`New consent invocation`);n(()=>{state.consents.preConsent.value=_objectSpread2(_objectSpread2({},state.consents.preConsent.value),{},{enabled:false});state.consents.postConsent.value=getValidPostConsentOptions(options,this.logger);const{initialized,consentsData}=getConsentManagementData(state.consents.postConsent.value.consentManagement,this.logger);state.consents.initialized.value=initialized;state.consents.data.value=consentsData;});// Update consents data in state
|
|
2423
|
+
if(state.consents.enabled.value&&!state.consents.initialized.value){var _this$pluginsManager6;(_this$pluginsManager6=this.pluginsManager)===null||_this$pluginsManager6===void 0||_this$pluginsManager6.invokeSingle(`consentManager.updateConsentsInfo`,state,this.storeManager,this.logger);}// Re-init store manager
|
|
2424
|
+
(_this$storeManager2=this.storeManager)===null||_this$storeManager2===void 0||_this$storeManager2.initializeStorageState();// Re-init user session manager
|
|
2425
|
+
(_this$userSessionMana11=this.userSessionManager)===null||_this$userSessionMana11===void 0||_this$userSessionMana11.syncStorageDataToState();// Resume event manager to process the events to destinations
|
|
2426
|
+
(_this$eventManager7=this.eventManager)===null||_this$eventManager7===void 0||_this$eventManager7.resume();// While replaying, defer to the 'loaded' lifecycle handler so that custom integrations
|
|
2427
|
+
// added later in the buffer are registered before destinations are loaded
|
|
2428
|
+
if(!this.isDrainingBuffer){this.loadDestinations();}this.sendTrackingEvents(isBufferedInvocation);}sendTrackingEvents(isBufferedInvocation){// If isBufferedInvocation is true, then the tracking events will be added to the end of the
|
|
2341
2429
|
// events buffer array so that any other preload events (mainly from query string API) will be processed first.
|
|
2342
|
-
if(state.consents.postConsent.value.trackConsent){const trackOptions=trackArgumentsToCallOptions(CONSENT_TRACK_EVENT_NAME);if(isBufferedInvocation){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['track',trackOptions,this.customContextStore.get()]];}else {this.track(trackOptions);}}if(state.consents.postConsent.value.sendPageEvent){const pageOptions=pageArgumentsToCallOptions();if(isBufferedInvocation){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['page',pageOptions,this.customContextStore.get()]];}else {this.page(pageOptions);}}}setAuthToken(token){this.userSessionManager
|
|
2430
|
+
if(state.consents.postConsent.value.trackConsent){const trackOptions=trackArgumentsToCallOptions(CONSENT_TRACK_EVENT_NAME);if(isBufferedInvocation){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['track',trackOptions,this.customContextStore.get()]];}else {this.track(trackOptions);}}if(state.consents.postConsent.value.sendPageEvent){const pageOptions=pageArgumentsToCallOptions();if(isBufferedInvocation){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['page',pageOptions,this.customContextStore.get()]];}else {this.page(pageOptions);}}}setAuthToken(token){var _this$userSessionMana12;(_this$userSessionMana12=this.userSessionManager)===null||_this$userSessionMana12===void 0||_this$userSessionMana12.setAuthToken(token);}/**
|
|
2343
2431
|
* Add a custom integration for a custom destination.
|
|
2344
2432
|
* @param destinationId - The ID of the custom destination from the RudderStack dashboard.
|
|
2345
2433
|
* @param integration - The custom integration object.
|
|
2346
2434
|
* @param isBufferedInvocation - Whether the invocation is buffered.
|
|
2347
|
-
*/addCustomIntegration(destinationId,integration,isBufferedInvocation=false){const type='addCustomIntegration';if(isBufferedInvocation){this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);this.pluginsManager
|
|
2435
|
+
*/addCustomIntegration(destinationId,integration,isBufferedInvocation=false){const type='addCustomIntegration';if(isBufferedInvocation){var _this$pluginsManager7;this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);(_this$pluginsManager7=this.pluginsManager)===null||_this$pluginsManager7===void 0||_this$pluginsManager7.invokeSingle('nativeDestinations.addCustomIntegration',destinationId,integration,state,this.logger);}else {if(state.lifecycle.loaded.value){this.logger.error(CUSTOM_INTEGRATION_CANNOT_BE_ADDED_ERROR(ANALYTICS_CORE,destinationId));return;}state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,destinationId,integration]];}}// End consumer exposed methods
|
|
2348
2436
|
}
|
|
2349
2437
|
|
|
2350
2438
|
/*
|
|
@@ -2352,11 +2440,9 @@ if(state.consents.postConsent.value.trackConsent){const trackOptions=trackArgume
|
|
|
2352
2440
|
* expose overloaded methods
|
|
2353
2441
|
* handle multiple Analytics instances
|
|
2354
2442
|
* consume SDK preload event buffer
|
|
2355
|
-
*/class RudderAnalytics{//
|
|
2356
|
-
//
|
|
2357
|
-
|
|
2358
|
-
analyticsInstances={};defaultAnalyticsKey='';logger=defaultLogger;// Singleton with constructor bind methods
|
|
2359
|
-
constructor(){try{if(RudderAnalytics.globalSingleton){// START-NO-SONAR-SCAN
|
|
2443
|
+
*/class RudderAnalytics{// Singleton with constructor bind methods
|
|
2444
|
+
constructor(){// END-NO-SONAR-SCAN
|
|
2445
|
+
_defineProperty(this,"analyticsInstances",{});_defineProperty(this,"defaultAnalyticsKey",'');_defineProperty(this,"logger",defaultLogger);try{if(RudderAnalytics.globalSingleton){// START-NO-SONAR-SCAN
|
|
2360
2446
|
// eslint-disable-next-line no-constructor-return
|
|
2361
2447
|
return RudderAnalytics.globalSingleton;// END-NO-SONAR-SCAN
|
|
2362
2448
|
}RudderAnalytics.initializeGlobalResources();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.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.setCustomContext=this.setCustomContext.bind(this);this.getCustomContext=this.getCustomContext.bind(this);this.clearCustomContext=this.clearCustomContext.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);this.addCustomIntegration=this.addCustomIntegration.bind(this);this.createSafeAnalyticsInstance();RudderAnalytics.globalSingleton=this;state.autoTrack.pageLifecycle.pageViewId.value=generateUUID();state.autoTrack.pageLifecycle.pageLoadedTimestamp.value=Date.now();// start loading if a load event was buffered or wait for explicit load call
|
|
@@ -2384,15 +2470,15 @@ if(isString(writeKey)&&writeKey){this.defaultAnalyticsKey=writeKey;}}/**
|
|
|
2384
2470
|
* @param dataPlaneUrl Data plane URL
|
|
2385
2471
|
* @param loadOptions Additional options for loading the SDK
|
|
2386
2472
|
* @returns none
|
|
2387
|
-
*/load(writeKey,dataPlaneUrl,loadOptions){try{if(this.analyticsInstances[writeKey]){return;}this.setDefaultInstanceKey(writeKey);// Track page loaded lifecycle event if enabled
|
|
2473
|
+
*/load(writeKey,dataPlaneUrl,loadOptions){try{var _this$getAnalyticsIns;if(this.analyticsInstances[writeKey]){return;}this.setDefaultInstanceKey(writeKey);// Track page loaded lifecycle event if enabled
|
|
2388
2474
|
this.trackPageLifecycleEvents(loadOptions);// Get the preloaded events array from global buffer instead of window.rudderanalytics
|
|
2389
2475
|
// as the constructor must have already pushed the events to the global buffer
|
|
2390
2476
|
const preloadedEventsArray=getExposedGlobal(GLOBAL_PRELOAD_BUFFER);// The array will be mutated in the below method
|
|
2391
|
-
promotePreloadedConsentEventsToTop(preloadedEventsArray);setExposedGlobal(GLOBAL_PRELOAD_BUFFER,clone(preloadedEventsArray));this.getAnalyticsInstance(writeKey)
|
|
2477
|
+
promotePreloadedConsentEventsToTop(preloadedEventsArray);setExposedGlobal(GLOBAL_PRELOAD_BUFFER,clone(preloadedEventsArray));(_this$getAnalyticsIns=this.getAnalyticsInstance(writeKey))===null||_this$getAnalyticsIns===void 0||_this$getAnalyticsIns.load(writeKey,dataPlaneUrl,loadOptions);}catch(error){dispatchErrorEvent(error);}}/**
|
|
2392
2478
|
* A function to track page lifecycle events like page loaded and page unloaded
|
|
2393
2479
|
* @param loadOptions
|
|
2394
2480
|
* @returns
|
|
2395
|
-
*/trackPageLifecycleEvents(loadOptions){const{autoTrack,useBeacon}=loadOptions
|
|
2481
|
+
*/trackPageLifecycleEvents(loadOptions){const{autoTrack,useBeacon}=loadOptions!==null&&loadOptions!==void 0?loadOptions:{};const{enabled:autoTrackEnabled=false,options:autoTrackOptions={},pageLifecycle}=autoTrack!==null&&autoTrack!==void 0?autoTrack:{};const{events=[PageLifecycleEvents.UNLOADED],enabled:pageLifecycleEnabled=autoTrackEnabled,options=autoTrackOptions}=pageLifecycle!==null&&pageLifecycle!==void 0?pageLifecycle:{};state.autoTrack.pageLifecycle.enabled.value=pageLifecycleEnabled;// Set the autoTrack enabled state
|
|
2396
2482
|
// if at least one of the autoTrack options is enabled
|
|
2397
2483
|
// IMPORTANT: make sure this is done at the end as it depends on the above states
|
|
2398
2484
|
state.autoTrack.enabled.value=autoTrackEnabled||pageLifecycleEnabled;if(!pageLifecycleEnabled){return;}this.setupPageUnloadTracking(events,useBeacon,options);}/**
|
|
@@ -2400,7 +2486,7 @@ state.autoTrack.enabled.value=autoTrackEnabled||pageLifecycleEnabled;if(!pageLif
|
|
|
2400
2486
|
* @param events
|
|
2401
2487
|
* @param useBeacon
|
|
2402
2488
|
* @param options
|
|
2403
|
-
*/setupPageUnloadTracking(events,useBeacon,options){if(events.length===0||events.includes(PageLifecycleEvents.UNLOADED)){if(useBeacon===true){onPageLeave(isAccessible=>{if(isAccessible===false&&state.lifecycle.loaded.value){const pageUnloadedTimestamp=Date.now();const timeOnPage=pageUnloadedTimestamp-state.autoTrack.pageLifecycle.pageLoadedTimestamp.value;this.track(PageLifecycleEvents.UNLOADED,{timeOnPage},{
|
|
2489
|
+
*/setupPageUnloadTracking(events,useBeacon,options){if(events.length===0||events.includes(PageLifecycleEvents.UNLOADED)){if(useBeacon===true){onPageLeave(isAccessible=>{if(isAccessible===false&&state.lifecycle.loaded.value){const pageUnloadedTimestamp=Date.now();const timeOnPage=pageUnloadedTimestamp-state.autoTrack.pageLifecycle.pageLoadedTimestamp.value;this.track(PageLifecycleEvents.UNLOADED,{timeOnPage},_objectSpread2(_objectSpread2({},options),{},{originalTimestamp:getFormattedTimestamp(new Date(pageUnloadedTimestamp))}));}},true);}else {// log warning if beacon is disabled
|
|
2404
2490
|
this.logger.warn(PAGE_UNLOAD_ON_BEACON_DISABLED_WARNING(RSA));}}}/**
|
|
2405
2491
|
* Trigger load event in buffer queue if exists and stores the
|
|
2406
2492
|
* remaining preloaded events array in global object
|
|
@@ -2414,22 +2500,22 @@ loadEvent.shift();// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
2414
2500
|
// @ts-ignore
|
|
2415
2501
|
this.load.apply(null,loadEvent);}}/**
|
|
2416
2502
|
* Get ready callback arguments and forward to ready call
|
|
2417
|
-
*/ready(callback){try{this.getAnalyticsInstance()
|
|
2503
|
+
*/ready(callback){try{var _this$getAnalyticsIns2;(_this$getAnalyticsIns2=this.getAnalyticsInstance())===null||_this$getAnalyticsIns2===void 0||_this$getAnalyticsIns2.ready(getSanitizedValue(callback));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2418
2504
|
* Process page arguments and forward to page call
|
|
2419
2505
|
*/// These overloads should be same as AnalyticsPageMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
2420
|
-
page(category,name,properties,options,callback){try{this.getAnalyticsInstance()
|
|
2506
|
+
page(category,name,properties,options,callback){try{var _this$getAnalyticsIns3;(_this$getAnalyticsIns3=this.getAnalyticsInstance())===null||_this$getAnalyticsIns3===void 0||_this$getAnalyticsIns3.page(pageArgumentsToCallOptions(getSanitizedValue(category),getSanitizedValue(name),getSanitizedValue(properties),getSanitizedValue(options),getSanitizedValue(callback)));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2421
2507
|
* Process track arguments and forward to page call
|
|
2422
2508
|
*/// These overloads should be same as AnalyticsTrackMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
2423
|
-
track(event,properties,options,callback){try{this.getAnalyticsInstance()
|
|
2509
|
+
track(event,properties,options,callback){try{var _this$getAnalyticsIns4;(_this$getAnalyticsIns4=this.getAnalyticsInstance())===null||_this$getAnalyticsIns4===void 0||_this$getAnalyticsIns4.track(trackArgumentsToCallOptions(getSanitizedValue(event),getSanitizedValue(properties),getSanitizedValue(options),getSanitizedValue(callback)));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2424
2510
|
* Process identify arguments and forward to page call
|
|
2425
2511
|
*/// These overloads should be same as AnalyticsIdentifyMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
2426
|
-
identify(userId,traits,options,callback){try{this.getAnalyticsInstance()
|
|
2512
|
+
identify(userId,traits,options,callback){try{var _this$getAnalyticsIns5;(_this$getAnalyticsIns5=this.getAnalyticsInstance())===null||_this$getAnalyticsIns5===void 0||_this$getAnalyticsIns5.identify(identifyArgumentsToCallOptions(getSanitizedValue(userId),getSanitizedValue(traits),getSanitizedValue(options),getSanitizedValue(callback)));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2427
2513
|
* Process alias arguments and forward to page call
|
|
2428
2514
|
*/// These overloads should be same as AnalyticsAliasMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
2429
|
-
alias(to,from,options,callback){try{this.getAnalyticsInstance()
|
|
2515
|
+
alias(to,from,options,callback){try{var _this$getAnalyticsIns6;(_this$getAnalyticsIns6=this.getAnalyticsInstance())===null||_this$getAnalyticsIns6===void 0||_this$getAnalyticsIns6.alias(aliasArgumentsToCallOptions(getSanitizedValue(to),getSanitizedValue(from),getSanitizedValue(options),getSanitizedValue(callback)));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2430
2516
|
* Process group arguments and forward to page call
|
|
2431
2517
|
*/// These overloads should be same as AnalyticsGroupMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
2432
|
-
group(groupId,traits,options,callback){try{this.getAnalyticsInstance()
|
|
2518
|
+
group(groupId,traits,options,callback){try{var _this$getAnalyticsIns7;(_this$getAnalyticsIns7=this.getAnalyticsInstance())===null||_this$getAnalyticsIns7===void 0||_this$getAnalyticsIns7.group(groupArgumentsToCallOptions(getSanitizedValue(groupId),getSanitizedValue(traits),getSanitizedValue(options),getSanitizedValue(callback)));}catch(error){dispatchErrorEvent(error);}}/**
|
|
2433
2519
|
* Reset the analytics instance
|
|
2434
2520
|
* @param options Reset options. Except for anonymousId, initialReferrer, and initialReferringDomain
|
|
2435
2521
|
* all other values will be reset by default.
|
|
@@ -2456,6 +2542,8 @@ group(groupId,traits,options,callback){try{this.getAnalyticsInstance()?.group(gr
|
|
|
2456
2542
|
* @param resetAnonymousId Reset anonymous ID
|
|
2457
2543
|
* @returns none
|
|
2458
2544
|
* @deprecated Use reset(options) instead
|
|
2459
|
-
*/reset(options){try{this.getAnalyticsInstance()
|
|
2545
|
+
*/reset(options){try{var _this$getAnalyticsIns8;(_this$getAnalyticsIns8=this.getAnalyticsInstance())===null||_this$getAnalyticsIns8===void 0||_this$getAnalyticsIns8.reset(getSanitizedValue(options));}catch(error){dispatchErrorEvent(error);}}getAnonymousId(options){try{var _this$getAnalyticsIns9;return (_this$getAnalyticsIns9=this.getAnalyticsInstance())===null||_this$getAnalyticsIns9===void 0?void 0:_this$getAnalyticsIns9.getAnonymousId(getSanitizedValue(options));}catch(error){dispatchErrorEvent(error);return undefined;}}setAnonymousId(anonymousId,rudderAmpLinkerParam){try{var _this$getAnalyticsIns0;(_this$getAnalyticsIns0=this.getAnalyticsInstance())===null||_this$getAnalyticsIns0===void 0||_this$getAnalyticsIns0.setAnonymousId(getSanitizedValue(anonymousId),getSanitizedValue(rudderAmpLinkerParam));}catch(error){dispatchErrorEvent(error);}}getUserId(){try{var _this$getAnalyticsIns1;return (_this$getAnalyticsIns1=this.getAnalyticsInstance())===null||_this$getAnalyticsIns1===void 0?void 0:_this$getAnalyticsIns1.getUserId();}catch(error){dispatchErrorEvent(error);return undefined;}}getUserTraits(){try{var _this$getAnalyticsIns10;return (_this$getAnalyticsIns10=this.getAnalyticsInstance())===null||_this$getAnalyticsIns10===void 0?void 0:_this$getAnalyticsIns10.getUserTraits();}catch(error){dispatchErrorEvent(error);return undefined;}}getGroupId(){try{var _this$getAnalyticsIns11;return (_this$getAnalyticsIns11=this.getAnalyticsInstance())===null||_this$getAnalyticsIns11===void 0?void 0:_this$getAnalyticsIns11.getGroupId();}catch(error){dispatchErrorEvent(error);return undefined;}}getGroupTraits(){try{var _this$getAnalyticsIns12;return (_this$getAnalyticsIns12=this.getAnalyticsInstance())===null||_this$getAnalyticsIns12===void 0?void 0:_this$getAnalyticsIns12.getGroupTraits();}catch(error){dispatchErrorEvent(error);return undefined;}}setCustomContext(context){try{var _this$getAnalyticsIns13;(_this$getAnalyticsIns13=this.getAnalyticsInstance())===null||_this$getAnalyticsIns13===void 0||_this$getAnalyticsIns13.setCustomContext(context);}catch(error){dispatchErrorEvent(error);}}getCustomContext(){try{var _this$getAnalyticsIns14,_this$getAnalyticsIns15;return (_this$getAnalyticsIns14=(_this$getAnalyticsIns15=this.getAnalyticsInstance())===null||_this$getAnalyticsIns15===void 0?void 0:_this$getAnalyticsIns15.getCustomContext())!==null&&_this$getAnalyticsIns14!==void 0?_this$getAnalyticsIns14:{};}catch(error){dispatchErrorEvent(error);return {};}}clearCustomContext(){try{var _this$getAnalyticsIns16;(_this$getAnalyticsIns16=this.getAnalyticsInstance())===null||_this$getAnalyticsIns16===void 0||_this$getAnalyticsIns16.clearCustomContext();}catch(error){dispatchErrorEvent(error);}}startSession(sessionId){try{var _this$getAnalyticsIns17;(_this$getAnalyticsIns17=this.getAnalyticsInstance())===null||_this$getAnalyticsIns17===void 0||_this$getAnalyticsIns17.startSession(getSanitizedValue(sessionId));}catch(error){dispatchErrorEvent(error);}}endSession(){try{var _this$getAnalyticsIns18;(_this$getAnalyticsIns18=this.getAnalyticsInstance())===null||_this$getAnalyticsIns18===void 0||_this$getAnalyticsIns18.endSession();}catch(error){dispatchErrorEvent(error);}}getSessionId(){try{var _this$getAnalyticsIns19;return (_this$getAnalyticsIns19=this.getAnalyticsInstance())===null||_this$getAnalyticsIns19===void 0?void 0:_this$getAnalyticsIns19.getSessionId();}catch(error){dispatchErrorEvent(error);return undefined;}}setAuthToken(token){try{var _this$getAnalyticsIns20;(_this$getAnalyticsIns20=this.getAnalyticsInstance())===null||_this$getAnalyticsIns20===void 0||_this$getAnalyticsIns20.setAuthToken(getSanitizedValue(token));}catch(error){dispatchErrorEvent(error);}}consent(options){try{var _this$getAnalyticsIns21;(_this$getAnalyticsIns21=this.getAnalyticsInstance())===null||_this$getAnalyticsIns21===void 0||_this$getAnalyticsIns21.consent(getSanitizedValue(options));}catch(error){dispatchErrorEvent(error);}}addCustomIntegration(destinationId,integration){try{var _this$getAnalyticsIns22;(_this$getAnalyticsIns22=this.getAnalyticsInstance())===null||_this$getAnalyticsIns22===void 0||_this$getAnalyticsIns22.addCustomIntegration(getSanitizedValue(destinationId),getSanitizedValue(integration));}catch(error){dispatchErrorEvent(error);}}}// START-NO-SONAR-SCAN
|
|
2546
|
+
// eslint-disable-next-line sonarjs/public-static-readonly
|
|
2547
|
+
_defineProperty(RudderAnalytics,"globalSingleton",null);
|
|
2460
2548
|
|
|
2461
2549
|
export { RudderAnalytics };
|