@rudderstack/analytics-js 3.34.2 → 3.35.0
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 +41 -0
- package/dist/npm/index.d.cts +9 -0
- package/dist/npm/index.d.mts +9 -0
- package/dist/npm/legacy/bundled/cjs/index.cjs +152 -64
- package/dist/npm/legacy/bundled/esm/index.mjs +152 -64
- package/dist/npm/legacy/bundled/umd/index.js +152 -64
- package/dist/npm/legacy/cjs/index.cjs +152 -64
- package/dist/npm/legacy/content-script/cjs/index.cjs +150 -63
- package/dist/npm/legacy/content-script/esm/index.mjs +150 -63
- package/dist/npm/legacy/content-script/umd/index.js +150 -63
- package/dist/npm/legacy/esm/index.mjs +152 -64
- package/dist/npm/legacy/lite/cjs/index.cjs +151 -63
- package/dist/npm/legacy/lite/esm/index.mjs +151 -63
- package/dist/npm/legacy/lite/umd/index.js +151 -63
- package/dist/npm/legacy/umd/index.js +152 -64
- package/dist/npm/modern/bundled/cjs/index.cjs +457 -327
- package/dist/npm/modern/bundled/esm/index.mjs +457 -327
- package/dist/npm/modern/bundled/umd/index.js +457 -327
- package/dist/npm/modern/cjs/index.cjs +356 -231
- package/dist/npm/modern/content-script/cjs/index.cjs +457 -327
- package/dist/npm/modern/content-script/esm/index.mjs +457 -327
- package/dist/npm/modern/content-script/umd/index.js +457 -327
- package/dist/npm/modern/esm/index.mjs +356 -231
- package/dist/npm/modern/lite/cjs/index.cjs +428 -298
- package/dist/npm/modern/lite/esm/index.mjs +428 -298
- package/dist/npm/modern/lite/umd/index.js +428 -298
- package/dist/npm/modern/umd/index.js +356 -231
- package/package.json +1 -1
|
@@ -2,6 +2,70 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
|
+
function _defineProperty(e, r, t) {
|
|
6
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
7
|
+
value: t,
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true
|
|
11
|
+
}) : e[r] = t, e;
|
|
12
|
+
}
|
|
13
|
+
function ownKeys(e, r) {
|
|
14
|
+
var t = Object.keys(e);
|
|
15
|
+
if (Object.getOwnPropertySymbols) {
|
|
16
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
17
|
+
r && (o = o.filter(function (r) {
|
|
18
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
19
|
+
})), t.push.apply(t, o);
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
}
|
|
23
|
+
function _objectSpread2(e) {
|
|
24
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
25
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
26
|
+
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
|
|
27
|
+
_defineProperty(e, r, t[r]);
|
|
28
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
29
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return e;
|
|
33
|
+
}
|
|
34
|
+
function _objectWithoutProperties(e, t) {
|
|
35
|
+
if (null == e) return {};
|
|
36
|
+
var o,
|
|
37
|
+
r,
|
|
38
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
39
|
+
if (Object.getOwnPropertySymbols) {
|
|
40
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
41
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
42
|
+
}
|
|
43
|
+
return i;
|
|
44
|
+
}
|
|
45
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
46
|
+
if (null == r) return {};
|
|
47
|
+
var t = {};
|
|
48
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
49
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
50
|
+
t[n] = r[n];
|
|
51
|
+
}
|
|
52
|
+
return t;
|
|
53
|
+
}
|
|
54
|
+
function _toPrimitive(t, r) {
|
|
55
|
+
if ("object" != typeof t || !t) return t;
|
|
56
|
+
var e = t[Symbol.toPrimitive];
|
|
57
|
+
if (void 0 !== e) {
|
|
58
|
+
var i = e.call(t, r);
|
|
59
|
+
if ("object" != typeof i) return i;
|
|
60
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
61
|
+
}
|
|
62
|
+
return ("string" === r ? String : Number)(t);
|
|
63
|
+
}
|
|
64
|
+
function _toPropertyKey(t) {
|
|
65
|
+
var i = _toPrimitive(t, "string");
|
|
66
|
+
return "symbol" == typeof i ? i : i + "";
|
|
67
|
+
}
|
|
68
|
+
|
|
5
69
|
function _isPlaceholder(a){return a!=null&&typeof a==='object'&&a['@@functional/placeholder']===true;}
|
|
6
70
|
|
|
7
71
|
/**
|
|
@@ -383,7 +447,7 @@ if(isString(category)&&!isString(name)){payload.category=undefined;payload.name=
|
|
|
383
447
|
// and set some proper defaults
|
|
384
448
|
// Also, to clone the incoming object type arguments
|
|
385
449
|
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
|
|
386
|
-
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{
|
|
450
|
+
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},_objectSpread2(_objectSpread2({},nameForProperties&&{name:nameForProperties}),categoryForProperties&&{category:categoryForProperties}));return payload;};/*
|
|
387
451
|
* Normalise the overloaded arguments of the track call facade
|
|
388
452
|
*/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
|
|
389
453
|
// and set some proper defaults
|
|
@@ -440,7 +504,7 @@ const generateUUID=()=>{if(hasCrypto$1()){return v4$1();}return v4();};
|
|
|
440
504
|
/**
|
|
441
505
|
* Determines if the SDK is running inside a chrome extension
|
|
442
506
|
* @returns boolean
|
|
443
|
-
*/const isSDKRunningInChromeExtension=()
|
|
507
|
+
*/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);
|
|
444
508
|
|
|
445
509
|
/**
|
|
446
510
|
* Registers events to detect page leave scenarios
|
|
@@ -474,25 +538,25 @@ const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A scrip
|
|
|
474
538
|
|
|
475
539
|
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
|
|
476
540
|
// eslint-disable-next-line func-names
|
|
477
|
-
return function(key,value){if(excludeKeys
|
|
541
|
+
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.
|
|
478
542
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
479
543
|
// @ts-ignore-next-line
|
|
480
|
-
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger
|
|
544
|
+
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;};};/**
|
|
481
545
|
* Utility method for JSON stringify object excluding null values & circular references
|
|
482
546
|
*
|
|
483
547
|
* @param {*} value input
|
|
484
548
|
* @param {boolean} excludeNull if it should exclude nul or not
|
|
485
549
|
* @param {function} logger optional logger methods for warning
|
|
486
550
|
* @returns string
|
|
487
|
-
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger
|
|
551
|
+
*/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
|
|
488
552
|
// Using a regular function to use `this` for the parent context
|
|
489
|
-
return function replacer(key,value){if(isBigInt(value)){logger
|
|
553
|
+
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
|
|
490
554
|
}// `this` is the object that value is contained in, i.e., its direct parent.
|
|
491
555
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
492
556
|
// @ts-ignore-next-line
|
|
493
557
|
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();// Remove ancestors that are no longer part of the chain
|
|
494
558
|
}// Check for circular references (if the value is already in the ancestors)
|
|
495
|
-
if(ancestors.includes(value)){logger
|
|
559
|
+
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
|
|
496
560
|
ancestors.push(value);return value;};};const traverseWithThis=(obj,replacer)=>{// Create a new result object or array
|
|
497
561
|
const result=Array.isArray(obj)?[]:{};// Traverse object properties or array elements
|
|
498
562
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -515,11 +579,11 @@ const MANUAL_ERROR_IDENTIFIER='[SDK DISPATCHED ERROR]';const getStacktrace=err=>
|
|
|
515
579
|
*/const getMutatedError=(err,issue)=>{if(!isTypeOfError(err)){return new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}try{// Preserve the specific error type (TypeError, ReferenceError, etc.)
|
|
516
580
|
const ErrorConstructor=err.constructor;const newError=new ErrorConstructor(`${issue}: ${err.message}`);// Preserve stack trace
|
|
517
581
|
const stack=getStacktrace(err);if(stack){newError.stack=stack;}// Preserve any other enumerable properties
|
|
518
|
-
Object.getOwnPropertyNames(err).forEach(key=>{if(key!=='message'&&key!=='stack'&&key!=='name'){try{newError[key]=err[key];}catch{// Ignore if property is not writable
|
|
519
|
-
}}});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
|
|
582
|
+
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
|
|
583
|
+
}}});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
|
|
520
584
|
error.stack=`${errStack}\n${MANUAL_ERROR_IDENTIFIER}`;}}globalThis.dispatchEvent(new ErrorEvent('error',{error,bubbles:true,cancelable:true,composed:true}));};
|
|
521
585
|
|
|
522
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.
|
|
586
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.35.0';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const BUILD_VARIANT='content-script';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';
|
|
523
587
|
|
|
524
588
|
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';
|
|
525
589
|
|
|
@@ -587,10 +651,10 @@ const EXTERNAL_SOURCE_LOAD_ORIGIN='RS_JS_SDK';
|
|
|
587
651
|
* @param {*} newScriptElement the script element to add
|
|
588
652
|
*
|
|
589
653
|
* @returns
|
|
590
|
-
*/const insertScript=newScriptElement=>{
|
|
591
|
-
const headElements=document.getElementsByTagName('head');if(headElements.length>0){headElements[0]
|
|
592
|
-
const scriptElements=document.getElementsByTagName('script');if(scriptElements.length>0&&scriptElements[0]
|
|
593
|
-
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement
|
|
654
|
+
*/const insertScript=newScriptElement=>{var _scriptElements$;// First try to add it to the head
|
|
655
|
+
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
|
|
656
|
+
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
|
|
657
|
+
const headElement=document.createElement('head');headElement.appendChild(newScriptElement);const htmlElement=document.getElementsByTagName('html')[0];htmlElement===null||htmlElement===void 0||htmlElement.insertBefore(headElement,htmlElement.firstChild);};/**
|
|
594
658
|
* Loads external js file as a script html tag
|
|
595
659
|
*
|
|
596
660
|
* @param {*} url The URL of the script to be loaded
|
|
@@ -618,7 +682,7 @@ var i=Symbol.for("preact-signals");function t(){if(!(v>1)){var i,t=false;!functi
|
|
|
618
682
|
|
|
619
683
|
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;';/**
|
|
620
684
|
* Service to log messages/data to output provider, default is console
|
|
621
|
-
*/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()]
|
|
685
|
+
*/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
|
|
622
686
|
// to assist on the fly debugging?
|
|
623
687
|
setMinLogLevel(logLevel){this.minLogLevel=LOG_LEVEL_MAP[logLevel];if(isUndefined(this.minLogLevel)){this.minLogLevel=LOG_LEVEL_MAP[DEFAULT_LOG_LEVEL];}}/**
|
|
624
688
|
* Formats the console message using `scope` and styles
|
|
@@ -639,7 +703,7 @@ const SUPPORTED_STORAGE_TYPES=['localStorage','memoryStorage','cookieStorage','s
|
|
|
639
703
|
|
|
640
704
|
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
|
|
641
705
|
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
|
|
642
|
-
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
|
|
706
|
+
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.`;
|
|
643
707
|
|
|
644
708
|
const DEFAULT_INTEGRATIONS_CONFIG={All:true};
|
|
645
709
|
|
|
@@ -654,7 +718,9 @@ const CDN_INT_DIR='js-integrations';const CDN_PLUGINS_DIR='plugins';const URL_PA
|
|
|
654
718
|
'(\\#[-a-zA-Z\\d_]*)?$')// fragment locator
|
|
655
719
|
;
|
|
656
720
|
|
|
657
|
-
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'
|
|
721
|
+
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
|
|
722
|
+
// the generated federation code requests at runtime.
|
|
723
|
+
const REMOTE_PLUGINS_ENTRY_FILE='rsa-plugins.js';
|
|
658
724
|
|
|
659
725
|
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';
|
|
660
726
|
|
|
@@ -665,7 +731,7 @@ anonymousId:false,initialReferrer:false,initialReferringDomain:false}});const SE
|
|
|
665
731
|
|
|
666
732
|
const sessionState={userId:y(DEFAULT_USER_SESSION_VALUES.userId),userTraits:y(DEFAULT_USER_SESSION_VALUES.userTraits),anonymousId:y(DEFAULT_USER_SESSION_VALUES.anonymousId),groupId:y(DEFAULT_USER_SESSION_VALUES.groupId),groupTraits:y(DEFAULT_USER_SESSION_VALUES.groupTraits),initialReferrer:y(DEFAULT_USER_SESSION_VALUES.initialReferrer),initialReferringDomain:y(DEFAULT_USER_SESSION_VALUES.initialReferringDomain),sessionInfo:y(DEFAULT_USER_SESSION_VALUES.sessionInfo),authToken:y(DEFAULT_USER_SESSION_VALUES.authToken)};
|
|
667
733
|
|
|
668
|
-
const capabilitiesState={isOnline:y(true),storage:{isLocalStorageAvailable:y(false),isCookieStorageAvailable:y(false),isSessionStorageAvailable:y(false)},isBeaconAvailable:y(false),isLegacyDOM:y(false),isUaCHAvailable:y(false),isCryptoAvailable:y(false),isAdBlockerDetectionInProgress:y(false),isAdBlocked:y(undefined),
|
|
734
|
+
const capabilitiesState={isOnline:y(true),storage:{isLocalStorageAvailable:y(false),isCookieStorageAvailable:y(false),isSessionStorageAvailable:y(false)},isBeaconAvailable:y(false),isLegacyDOM:y(false),isUaCHAvailable:y(false),isCryptoAvailable:y(false),isAdBlockerDetectionInProgress:y(false),isAdBlocked:y(undefined),cspViolations:y([]),sdkCdnProbe:y({})};
|
|
669
735
|
|
|
670
736
|
const reportingState={isErrorReportingEnabled:y(false),isMetricsReportingEnabled:y(false),breadcrumbs:y([])};
|
|
671
737
|
|
|
@@ -697,9 +763,11 @@ const dataPlaneEventsState={eventsQueuePluginName:y(undefined),deliveryEnabled:y
|
|
|
697
763
|
|
|
698
764
|
const autoTrackState={enabled:y(false),pageLifecycle:{enabled:y(false),pageViewId:y(undefined),pageLoadedTimestamp:y(undefined)}};
|
|
699
765
|
|
|
700
|
-
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={
|
|
766
|
+
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));
|
|
701
767
|
|
|
702
|
-
const CHROME_STACK_LINE_RE=/^\s*at /;const SAFARI_NATIVE_RE=/^(eval@)?(\[native code])?$/;const
|
|
768
|
+
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,
|
|
769
|
+
// colons included, is the file. A url keeps its scheme because "//host" is not digits.
|
|
770
|
+
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};}/**
|
|
703
771
|
* Parses an Error object's stack trace into structured frames.
|
|
704
772
|
* Supports V8/Chromium (Chrome, Edge, Node) and SpiderMonkey/WebKit (Firefox, Safari) formats.
|
|
705
773
|
* Throws if the error has no stack property.
|
|
@@ -709,13 +777,15 @@ const GLOBAL_CODE='global code';const normalizeFunctionName=name=>{if(isDefined(
|
|
|
709
777
|
// - non-error exception thrown from global code in FF
|
|
710
778
|
// This adds one.
|
|
711
779
|
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
|
|
712
|
-
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,[]);}};
|
|
780
|
+
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,[]);}};
|
|
713
781
|
|
|
714
782
|
/**
|
|
715
783
|
* Utility to parse XHR JSON response
|
|
716
784
|
*/const responseTextToJson=(responseText,onError)=>{try{return JSON.parse(responseText||'');}catch(err){const error=getMutatedError(err,'Failed to parse response data');onError(error);}return undefined;};
|
|
717
785
|
|
|
718
|
-
const FAILED_REQUEST_ERR_MSG_PREFIX='The request failed';const PLUGINS_LOAD_FAILURE_MESSAGES=[
|
|
786
|
+
const FAILED_REQUEST_ERR_MSG_PREFIX='The request failed';const PLUGINS_LOAD_FAILURE_MESSAGES=[// Chromium
|
|
787
|
+
/Failed to fetch dynamically imported module: .*/,// Firefox
|
|
788
|
+
/error loading dynamically imported module: .*/];const INTEGRATIONS_LOAD_FAILURE_MESSAGES=[/Unable to load \(.*\) the script with the id .*/,/A timeout of \d+ ms occurred while trying to load the script with id .*/];const ERROR_MESSAGES_TO_BE_FILTERED=[new RegExp(`${FAILED_REQUEST_ERR_MSG_PREFIX}.*`),/A script with the id .* is already loaded\./];const SCRIPT_LOAD_FAILURE_MESSAGES=[...PLUGINS_LOAD_FAILURE_MESSAGES,...INTEGRATIONS_LOAD_FAILURE_MESSAGES];const INTEGRATIONS_ERROR_CATEGORY='integrations';const SDK_ERROR_CATEGORY='sdk';const DEFAULT_ERROR_CATEGORY=SDK_ERROR_CATEGORY;
|
|
719
789
|
|
|
720
790
|
const DEFAULT_XHR_REQUEST_OPTIONS={headers:{Accept:'application/json','Content-Type':'application/json;charset=UTF-8'},method:'GET'};/**
|
|
721
791
|
* Utility to create request configuration based on default options
|
|
@@ -725,7 +795,7 @@ const DEFAULT_XHR_REQUEST_OPTIONS={headers:{Accept:'application/json','Content-T
|
|
|
725
795
|
* this is not supported by our sourceConfig API
|
|
726
796
|
*/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
|
|
727
797
|
return;}}const xhr=new XMLHttpRequest();// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
728
|
-
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
|
|
798
|
+
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
|
|
729
799
|
// and the first call to the send method in legacy browsers
|
|
730
800
|
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});}});
|
|
731
801
|
|
|
@@ -733,14 +803,14 @@ xhr.timeout=timeout;Object.keys(options.headers).forEach(headerName=>{if(options
|
|
|
733
803
|
* Service to handle data communication with APIs
|
|
734
804
|
*/class HttpClient{constructor(logger){this.logger=logger;this.onError=this.onError.bind(this);}init(errorHandler){this.errorHandler=errorHandler;}/**
|
|
735
805
|
* Implement requests in a blocking way
|
|
736
|
-
*/async getData(config){const{url,options,timeout,isRawResponse}=config;try{const data=await xhrRequest(createXhrRequestOptions(url,options,this.
|
|
806
|
+
*/async getData(config){const{url,options,timeout,isRawResponse,skipAuthHeader}=config;try{const data=await xhrRequest(createXhrRequestOptions(url,options,this.getAuthHeader(skipAuthHeader)),timeout,this.logger);return {data:isRawResponse?data.response:responseTextToJson(data.response,this.onError),details:data};}catch(reason){return {data:undefined,details:reason};}}/**
|
|
737
807
|
* Implement requests in a non-blocking way
|
|
738
|
-
*/getAsyncData(config){const{callback,url,options,timeout,isRawResponse}=config;const isFireAndForget=!isFunction(callback);xhrRequest(createXhrRequestOptions(url,options,this.
|
|
808
|
+
*/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
|
|
739
809
|
.catch(this.onError);}/**
|
|
740
810
|
* Handle errors
|
|
741
|
-
*/onError(error,groupingHash){this.errorHandler
|
|
811
|
+
*/onError(error,groupingHash){var _this$errorHandler;(_this$errorHandler=this.errorHandler)===null||_this$errorHandler===void 0||_this$errorHandler.onError({error,context:HTTP_CLIENT,groupingHash});}/**
|
|
742
812
|
* Set basic authentication header (eg writekey)
|
|
743
|
-
*/setAuthHeader(value,noBtoa=false){const authVal=noBtoa?value:toBase64(`${value}:`);this.basicAuthHeader=`Basic ${authVal}`;}/**
|
|
813
|
+
*/getAuthHeader(skipAuthHeader){return skipAuthHeader===true?undefined:this.basicAuthHeader;}setAuthHeader(value,noBtoa=false){const authVal=noBtoa?value:toBase64(`${value}:`);this.basicAuthHeader=`Basic ${authVal}`;}/**
|
|
744
814
|
* Clear basic authentication header
|
|
745
815
|
*/resetAuthHeader(){this.basicAuthHeader=undefined;}}const defaultHttpClient=new HttpClient(defaultLogger);
|
|
746
816
|
|
|
@@ -755,58 +825,79 @@ const APP_STATE_EXCLUDE_KEYS=['userId','userTraits','groupId','groupTraits','ano
|
|
|
755
825
|
'customContext',// customer-provided event context
|
|
756
826
|
'traits','authToken'];const NOTIFIER_NAME='RudderStack JavaScript SDK';const SDK_GITHUB_URL='git+https://github.com/rudderlabs/rudder-sdk-js.git';const SOURCE_NAME='js';
|
|
757
827
|
|
|
758
|
-
const detectAdBlockers=httpClient=>{state.capabilities.isAdBlockerDetectionInProgress.value=true;try{// Apparently, '?view=ad' is a query param that is blocked by majority of adblockers
|
|
759
|
-
// Use source config URL here as it is very unlikely to be blocked by adblockers
|
|
760
|
-
// Only the extra query param should make it vulnerable to adblockers
|
|
761
|
-
// This will work even if the users proxies it.
|
|
762
|
-
// The edge case where this doesn't work is when HEAD method is not allowed by the server (user's)
|
|
763
|
-
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
|
|
764
|
-
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
|
|
765
|
-
// Often adblockers instead of blocking the request, they redirect it to an internal URL
|
|
766
|
-
state.capabilities.isAdBlocked.value=details?.error!==undefined||details?.xhr?.responseURL!==url;}});}catch(err){// Reset the flag to prevent blocking future detection attempts
|
|
767
|
-
state.capabilities.isAdBlockerDetectionInProgress.value=false;// Re-throw the error to be handled by the caller
|
|
768
|
-
throw err;}};
|
|
769
|
-
|
|
770
828
|
const getErrInstance=(err,errorType)=>{switch(errorType){case ErrorType.UNHANDLEDEXCEPTION:{const{error}=err;return error||err;}case ErrorType.UNHANDLEDREJECTION:{return err.reason;}case ErrorType.HANDLEDEXCEPTION:default:return err;}};const createNewBreadcrumb=message=>({type:'manual',name:message,timestamp:new Date(),metaData:{}});/**
|
|
771
829
|
* A function to get the Bugsnag release stage for the current environment
|
|
772
830
|
* @param getHostName Optional function to get the hostname (primarily for testing)
|
|
773
831
|
* @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)
|
|
774
|
-
*/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)=>
|
|
775
|
-
//
|
|
776
|
-
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
832
|
+
*/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
|
|
833
|
+
// is the fallback for both, so it counts for either.
|
|
834
|
+
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));/**
|
|
835
|
+
* Whether a URL is the blocked one or sits beneath it.
|
|
836
|
+
*
|
|
837
|
+
* Browsers strip a cross-origin blockedURI down to its origin, so a stored entry
|
|
838
|
+
* is often a prefix of the failing URL rather than equal to it. Matching on a
|
|
839
|
+
* bare string prefix is too loose: an origin entry would swallow a look-alike
|
|
840
|
+
* host, and a script entry would swallow its own source map. The prefix only
|
|
841
|
+
* counts when the next character starts a new path, query or fragment.
|
|
842
|
+
*/const isSameOrUnder=(url,blockedURL)=>{if(url===blockedURL){return true;}if(!url.startsWith(blockedURL)){return false;}const boundary=url.charAt(blockedURL.length);return boundary==='/'||boundary==='?'||boundary==='#';};// Probes already in flight, keyed by URL. Concurrent failures share one request
|
|
843
|
+
// rather than each firing its own HEAD and possibly reaching different verdicts
|
|
844
|
+
// about the same URL.
|
|
845
|
+
const inFlightProbes=new Map();/**
|
|
846
|
+
* Probes the URL that failed to load and records what came back, so the report
|
|
847
|
+
* can tell a request that never left the client from one the CDN answered with
|
|
848
|
+
* an error. The failed URL is probed rather than a fixed path: plugins and
|
|
849
|
+
* integrations sit under different prefixes and can be blocked independently.
|
|
850
|
+
*/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
|
|
851
|
+
// carrying none of the headers the client would otherwise add.
|
|
852
|
+
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
|
|
853
|
+
// answers instead of dropping it lands on a URL outside the CDN. An
|
|
854
|
+
// ordinary redirect that stays under the CDN -- canonicalisation, a signed
|
|
855
|
+
// URL -- is the CDN answering and must not be mistaken for one.
|
|
856
|
+
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());}});};/**
|
|
788
857
|
* A function to determine whether the error should be promoted to notify or not.
|
|
789
|
-
*
|
|
790
|
-
*
|
|
791
|
-
*
|
|
858
|
+
* Script load failures from a host other than the RS CDN are not promoted.
|
|
859
|
+
* For those from the RS CDN, a probe of the failed URL is awaited so its result
|
|
860
|
+
* is carried in the report, and the error is suppressed in exactly two cases: a
|
|
861
|
+
* CSP violation covering that URL, or a probe whose shape nothing server side
|
|
862
|
+
* produces -- a request that never reached the CDN, or one answered by
|
|
863
|
+
* something else. Any status the CDN itself returned is promoted.
|
|
864
|
+
* The generic ad blocker signal is deliberately not consulted: it probes the
|
|
865
|
+
* source config host, and a client that cannot reach the CDN cannot be told
|
|
866
|
+
* apart from a CDN outage.
|
|
867
|
+
* Errors from other causes are promoted unless explicitly denylisted.
|
|
792
868
|
* @param {Error} exception The error object
|
|
793
869
|
* @param {ApplicationState} state The application state
|
|
794
870
|
* @param {IHttpClient} httpClient The HTTP client instance
|
|
795
871
|
* @returns A promise that resolves to a boolean indicating whether the error should be promoted to notify or not
|
|
796
872
|
*/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.
|
|
797
|
-
if(SCRIPT_LOAD_FAILURE_MESSAGES.some(regex=>regex.test(errMsg))){const extractedURL=/https?:\/\/[^\s"'(),;<>[\]{}]+/.exec(errMsg)
|
|
798
|
-
|
|
799
|
-
|
|
873
|
+
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
|
|
874
|
+
// report. The generic ad blocker signal is deliberately not consulted:
|
|
875
|
+
// it probes the source config host rather than the CDN, and a client
|
|
876
|
+
// that cannot reach the CDN is indistinguishable from a CDN outage, so
|
|
877
|
+
// it must not suppress the error.
|
|
878
|
+
probeSdkCdn(state,httpClient,extractedURL,()=>{// Only a script directive can explain a failed script load.
|
|
879
|
+
const isCspBlocked=hasCspViolation(state,extractedURL,SCRIPT_CSP_DIRECTIVES);// A probe that never reached the CDN, or that was answered by
|
|
880
|
+
// something else, is a client-side failure: nothing server side
|
|
881
|
+
// produces either shape. A timeout is not attributable, and any
|
|
882
|
+
// status the CDN itself returned is worth reporting.
|
|
883
|
+
const probe=state.capabilities.sdkCdnProbe.value[extractedURL];// Unless CSP stopped the probe itself. connect-src governs the probe
|
|
884
|
+
// while script-src governs the import, and a page can allow the
|
|
885
|
+
// import and deny the probe -- then status 0 says nothing about the
|
|
886
|
+
// load that actually failed, so the probe is inconclusive and the
|
|
887
|
+
// error stands on its own.
|
|
888
|
+
const isProbeCspBlocked=hasCspViolation(state,extractedURL,CONNECT_CSP_DIRECTIVES);const isClientSideFailure=probe!==undefined&&!probe.timedOut&&!isProbeCspBlocked&&(probe.status===0||probe.redirectedOffCdn);resolve(!isCspBlocked&&!isClientSideFailure);});}else {// Filter out errors that are not from the RS CDN.
|
|
800
889
|
resolve(false);}}else {// Allow the error to be notified if no URL could be extracted from the error message
|
|
801
890
|
resolve(true);}}else {resolve(!ERROR_MESSAGES_TO_BE_FILTERED.some(e=>e.test(errMsg)));}});};/**
|
|
802
891
|
* A function to get the directory name from a file path.
|
|
803
892
|
* @param {string} filePath The file path
|
|
804
893
|
* @returns The directory name or undefined if the file path is invalid
|
|
805
|
-
*/const getDirectoryName=filePath=>{if(!filePath){return undefined;}const paths=filePath.split('/')
|
|
894
|
+
*/const getDirectoryName=filePath=>{if(!filePath){return undefined;}const paths=filePath.split('/');// Not `.at(-2)`: Array.prototype.at is neither transpiled nor polyfilled
|
|
895
|
+
return paths[paths.length-2];// NOSONAR
|
|
896
|
+
};/**
|
|
806
897
|
* A function to get the top stack path from the exception.
|
|
807
898
|
* @param {Exception} exception The exception object
|
|
808
899
|
* @returns The top stack path or undefined if the exception is invalid
|
|
809
|
-
*/const getTopStackPath=exception=>{const errorOrigin=exception.stacktrace[0]
|
|
900
|
+
*/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;};/**
|
|
810
901
|
* A function to determine if the error is from Rudder SDK
|
|
811
902
|
* @param {Error} exception
|
|
812
903
|
* @returns
|
|
@@ -823,15 +914,17 @@ resolve(true);}}else {resolve(!ERROR_MESSAGES_TO_BE_FILTERED.some(e=>e.test(errM
|
|
|
823
914
|
|
|
824
915
|
/**
|
|
825
916
|
* A service to handle errors
|
|
826
|
-
*/class ErrorHandler{
|
|
827
|
-
constructor(httpClient,logger){this.httpClient=httpClient;this.logger=logger;}/**
|
|
917
|
+
*/class ErrorHandler{// If no logger is passed errors will be thrown as unhandled error
|
|
918
|
+
constructor(httpClient,logger){_defineProperty(this,"initialized",false);this.httpClient=httpClient;this.logger=logger;}/**
|
|
828
919
|
* Initializes the error handler by attaching global error listeners.
|
|
829
920
|
* This method should be called once after construction.
|
|
830
921
|
*/init(){if(this.initialized){return;}this.attachErrorListeners();this.initialized=true;}/**
|
|
831
922
|
* Attach error listeners to the global window object
|
|
832
|
-
*/attachErrorListeners(){globalThis.addEventListener('error',event=>{this.onError({error:event,context:ERROR_HANDLER,errorType:ErrorType.UNHANDLEDEXCEPTION});});globalThis.addEventListener('unhandledrejection',event=>{this.onError({error:event,context:ERROR_HANDLER,errorType:ErrorType.UNHANDLEDREJECTION});});// Listen to CSP violations
|
|
833
|
-
//
|
|
834
|
-
|
|
923
|
+
*/attachErrorListeners(){globalThis.addEventListener('error',event=>{this.onError({error:event,context:ERROR_HANDLER,errorType:ErrorType.UNHANDLEDEXCEPTION});});globalThis.addEventListener('unhandledrejection',event=>{this.onError({error:event,context:ERROR_HANDLER,errorType:ErrorType.UNHANDLEDREJECTION});});// Listen to CSP violations for RS CDN URLs, recording the directive that
|
|
924
|
+
// rejected each one. script-src governs a plugin import and connect-src the
|
|
925
|
+
// reachability probe, so without the directive a probe-only violation looks
|
|
926
|
+
// identical to one that stopped the script.
|
|
927
|
+
document.addEventListener('securitypolicyviolation',event=>{const blockedURL=isString(event.blockedURI)?event.blockedURI:'';const directive=isString(event.effectiveDirective)?event.effectiveDirective:'';if(event.disposition!=='enforce'||!isSameOrUnder(blockedURL,SDK_CDN_BASE_URL)){return;}const isAlreadyRecorded=state.capabilities.cspViolations.value.some(violation=>violation.blockedURL===blockedURL&&violation.directive===directive);if(!isAlreadyRecorded){state.capabilities.cspViolations.value=[...state.capabilities.cspViolations.value,{blockedURL,directive}];}});}/**
|
|
835
928
|
* Handle errors
|
|
836
929
|
* @param errorInfo - The error information
|
|
837
930
|
* @param errorInfo.error - The error to handle
|
|
@@ -840,7 +933,7 @@ document.addEventListener('securitypolicyviolation',event=>{const blockedURL=isS
|
|
|
840
933
|
* @param errorInfo.errorType - The type of the error (handled or unhandled)
|
|
841
934
|
* @param errorInfo.groupingHash - The grouping hash of the error
|
|
842
935
|
* @param errorInfo.category - The category of the error (sdk or integrations)
|
|
843
|
-
*/async onError(errorInfo){try{const{error,context,customMessage,groupingHash,category}=errorInfo;const errorType=errorInfo.errorType
|
|
936
|
+
*/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.
|
|
844
937
|
// In case of NPM installations, the unhandled errors from the SDK cannot be identified
|
|
845
938
|
// and will NOT be reported unless they occur in plugins or integrations.
|
|
846
939
|
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.
|
|
@@ -864,10 +957,10 @@ const defaultErrorHandler=new ErrorHandler(defaultHttpClient,defaultLogger);
|
|
|
864
957
|
// to next or return the value if it is the last one instead of an array per
|
|
865
958
|
// plugin that is the normal invoke
|
|
866
959
|
// TODO: add invoke method for extension point that we know only one plugin can be used. add invokeMultiple and invokeSingle methods
|
|
867
|
-
class PluginEngine{plugins
|
|
960
|
+
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.
|
|
868
961
|
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
|
|
869
962
|
// do some unified pre-process before application starts.
|
|
870
|
-
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
|
|
963
|
+
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
|
|
871
964
|
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
|
|
872
965
|
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});
|
|
873
966
|
|
|
@@ -890,7 +983,8 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
|
|
|
890
983
|
* @param id The id of the destination
|
|
891
984
|
*
|
|
892
985
|
* @returns the user friendly id
|
|
893
|
-
*/const getDestinationUserFriendlyId=(displayName,id)
|
|
986
|
+
*/const getDestinationUserFriendlyId=(displayName,id)=>// displayName comes from the source config response, so it is not guaranteed to be a string
|
|
987
|
+
`${String(displayName!==null&&displayName!==void 0?displayName:'').replace(/ /g,'-')}___${id}`;
|
|
894
988
|
|
|
895
989
|
/**
|
|
896
990
|
* List of plugin names that are loaded as dynamic imports in modern builds
|
|
@@ -915,7 +1009,7 @@ new URL(url);}return URL_PATTERN.test(url);}catch(e){return false;}};
|
|
|
915
1009
|
|
|
916
1010
|
/**
|
|
917
1011
|
* Encode.
|
|
918
|
-
*/const encode=(value,logger)=>{try{return encodeURIComponent(value);}catch(err){logger
|
|
1012
|
+
*/const encode=(value,logger)=>{try{return encodeURIComponent(value);}catch(err){logger===null||logger===void 0||logger.error(COOKIE_DATA_ENCODING_ERROR,err);return undefined;}};/**
|
|
919
1013
|
* Decode
|
|
920
1014
|
*/const decode$1=value=>{try{return decodeURIComponent(value);}catch(err){// Do nothing as non-RS SDK cookies may not be URI encoded
|
|
921
1015
|
return undefined;}};/**
|
|
@@ -923,7 +1017,7 @@ return undefined;}};/**
|
|
|
923
1017
|
*/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
|
|
924
1018
|
pairs.forEach(pairItem=>{pair=pairItem.split('=');const keyName=pair[0]?decode$1(pair[0]):undefined;if(keyName){obj[keyName]=pair[1]?decode$1(pair[1]):undefined;}});return obj;};/**
|
|
925
1019
|
* Set cookie `name` to `value`
|
|
926
|
-
*/const set=(name,value,optionsConfig,logger)=>{const options={
|
|
1020
|
+
*/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;};/**
|
|
927
1021
|
* Return all cookies
|
|
928
1022
|
*/const all=()=>{const cookieStringValue=globalThis.document.cookie;return parse(cookieStringValue);};/**
|
|
929
1023
|
* Get cookie `name`
|
|
@@ -934,7 +1028,7 @@ const cookie=function(name,value,options,logger){switch(arguments.length){case 4
|
|
|
934
1028
|
|
|
935
1029
|
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_';
|
|
936
1030
|
|
|
937
|
-
const encryptBrowser=value=>`${ENCRYPTION_PREFIX_V3}${toBase64(value)}`;const decryptBrowser=value=>{if(value
|
|
1031
|
+
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;};
|
|
938
1032
|
|
|
939
1033
|
const EVENT_PAYLOAD_SIZE_BYTES_LIMIT=32*1024;// 32 KB
|
|
940
1034
|
const RETRY_REASON_CLIENT_NETWORK='client-network';const RETRY_REASON_CLIENT_TIMEOUT='client-timeout';const DEFAULT_RETRY_REASON=RETRY_REASON_CLIENT_NETWORK;
|
|
@@ -942,8 +1036,8 @@ const RETRY_REASON_CLIENT_NETWORK='client-network';const RETRY_REASON_CLIENT_TIM
|
|
|
942
1036
|
const isStorageQuotaExceeded=e=>{const matchingNames=['QuotaExceededError','NS_ERROR_DOM_QUOTA_REACHED'];// Everything except Firefox, Firefox
|
|
943
1037
|
const matchingCodes=[22,1014];if(e instanceof DOMException){return matchingNames.includes(e.name)||matchingCodes.includes(e.code);}return false;};// TODO: also check for SecurityErrors
|
|
944
1038
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#exceptions
|
|
945
|
-
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
|
|
946
|
-
break;case SESSION_STORAGE:storage=storageInstance
|
|
1039
|
+
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
|
|
1040
|
+
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
|
|
947
1041
|
return false;};
|
|
948
1042
|
|
|
949
1043
|
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';/**
|
|
@@ -955,7 +1049,7 @@ const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${
|
|
|
955
1049
|
* Utility to validate final payload size before sending to server
|
|
956
1050
|
* @param event RudderEvent object
|
|
957
1051
|
* @param logger Logger instance
|
|
958
|
-
*/const validateEventPayloadSize=(event,logger)=>{const payloadStr=getDeliveryPayload(event,logger);if(payloadStr){const payloadSize=payloadStr.length;if(payloadSize>EVENT_PAYLOAD_SIZE_BYTES_LIMIT){logger
|
|
1052
|
+
*/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));}};/**
|
|
959
1053
|
* Mutates the event and return final event for delivery
|
|
960
1054
|
* Updates certain parameters like sentAt timestamp, integrations config etc.
|
|
961
1055
|
* @param event RudderEvent object
|
|
@@ -986,7 +1080,7 @@ const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flush
|
|
|
986
1080
|
* @param events RudderEvent object array
|
|
987
1081
|
* @param logger Logger instance
|
|
988
1082
|
* @returns stringified events payload as Blob, undefined if error occurs.
|
|
989
|
-
*/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
|
|
1083
|
+
*/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;};
|
|
990
1084
|
|
|
991
1085
|
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={};}}
|
|
992
1086
|
|
|
@@ -1009,23 +1103,25 @@ const runningQueueIdsByName=new Map();class RetryQueue{/**
|
|
|
1009
1103
|
* @param {StorageType} [storageType] The storage type to use. Defaults to LOCAL_STORAGE
|
|
1010
1104
|
* @param {ILogger} [logger] The logger to use
|
|
1011
1105
|
* @param {QueueBatchItemsSizeCalculatorCallback} [queueBatchItemsSizeCalculatorCb] The callback to use to calculate the size of items in the batch queue
|
|
1012
|
-
*/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
|
|
1013
|
-
|
|
1106
|
+
*/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
|
|
1107
|
+
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
|
|
1108
|
+
jitter:Number.isNaN(jitter)?DEFAULT_BACKOFF_JITTER:Math.min(Math.max(jitter,0),1)};// Limit the timer scale factor to the minimum value
|
|
1109
|
+
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
|
|
1014
1110
|
timerScaleFactor=Math.min(timerScaleFactor,MAX_TIMER_SCALE_FACTOR);// painstakingly tuned. that's why they're not "easily" configurable
|
|
1015
1111
|
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
|
|
1016
1112
|
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
|
|
1017
1113
|
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
|
|
1018
|
-
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){
|
|
1019
|
-
this.batch.maxSize=Math.min(batchOptions.maxSize
|
|
1114
|
+
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
|
|
1115
|
+
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
|
|
1020
1116
|
setStorageEntry(name,value){if(isNullOrUndefined(value)){this.store.remove(name);}else {this.store.set(name,value);}}/**
|
|
1021
1117
|
* Stops processing the queue
|
|
1022
|
-
*/stop(){this.schedule.cancelAll();this.scheduleTimeoutActive=false;const runningQueueIds=runningQueueIdsByName.get(this.name);runningQueueIds
|
|
1118
|
+
*/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);}}/**
|
|
1023
1119
|
* Starts processing the queue
|
|
1024
|
-
*/start(){if(this.scheduleTimeoutActive){this.stop();}const runningQueueIds=runningQueueIdsByName.get(this.name)
|
|
1120
|
+
*/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();}/**
|
|
1025
1121
|
* Configures the timeout handler for flushing the batch queue
|
|
1026
|
-
*/scheduleFlushBatch(){if(this.batch.enabled&&this.batch
|
|
1122
|
+
*/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);}}/**
|
|
1027
1123
|
* Flushes the batch queue
|
|
1028
|
-
*/flushBatch(isAccessible=true){if(!this.batchingInProgress){this.isPageAccessible=isAccessible;this.batchingInProgress=true;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)
|
|
1124
|
+
*/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
|
|
1029
1125
|
this.scheduleFlushBatch();}}/**
|
|
1030
1126
|
* Decides whether to retry. Overridable.
|
|
1031
1127
|
*
|
|
@@ -1037,16 +1133,18 @@ this.scheduleFlushBatch();}}/**
|
|
|
1037
1133
|
*
|
|
1038
1134
|
* @param {Number} attemptNumber The attemptNumber (1 for first retry)
|
|
1039
1135
|
* @return {Number} The delay in milliseconds to wait before attempting a retry
|
|
1040
|
-
*/getDelay(attemptNumber){
|
|
1136
|
+
*/getDelay(attemptNumber){// Cap leaves headroom for +jitter so the jittered delay never exceeds maxRetryDelay
|
|
1137
|
+
const cap=Math.floor(this.backoff.maxRetryDelay/(1+this.backoff.jitter));let ms=Math.min(// First retry waits the base delay
|
|
1138
|
+
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
|
|
1041
1139
|
if(curEntry){this.pushToMainQueue(curEntry);}}/**
|
|
1042
1140
|
* Handles a new item added to the retry queue when batching is enabled
|
|
1043
1141
|
* @param entry New item added to the retry queue
|
|
1044
1142
|
* @returns Undefined or batch entry object
|
|
1045
|
-
*/handleNewItemForBatch(entry){let curEntry;let batchQueue=this.getStorageEntry(QueueStatuses.BATCH_QUEUE)
|
|
1143
|
+
*/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
|
|
1046
1144
|
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
|
|
1047
1145
|
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
|
|
1048
1146
|
this.scheduleFlushBatch();}this.batchingInProgress=false;}else {batchQueue.push(entry);}// update the batch queue
|
|
1049
|
-
this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}pushToMainQueue(curEntry){let queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1147
|
+
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();}}/**
|
|
1050
1148
|
* Adds an item to the queue
|
|
1051
1149
|
*
|
|
1052
1150
|
* @param {Object} itemData The item to process
|
|
@@ -1054,51 +1152,51 @@ this.setStorageEntry(QueueStatuses.BATCH_QUEUE,batchQueue);return curEntry;}push
|
|
|
1054
1152
|
* Generates a queue item
|
|
1055
1153
|
* @param itemData Queue item data
|
|
1056
1154
|
* @returns Queue item
|
|
1057
|
-
*/genQueueItem(itemData,type=SINGLE_QUEUE_ITEM_TYPE,reclaimed){return {item:itemData,attemptNumber:0,time:this.schedule.now(),id:generateUUID(),type
|
|
1155
|
+
*/genQueueItem(itemData,type=SINGLE_QUEUE_ITEM_TYPE,reclaimed){return _objectSpread2({item:itemData,attemptNumber:0,time:this.schedule.now(),id:generateUUID(),type},isDefined(reclaimed)?{reclaimed}:{});}/**
|
|
1058
1156
|
* Adds an item to the retry queue
|
|
1059
1157
|
*
|
|
1060
1158
|
* @param {Object} qItem The item to process
|
|
1061
1159
|
*/requeue(qItem){const{attemptNumber,item,type,id,firstAttemptedAt,lastAttemptedAt,reclaimed,retryReason}=qItem;// Increment the attempt number as we're about to retry
|
|
1062
|
-
const attemptNumberToUse=attemptNumber+1;if(this.shouldRetry(item,attemptNumberToUse)){this.enqueue({item,attemptNumber:attemptNumberToUse,time:this.schedule.now()+this.getDelay(attemptNumberToUse),id:id
|
|
1160
|
+
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});}}/**
|
|
1063
1161
|
* Returns the information about whether the batch criteria is met or exceeded
|
|
1064
1162
|
* @param batchItems Prospective batch items
|
|
1065
1163
|
* @returns Batch dispatch info
|
|
1066
|
-
*/getBatchDispatchInfo(batchItems){let lengthCriteriaMet=false;let lengthCriteriaExceeded=false;const configuredBatchMaxItems=this.batch
|
|
1164
|
+
*/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
|
|
1067
1165
|
this.schedule.cancel(this.processId);// Pop the head off the queue
|
|
1068
|
-
let queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1069
|
-
const processItemCallback=(el,id)=>(err,res)=>{const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)
|
|
1166
|
+
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
|
|
1167
|
+
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
|
|
1070
1168
|
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
|
|
1071
1169
|
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
|
|
1072
|
-
try{const now=this.schedule.now();const inProgress=this.getStorageEntry(QueueStatuses.IN_PROGRESS)
|
|
1073
|
-
reclaimed=inProgressItem.reclaimed
|
|
1170
|
+
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
|
|
1171
|
+
reclaimed=(_inProgressItem$recla=inProgressItem.reclaimed)!==null&&_inProgressItem$recla!==void 0?_inProgressItem$recla:reclaimed;// Update the first attempted at timestamp for the in progress item
|
|
1074
1172
|
inProgressItem.firstAttemptedAt=firstAttemptedAt;// Update the last attempted at to current timestamp for the in progress item
|
|
1075
1173
|
inProgressItem.lastAttemptedAt=now;inProgress[el.id]=inProgressItem;this.setStorageEntry(QueueStatuses.IN_PROGRESS,inProgress);}// A decimal integer representing the milliseconds since the first attempt
|
|
1076
1174
|
const timeSinceFirstAttempt=now-firstAttemptedAt;// A decimal integer representing the milliseconds since the last attempt
|
|
1077
|
-
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
|
|
1175
|
+
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
|
|
1078
1176
|
el.done(err);}else {errMsg=`Retries exhausted (${this.maxAttempts}). The item will be dropped.`;// drop the event as we're unable to process it
|
|
1079
1177
|
// after the max attempts are exhausted
|
|
1080
|
-
el.done();}this.logger
|
|
1081
|
-
queue=this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1178
|
+
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
|
|
1179
|
+
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
|
|
1082
1180
|
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);}/**
|
|
1083
1181
|
* Take over the items of another queue.
|
|
1084
1182
|
*
|
|
1085
1183
|
* Reads through the handle `findOtherQueues` discovered rather than building a
|
|
1086
1184
|
* fresh one: a quota error during the handshake swaps that handle to the
|
|
1087
1185
|
* in-memory engine, and a new localStorage store would find nothing.
|
|
1088
|
-
*/reclaim(other){const our={queue:this.getStorageEntry(QueueStatuses.QUEUE)
|
|
1186
|
+
*/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
|
|
1089
1187
|
// After some point, we can remove this hack as most of the stale data will have been processed
|
|
1090
1188
|
// and the new entries will have the type field set
|
|
1091
|
-
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
|
|
1189
|
+
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
|
|
1092
1190
|
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#
|
|
1093
1191
|
addConcatQueue(their.queue,0);// Process batch queue items
|
|
1094
|
-
if(this.batch.enabled){their.batchQueue.forEach(el=>{const id=el.id
|
|
1095
|
-
reclaimed:true,type:el.type
|
|
1192
|
+
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
|
|
1193
|
+
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
|
|
1096
1194
|
addConcatQueue(their.batchQueue,0);}// if the queue is abandoned, all the in-progress are failed. retry them immediately and increment the attempt#
|
|
1097
1195
|
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
|
|
1098
1196
|
this.clearQueueEntries(other,1);// process the new items we claimed
|
|
1099
1197
|
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
|
|
1100
1198
|
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
|
|
1101
|
-
this.removeStorageEntry(store,entryIdx,backoff+40,attempt+1);}else {this.logger
|
|
1199
|
+
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
|
|
1102
1200
|
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
|
|
1103
1201
|
// Hence, we need this backward compatibility check
|
|
1104
1202
|
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
|
|
@@ -1114,14 +1212,14 @@ const pluginName$d='BeaconQueue';const BeaconQueue=()=>({name:pluginName$d,deps:
|
|
|
1114
1212
|
* @param errorHandler Error handler instance
|
|
1115
1213
|
* @param logger Logger instance
|
|
1116
1214
|
* @returns BeaconItemsQueue instance
|
|
1117
|
-
*/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
|
|
1118
|
-
done(null);return;}try{if(!navigator.sendBeacon(url,data)){if(isPageAccessible){logger
|
|
1215
|
+
*/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
|
|
1216
|
+
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
|
|
1119
1217
|
done(null);}else {// Note: We're not removing the item from the queue as we want to retry the request
|
|
1120
|
-
logger
|
|
1121
|
-
done(null);}}catch(err){errorHandler
|
|
1218
|
+
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
|
|
1219
|
+
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
|
|
1122
1220
|
done(null);}};const eventsQueue=new RetryQueue(`${QUEUE_NAME$3}_${writeKey}`,{batch:{enabled:true,flushInterval:finalQOpts.flushQueueInterval,maxSize:MAX_BATCH_PAYLOAD_SIZE_BYTES,// set the hard limit
|
|
1123
|
-
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
|
|
1124
|
-
return getBatchDeliveryPayload$1(events,currentTime,logger).size;});return eventsQueue;},/**
|
|
1221
|
+
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
|
|
1222
|
+
return (_getBatchDeliveryPayl=getBatchDeliveryPayload$1(events,currentTime,logger))===null||_getBatchDeliveryPayl===void 0?void 0:_getBatchDeliveryPayl.size;});return eventsQueue;},/**
|
|
1125
1223
|
* Add event to the queue for delivery
|
|
1126
1224
|
* @param state Application state
|
|
1127
1225
|
* @param eventsQueue IQueue instance
|
|
@@ -1139,12 +1237,12 @@ const DESTINATION_CONSENT_STATUS_ERROR$3=`Failed to determine the consent status
|
|
|
1139
1237
|
|
|
1140
1238
|
const pluginName$c='CustomConsentManager';const CustomConsentManager=()=>({name:pluginName$c,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$c];},consentManager:{init(state,logger){// Nothing to initialize
|
|
1141
1239
|
},updateConsentsInfo(state,storeManager,logger){// Nothing to update. Already provided by the user
|
|
1142
|
-
},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.
|
|
1240
|
+
},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.
|
|
1143
1241
|
if(!consentManagement){return true;}// Get the corresponding consents for the destination
|
|
1144
1242
|
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.
|
|
1145
|
-
if(!cmpConfig
|
|
1243
|
+
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
|
|
1146
1244
|
// the configured resolution strategy
|
|
1147
|
-
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
|
|
1245
|
+
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;}}}});
|
|
1148
1246
|
|
|
1149
1247
|
const READY_CHECK_TIMEOUT_MS=11*1000;// 11 seconds
|
|
1150
1248
|
const SCRIPT_LOAD_TIMEOUT_MS=10*1000;// 10 seconds
|
|
@@ -1158,7 +1256,7 @@ const isDestIntgConfigTruthy=destIntgConfig=>!isUndefined(destIntgConfig)&&Boole
|
|
|
1158
1256
|
* @param intgOpts Integration options object
|
|
1159
1257
|
* @param destinations Destinations array
|
|
1160
1258
|
* @returns Destinations array filtered based on the integration options
|
|
1161
|
-
*/const filterDestinations=(intgOpts,destinations)=>{const allOptVal=intgOpts.All
|
|
1259
|
+
*/const filterDestinations=(intgOpts,destinations)=>{var _intgOpts$All;const allOptVal=(_intgOpts$All=intgOpts.All)!==null&&_intgOpts$All!==void 0?_intgOpts$All:true;return destinations.filter(dest=>{const destDisplayName=dest.displayName;let isDestEnabled;if(allOptVal){isDestEnabled=true;if(isDestIntgConfigFalsy(intgOpts[destDisplayName])){isDestEnabled=false;}}else {isDestEnabled=false;if(isDestIntgConfigTruthy(intgOpts[destDisplayName])){isDestEnabled=true;}}return isDestEnabled;});};
|
|
1162
1260
|
|
|
1163
1261
|
const ACTIVE_CAMPAIGN_DISPLAY_NAME='ActiveCampaign';const ADOBE_ANALYTICS_DISPLAY_NAME='Adobe Analytics';const ADROLL_DISPLAY_NAME='Adroll';const AM_DISPLAY_NAME='Amplitude';const APPCUES_DISPLAY_NAME='Appcues';const AXEPTIO_DISPLAY_NAME='Axeptio';const BINGADS_DISPLAY_NAME='Bing Ads';const BRAZE_DISPLAY_NAME='Braze';const BUGSNAG_DISPLAY_NAME='Bugsnag';const CHARTBEAT_DISPLAY_NAME='Chartbeat';const CLEVERTAP_DISPLAY_NAME='CleverTap';const COMMANDBAR_DISPLAY_NAME='CommandBar';const COMSCORE_DISPLAY_NAME='Comscore';const CONVERTFLOW_DISPLAY_NAME='Convertflow';const CRITEO_DISPLAY_NAME='Criteo';const CUSTOMERIO_DISPLAY_NAME='Customer IO';const DCM_FLOODLIGHT_DISPLAY_NAME='DCM Floodlight';const DRIP_DISPLAY_NAME='Drip';const ENGAGE_DISPLAY_NAME='Engage';const FACEBOOK_PIXEL_DISPLAY_NAME='Facebook Pixel';const FULLSTORY_DISPLAY_NAME='Fullstory';const GA_DISPLAY_NAME='Google Analytics';const GA360_DISPLAY_NAME='Google Analytics 360';const GA4_DISPLAY_NAME='Google Analytics 4 (GA4)';const GA4_V2_DISPLAY_NAME='Google Analytics 4 (GA4) V2';const GAINSIGHT_PX_DISPLAY_NAME='Gainsight PX';const GOOGLE_OPTIMIZE_DISPLAY_NAME='Google Optimize';const GOOGLEADS_DISPLAY_NAME='Google Ads';const GTM_DISPLAY_NAME='Google Tag Manager';const HEAP_DISPLAY_NAME='Heap.io';const HOTJAR_DISPLAY_NAME='Hotjar';const HS_DISPLAY_NAME='HubSpot';const INTERCOM_DISPLAY_NAME='Intercom';const ITERABLE_DISPLAY_NAME='Iterable';const JUNE_DISPLAY_NAME='JUNE';const KEEN_DISPLAY_NAME='Keen';const KISSMETRICS_DISPLAY_NAME='Kiss Metrics';const KLAVIYO_DISPLAY_NAME='Klaviyo';const LAUNCHDARKLY_DISPLAY_NAME='LaunchDarkly';const LEMNISK_DISPLAY_NAME='Lemnisk Marketing Automation';const LINKEDIN_INSIGHT_TAG_DISPLAY_NAME='Linkedin Insight Tag';const LIVECHAT_DISPLAY_NAME='livechat';const LOTAME_DISPLAY_NAME='Lotame';const LYTICS_DISPLAY_NAME='Lytics';const MATOMO_DISPLAY_NAME='Matomo';const MICROSOFT_CLARITY_DISPLAY_NAME='Microsoft Clarity';const MOENGAGE_DISPLAY_NAME='MoEngage';const MOUSEFLOW_DISPLAY_NAME='Mouseflow';const MP_DISPLAY_NAME='Mixpanel';const NINETAILED_DISPLAY_NAME='Ninetailed';const OLARK_DISPLAY_NAME='Olark';const OPENAI_ADS_DISPLAY_NAME='OpenAI Ads';const OPTIMIZELY_DISPLAY_NAME='Optimizely Web';const PENDO_DISPLAY_NAME='Pendo';const PINTEREST_TAG_DISPLAY_NAME='Pinterest Tag';const PODSIGHTS_DISPLAY_NAME='Podsights';const POST_AFFILIATE_PRO_DISPLAY_NAME='Post Affiliate Pro';const POSTHOG_DISPLAY_NAME='PostHog';const PROFITWELL_DISPLAY_NAME='ProfitWell';const QUALAROO_DISPLAY_NAME='Qualaroo';const QUALTRICS_DISPLAY_NAME='Qualtrics';const QUANTUMMETRIC_DISPLAY_NAME='Quantum Metric';const QUORA_PIXEL_DISPLAY_NAME='Quora Pixel';const REDDIT_PIXEL_DISPLAY_NAME='Reddit Pixel';const REFINER_DISPLAY_NAME='Refiner';const ROCKERBOX_DISPLAY_NAME='Rockerbox';const ROLLBAR_DISPLAY_NAME='rollbar';const SATISMETER_DISPLAY_NAME='SatisMeter';const SENDINBLUE_DISPLAY_NAME='Sendinblue';const SENTRY_DISPLAY_NAME='Sentry';const SHYNET_DISPLAY_NAME='Shynet';const SNAP_PIXEL_DISPLAY_NAME='Snap Pixel';const SNAPENGAGE_DISPLAY_NAME='SnapEngage';const SPOTIFYPIXEL_DISPLAY_NAME='Spotify Pixel';const SPRIG_DISPLAY_NAME='Sprig';const TIKTOK_ADS_DISPLAY_NAME='TikTok Ads';const TVSQUARED_DISPLAY_NAME='TVSquared';const USERPILOT_DISPLAY_NAME='Userpilot';const VERO_DISPLAY_NAME='Vero';const VWO_DISPLAY_NAME='VWO';const WOOPRA_DISPLAY_NAME='WOOPRA';const XPIXEL_DISPLAY_NAME='XPixel';const YANDEX_METRICA_DISPLAY_NAME='Yandex.Metrica';
|
|
1164
1262
|
|
|
@@ -1338,24 +1436,24 @@ const destDisplayNamesToFileNamesMap={[HS_DISPLAY_NAME]:DIR_NAME$1i,[GA_DISPLAY_
|
|
|
1338
1436
|
* @param sdkTypeName The name of the destination SDK type
|
|
1339
1437
|
* @param logger Logger instance
|
|
1340
1438
|
* @returns true if the destination SDK code is evaluated, false otherwise
|
|
1341
|
-
*/const isDestinationSDKMounted=(destSDKIdentifier,sdkTypeName,logger)=>Boolean(globalThis[destSDKIdentifier]
|
|
1439
|
+
*/const isDestinationSDKMounted=(destSDKIdentifier,sdkTypeName,logger)=>{var _destSDKIdentifier;return Boolean(((_destSDKIdentifier=globalThis[destSDKIdentifier])===null||_destSDKIdentifier===void 0||(_destSDKIdentifier=_destSDKIdentifier[sdkTypeName])===null||_destSDKIdentifier===void 0?void 0:_destSDKIdentifier.prototype)&&typeof globalThis[destSDKIdentifier][sdkTypeName].prototype.constructor!=='undefined');};const wait=time=>new Promise(resolve=>{globalThis.setTimeout(resolve,time);});const createIntegrationInstance=(destSDKIdentifier,sdkTypeName,dest,state)=>{var _state$consents$postC,_state$consents$postC2;const analyticsInstance=_objectSpread2({loadIntegration:state.nativeDestinations.loadIntegration.value,logLevel:state.lifecycle.logLevel.value,loadOnlyIntegrations:(_state$consents$postC=(_state$consents$postC2=state.consents.postConsent.value)===null||_state$consents$postC2===void 0?void 0:_state$consents$postC2.integrations)!==null&&_state$consents$postC!==void 0?_state$consents$postC:state.nativeDestinations.loadOnlyIntegrations.value},state.lifecycle.safeAnalyticsInstance.value);const integration=new globalThis[destSDKIdentifier][sdkTypeName](clone(dest.config),analyticsInstance,{shouldApplyDeviceModeTransformation:dest.shouldApplyDeviceModeTransformation,propagateEventsUntransformedOnError:dest.propagateEventsUntransformedOnError,destinationId:dest.id});return integration;};const isDestinationReady=(dest,time=0)=>new Promise((resolve,reject)=>{var _dest$integration;if((_dest$integration=dest.integration)!==null&&_dest$integration!==void 0&&_dest$integration.isReady()){resolve(true);}else if(time>=READY_CHECK_TIMEOUT_MS){reject(new Error(INTEGRATION_READY_TIMEOUT_ERROR(READY_CHECK_TIMEOUT_MS)));}else {const curTime=Date.now();wait(READY_CHECK_INTERVAL_MS).then(()=>{const elapsedTime=Date.now()-curTime;isDestinationReady(dest,time+elapsedTime).then(resolve).catch(err=>reject(err));});}});/**
|
|
1342
1440
|
* Extracts the integration config, if any, from the given destination
|
|
1343
1441
|
* and merges it with the current integrations config
|
|
1344
1442
|
* @param dest Destination object
|
|
1345
1443
|
* @param curDestIntgConfig Current destinations integration config
|
|
1346
1444
|
* @param logger Logger object
|
|
1347
1445
|
* @returns Combined destinations integrations config
|
|
1348
|
-
*/const getCumulativeIntegrationsConfig=(dest,curDestIntgConfig,errorHandler)=>{let integrationsConfig=curDestIntgConfig;if(isFunction(dest.integration
|
|
1349
|
-
if(isHybridModeDestination(initializedDestination)){state.nativeDestinations.integrationsConfig.value=getCumulativeIntegrationsConfig(initializedDestination,state.nativeDestinations.integrationsConfig.value,errorHandler);}state.nativeDestinations.initializedDestinations.value=[...state.nativeDestinations.initializedDestinations.value,initializedDestination];}).catch(err=>{state.nativeDestinations.failedDestinations.value=[...state.nativeDestinations.failedDestinations.value,dest];errorHandler
|
|
1446
|
+
*/const getCumulativeIntegrationsConfig=(dest,curDestIntgConfig,errorHandler)=>{var _dest$integration2;let integrationsConfig=curDestIntgConfig;if(isFunction((_dest$integration2=dest.integration)===null||_dest$integration2===void 0?void 0:_dest$integration2.getDataForIntegrationsObject)){try{integrationsConfig=_objectSpread2(_objectSpread2({},curDestIntgConfig),getSanitizedValue(dest.integration.getDataForIntegrationsObject()));}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:DEVICE_MODE_DESTINATIONS_PLUGIN,customMessage:INTEGRATIONS_DATA_ERROR(dest.userFriendlyId),groupingHash:INTEGRATIONS_DATA_ERROR(dest.displayName),category:INTEGRATIONS_ERROR_CATEGORY});}}return integrationsConfig;};const initializeDestination=(dest,state,destSDKIdentifier,sdkTypeName,errorHandler,logger)=>{try{var _integration$init,_integration;const initializedDestination=clone(dest);let integration=initializedDestination.integration;if(isUndefined(integration)){integration=createIntegrationInstance(destSDKIdentifier,sdkTypeName,dest,state);initializedDestination.integration=integration;}(_integration$init=(_integration=integration).init)===null||_integration$init===void 0||_integration$init.call(_integration);isDestinationReady(initializedDestination).then(()=>{// Collect the integrations data for the hybrid mode destinations
|
|
1447
|
+
if(isHybridModeDestination(initializedDestination)){state.nativeDestinations.integrationsConfig.value=getCumulativeIntegrationsConfig(initializedDestination,state.nativeDestinations.integrationsConfig.value,errorHandler);}state.nativeDestinations.initializedDestinations.value=[...state.nativeDestinations.initializedDestinations.value,initializedDestination];}).catch(err=>{state.nativeDestinations.failedDestinations.value=[...state.nativeDestinations.failedDestinations.value,dest];errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:DEVICE_MODE_DESTINATIONS_PLUGIN,customMessage:INTEGRATION_READY_CHECK_ERROR(dest.userFriendlyId),groupingHash:INTEGRATION_READY_CHECK_ERROR(dest.displayName),category:INTEGRATIONS_ERROR_CATEGORY});});}catch(err){state.nativeDestinations.failedDestinations.value=[...state.nativeDestinations.failedDestinations.value,dest];errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:DEVICE_MODE_DESTINATIONS_PLUGIN,customMessage:INTEGRATION_INIT_ERROR(dest.userFriendlyId),groupingHash:INTEGRATION_INIT_ERROR(dest.displayName),category:INTEGRATIONS_ERROR_CATEGORY});}};/**
|
|
1350
1448
|
* Applies source configuration overrides to destinations
|
|
1351
1449
|
* @param destinations Array of destinations to process
|
|
1352
1450
|
* @param sourceConfigOverride Source configuration override options
|
|
1353
1451
|
* @param logger Logger instance for warnings
|
|
1354
1452
|
* @returns Array of destinations with overrides applied
|
|
1355
|
-
*/const applySourceConfigurationOverrides=(destinations,sourceConfigOverride,logger)=>{if(!sourceConfigOverride
|
|
1453
|
+
*/const applySourceConfigurationOverrides=(destinations,sourceConfigOverride,logger)=>{var _sourceConfigOverride;if(!(sourceConfigOverride!==null&&sourceConfigOverride!==void 0&&(_sourceConfigOverride=sourceConfigOverride.destinations)!==null&&_sourceConfigOverride!==void 0&&_sourceConfigOverride.length)){return filterDisabledDestinations(destinations);}const destIds=destinations.map(dest=>dest.id);// Group overrides by destination ID to support future cloning
|
|
1356
1454
|
// When cloning is implemented, multiple overrides with same ID will create multiple destination instances
|
|
1357
1455
|
const overridesByDestId={};sourceConfigOverride.destinations.forEach(override=>{const existing=overridesByDestId[override.id]||[];existing.push(override);overridesByDestId[override.id]=existing;});// Find unmatched destination IDs and log warning
|
|
1358
|
-
const unmatchedIds=Object.keys(overridesByDestId).filter(id=>!destIds.includes(id));if(unmatchedIds.length>0){logger
|
|
1456
|
+
const unmatchedIds=Object.keys(overridesByDestId).filter(id=>!destIds.includes(id));if(unmatchedIds.length>0){logger===null||logger===void 0||logger.warn(`${DEVICE_MODE_DESTINATIONS_PLUGIN}:: Source configuration override - Unable to identify the destinations with the following IDs: "${unmatchedIds.join(', ')}"`);}// Process overrides and apply them to destinations
|
|
1359
1457
|
const processedDestinations=[];destinations.forEach(dest=>{const overrides=overridesByDestId[dest.id];if(!overrides||overrides.length===0){// No override for this destination, keep original
|
|
1360
1458
|
processedDestinations.push(dest);return;}if(overrides.length>1){// Multiple overrides for the same destination, create clones
|
|
1361
1459
|
overrides.forEach((override,index)=>{const overriddenDestination=applyOverrideToDestination(dest,override,`${index+1}`);overriddenDestination.cloned=true;overriddenDestination.originalId=dest.id;processedDestinations.push(overriddenDestination);});}else {const overriddenDestination=applyOverrideToDestination(dest,overrides[0]);processedDestinations.push(overriddenDestination);}});return filterDisabledDestinations(processedDestinations);};/**
|
|
@@ -1379,7 +1477,7 @@ const clonedDest=clone(destination);if(cloneId){clonedDest.id=`${destination.id}
|
|
|
1379
1477
|
if(isEnabledStatusChanged){clonedDest.enabled=override.enabled;// Mark as overridden
|
|
1380
1478
|
clonedDest.overridden=true;}// Apply config overrides if provided for enabled destination
|
|
1381
1479
|
if(willApplyConfig){// Override the config with the new config and remove undefined and null values
|
|
1382
|
-
clonedDest.config=removeUndefinedAndNullValues({
|
|
1480
|
+
clonedDest.config=removeUndefinedAndNullValues(_objectSpread2(_objectSpread2({},clonedDest.config),override.config));clonedDest.overridden=true;}return clonedDest;};/**
|
|
1383
1481
|
* Validates if the destination ID and custom integration are valid
|
|
1384
1482
|
* @param destinationId - The destination ID to validate
|
|
1385
1483
|
* @param integration - The custom integration instance
|
|
@@ -1404,19 +1502,19 @@ const safeLogger={log:integrationLogger.log.bind(integrationLogger),info:integra
|
|
|
1404
1502
|
// to pass to the init method
|
|
1405
1503
|
const customDestinationConfig=clone(destination.config);// Create a wrapper around the custom integration APIs
|
|
1406
1504
|
// to make them consistent with the standard device mode integrations
|
|
1407
|
-
destination.integration={
|
|
1505
|
+
destination.integration=_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({},integration.init&&{init:()=>integration.init(customDestinationConfig,analyticsInstance,safeLogger)}),integration.track&&{track:event=>integration.track(analyticsInstance,safeLogger,event)}),integration.page&&{page:event=>integration.page(analyticsInstance,safeLogger,event)}),integration.identify&&{identify:event=>integration.identify(analyticsInstance,safeLogger,event)}),integration.group&&{group:event=>integration.group(analyticsInstance,safeLogger,event)}),integration.alias&&{alias:event=>integration.alias(analyticsInstance,safeLogger,event)}),{},{isReady:()=>integration.isReady(analyticsInstance,safeLogger)});};
|
|
1408
1506
|
|
|
1409
1507
|
const pluginName$b='DeviceModeDestinations';const DeviceModeDestinations=()=>({name:pluginName$b,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$b];},nativeDestinations:{addCustomIntegration(destinationId,integration,state,logger){const destination=validateCustomIntegration(destinationId,integration,state,logger);if(!destination){return;}addIntegrationToDestination(destination,integration,state,logger);// Refresh the state value to trigger any effects that depend on it
|
|
1410
|
-
state.nativeDestinations.configuredDestinations.value=[...state.nativeDestinations.configuredDestinations.value];},setActiveDestinations(state,pluginsManager,errorHandler,logger){state.nativeDestinations.loadIntegration.value=state.loadOptions.value.loadIntegration;// Filter destination that doesn't have mapping config-->Integration names
|
|
1508
|
+
state.nativeDestinations.configuredDestinations.value=[...state.nativeDestinations.configuredDestinations.value];},setActiveDestinations(state,pluginsManager,errorHandler,logger){var _state$consents$postC,_state$consents$postC2;state.nativeDestinations.loadIntegration.value=state.loadOptions.value.loadIntegration;// Filter destination that doesn't have mapping config-->Integration names
|
|
1411
1509
|
const configSupportedDestinations=state.nativeDestinations.configuredDestinations.value.filter(configDest=>{// Filter enabled or disabled custom destinations that don't have an integration added to them
|
|
1412
|
-
if(configDest.isCustomIntegration&&isUndefined(configDest.integration)){if(configDest.enabled){logger
|
|
1510
|
+
if(configDest.isCustomIntegration&&isUndefined(configDest.integration)){if(configDest.enabled){logger===null||logger===void 0||logger.warn(INTEGRATION_NOT_ADDED_TO_CUSTOM_DESTINATION_WARNING(DEVICE_MODE_DESTINATIONS_PLUGIN,configDest.id));}return false;}// Ensure the destination is supported by the SDK
|
|
1413
1511
|
// or it is a custom integration
|
|
1414
|
-
if(configDest.isCustomIntegration||destDisplayNamesToFileNamesMap[configDest.displayName]){return true;}const errMessage=INTEGRATION_NOT_SUPPORTED_ERROR(configDest.displayName);errorHandler
|
|
1512
|
+
if(configDest.isCustomIntegration||destDisplayNamesToFileNamesMap[configDest.displayName]){return true;}const errMessage=INTEGRATION_NOT_SUPPORTED_ERROR(configDest.displayName);errorHandler===null||errorHandler===void 0||errorHandler.onError({error:new Error(errMessage),context:DEVICE_MODE_DESTINATIONS_PLUGIN,category:INTEGRATIONS_ERROR_CATEGORY});return false;});// Apply source configuration overrides if provided
|
|
1415
1513
|
const configuredDestinations=state.loadOptions.value.sourceConfigurationOverride?applySourceConfigurationOverrides(configSupportedDestinations,state.loadOptions.value.sourceConfigurationOverride,logger):filterDisabledDestinations(configSupportedDestinations);// Filter destinations that are disabled through load or consent API options
|
|
1416
|
-
const destinationsToLoad=filterDestinations(state.consents.postConsent.value
|
|
1417
|
-
pluginsManager.invokeSingle(`consentManager.isDestinationConsented`,state,dest.config,errorHandler,logger)
|
|
1514
|
+
const destinationsToLoad=filterDestinations((_state$consents$postC=(_state$consents$postC2=state.consents.postConsent.value)===null||_state$consents$postC2===void 0?void 0:_state$consents$postC2.integrations)!==null&&_state$consents$postC!==void 0?_state$consents$postC:state.nativeDestinations.loadOnlyIntegrations.value,configuredDestinations);const consentedDestinations=destinationsToLoad.filter(dest=>{var _pluginsManager$invok;return(// if consent manager is not configured, then default to load the destination
|
|
1515
|
+
(_pluginsManager$invok=pluginsManager.invokeSingle(`consentManager.isDestinationConsented`,state,dest.config,errorHandler,logger))!==null&&_pluginsManager$invok!==void 0?_pluginsManager$invok:true);});// Add the distilled destinations to the active destinations list
|
|
1418
1516
|
state.nativeDestinations.activeDestinations.value=[...state.nativeDestinations.activeDestinations.value,...consentedDestinations];},load(state,externalSrcLoader,errorHandler,logger,externalScriptOnLoad){const integrationsCDNPath=state.lifecycle.integrationsCDNPath.value;const activeDestinations=state.nativeDestinations.activeDestinations.value;activeDestinations.forEach(dest=>{const sdkName=destDisplayNamesToFileNamesMap[dest.displayName];const destSDKIdentifier=`${sdkName}_RS`;// this is the name of the object loaded on the window
|
|
1419
|
-
const sdkTypeName=sdkName;if(sdkTypeName&&!isDestinationSDKMounted(destSDKIdentifier,sdkTypeName)){const destSdkURL=`${integrationsCDNPath}/${sdkName}.min.js`;externalSrcLoader.loadJSFile({url:destSdkURL,id:dest.userFriendlyId,callback:externalScriptOnLoad
|
|
1517
|
+
const sdkTypeName=sdkName;if(sdkTypeName&&!isDestinationSDKMounted(destSDKIdentifier,sdkTypeName)){const destSdkURL=`${integrationsCDNPath}/${sdkName}.min.js`;externalSrcLoader.loadJSFile({url:destSdkURL,id:dest.userFriendlyId,callback:externalScriptOnLoad!==null&&externalScriptOnLoad!==void 0?externalScriptOnLoad:(id,err)=>{if(err){const customMessage=INTEGRATION_SDK_LOAD_ERROR(dest.displayName);errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:DEVICE_MODE_DESTINATIONS_PLUGIN,customMessage,groupingHash:customMessage,category:INTEGRATIONS_ERROR_CATEGORY});state.nativeDestinations.failedDestinations.value=[...state.nativeDestinations.failedDestinations.value,dest];}else {initializeDestination(dest,state,destSDKIdentifier,sdkTypeName,errorHandler);}},timeout:SCRIPT_LOAD_TIMEOUT_MS});}else {initializeDestination(dest,state,destSDKIdentifier,sdkTypeName,errorHandler);}});}}});
|
|
1420
1518
|
|
|
1421
1519
|
const DEFAULT_TRANSFORMATION_QUEUE_OPTIONS={minRetryDelay:500,backoffFactor:2,maxAttempts:3};const REQUEST_TIMEOUT_MS$1=10*1000;// 10 seconds
|
|
1422
1520
|
const QUEUE_NAME$2='rudder_dmt';const DMT_PLUGIN='DeviceModeTransformationPlugin';
|
|
@@ -1429,16 +1527,16 @@ const DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR=(context,displayName,id,reason,actio
|
|
|
1429
1527
|
*
|
|
1430
1528
|
*/const createPayload=(event,destinationIds,token)=>{const orderNo=Date.now();const payload={metadata:{'Custom-Authorization':token},batch:[{orderNo,destinationIds,event}]};return payload;};/**
|
|
1431
1529
|
* Helper function to get destination identifier consistently
|
|
1432
|
-
*/const getDestinationId=dest=>dest.originalId
|
|
1530
|
+
*/const getDestinationId=dest=>{var _dest$originalId;return (_dest$originalId=dest.originalId)!==null&&_dest$originalId!==void 0?_dest$originalId:dest.id;};/**
|
|
1433
1531
|
* Helper function to log once per destination to avoid duplicate messages
|
|
1434
1532
|
*/const logOncePerDestination=(destinationId,loggedDestinations,logFn)=>{if(!loggedDestinations.includes(destinationId)){loggedDestinations.push(destinationId);logFn();}};const sendTransformedEventToDestinations=(state,pluginsManager,destinationIds,result,status,event,errorHandler,logger)=>{const NATIVE_DEST_EXT_POINT='destinationsEventsQueue.enqueueEventToDestination';const ACTION_TO_SEND_UNTRANSFORMED_EVENT='Sending untransformed event';const ACTION_TO_DROP_EVENT='Dropping the event';// Items that don't carry destination IDs don't belong to this queue
|
|
1435
1533
|
// and cannot be delivered to any destination
|
|
1436
|
-
if(!Array.isArray(destinationIds)){const errMessage=DMT_INVALID_DESTINATION_IDS_ERROR(ACTION_TO_DROP_EVENT);errorHandler
|
|
1437
|
-
case 404:{logOncePerDestination(destinationId,loggedDestinations,()=>{logger
|
|
1534
|
+
if(!Array.isArray(destinationIds)){const errMessage=DMT_INVALID_DESTINATION_IDS_ERROR(ACTION_TO_DROP_EVENT);errorHandler===null||errorHandler===void 0||errorHandler.onError({error:new Error(errMessage),context:DMT_PLUGIN,customMessage:errMessage});return;}const destinations=state.nativeDestinations.initializedDestinations.value.filter(d=>d&&destinationIds.includes(getDestinationId(d)));const loggedDestinations=[];destinations.forEach(dest=>{try{const eventsToSend=[];const destinationId=getDestinationId(dest);switch(status){case 200:{const response=JSON.parse(result);const destTransformedResult=response.transformedBatch.find(e=>e.id===destinationId);destTransformedResult===null||destTransformedResult===void 0||destTransformedResult.payload.forEach(tEvent=>{if(tEvent.status==='200'){eventsToSend.push(tEvent.event);}else {let reason='Unknown';if(tEvent.status==='410'){reason='Transformation is not available';}let action=ACTION_TO_DROP_EVENT;if(dest.propagateEventsUntransformedOnError===true){action=ACTION_TO_SEND_UNTRANSFORMED_EVENT;eventsToSend.push(event);logOncePerDestination(destinationId,loggedDestinations,()=>{logger===null||logger===void 0||logger.warn(DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR(DMT_PLUGIN,dest.displayName,destinationId,reason,action));});}else {logOncePerDestination(destinationId,loggedDestinations,()=>{logger===null||logger===void 0||logger.error(DMT_TRANSFORMATION_UNSUCCESSFUL_ERROR(DMT_PLUGIN,dest.displayName,destinationId,reason,action));});}}});break;}// Transformation server access denied
|
|
1535
|
+
case 404:{logOncePerDestination(destinationId,loggedDestinations,()=>{logger===null||logger===void 0||logger.warn(DMT_SERVER_ACCESS_DENIED_WARNING(DMT_PLUGIN));});eventsToSend.push(event);break;}default:{if(dest.propagateEventsUntransformedOnError===true){logOncePerDestination(destinationId,loggedDestinations,()=>{logger===null||logger===void 0||logger.warn(DMT_REQUEST_FAILED_ERROR(DMT_PLUGIN,dest.displayName,destinationId,status,ACTION_TO_SEND_UNTRANSFORMED_EVENT));});eventsToSend.push(event);}else {logOncePerDestination(destinationId,loggedDestinations,()=>{logger===null||logger===void 0||logger.error(DMT_REQUEST_FAILED_ERROR(DMT_PLUGIN,dest.displayName,destinationId,status,ACTION_TO_DROP_EVENT));});}break;}}eventsToSend===null||eventsToSend===void 0||eventsToSend.forEach(tEvent=>{if(isNonEmptyObject(tEvent)){pluginsManager.invokeSingle(NATIVE_DEST_EXT_POINT,state,tEvent,dest,errorHandler,logger);}});}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:DMT_PLUGIN,customMessage:DMT_EXCEPTION(dest.displayName,dest.id)});}});};
|
|
1438
1536
|
|
|
1439
1537
|
const pluginName$a='DeviceModeTransformation';const DeviceModeTransformation=()=>({name:pluginName$a,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$a];},transformEvent:{init(state,pluginsManager,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;httpClient.setAuthHeader(writeKey);const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
|
1440
|
-
`${QUEUE_NAME$2}_${writeKey}`,DEFAULT_TRANSFORMATION_QUEUE_OPTIONS,(item,done,qItemProcessInfo)=>{const payload=createPayload(item.event,item.destinationIds,item.token);httpClient.getAsyncData({url:`${state.lifecycle.activeDataplaneUrl.value}/transform`,options:{method:'POST',data:getDMTDeliveryPayload(payload),sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS$1,callback:(result,details)=>{const isRetryable=isErrRetryable(details
|
|
1441
|
-
if(isUndefined(details
|
|
1538
|
+
`${QUEUE_NAME$2}_${writeKey}`,DEFAULT_TRANSFORMATION_QUEUE_OPTIONS,(item,done,qItemProcessInfo)=>{const payload=createPayload(item.event,item.destinationIds,item.token);httpClient.getAsyncData({url:`${state.lifecycle.activeDataplaneUrl.value}/transform`,options:{method:'POST',data:getDMTDeliveryPayload(payload),sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS$1,callback:(result,details)=>{var _details$xhr$status,_details$xhr;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);// If there is no error, or the error is not retryable, or the attempt number is the max retry attempts, then attempt send the event to the destinations
|
|
1539
|
+
if(isUndefined(details===null||details===void 0?void 0:details.error)||!isRetryable||qItemProcessInfo.retryAttemptNumber===qItemProcessInfo.maxRetryAttempts){var _details$xhr2;sendTransformedEventToDestinations(state,pluginsManager,item.destinationIds,result,details===null||details===void 0||(_details$xhr2=details.xhr)===null||_details$xhr2===void 0?void 0:_details$xhr2.status,item.event,errorHandler,logger);done(null);}else {// Requeue the item as the error is retryable.
|
|
1442
1540
|
done(details);}}});},storeManager,MEMORY_STORAGE);return eventsQueue;},enqueue(state,eventsQueue,event,destinations){// Collect unique destination IDs for transformation
|
|
1443
1541
|
// For cloned destinations, getDestinationId returns originalId to ensure uniqueness
|
|
1444
1542
|
const destinationIds=[];destinations.forEach(d=>{const id=getDestinationId(d);if(!destinationIds.includes(id)){destinationIds.push(id);}});eventsQueue.addItem({event,destinationIds,token:state.session.authToken.value});}}});
|
|
@@ -1448,10 +1546,10 @@ const externallyLoadedSessionStorageKeys={segment:'ajs_anonymous_id'};
|
|
|
1448
1546
|
const getSegmentAnonymousId=getStorageEngine=>{let anonymousId;/**
|
|
1449
1547
|
* First check the local storage for anonymousId
|
|
1450
1548
|
* Ref: https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/#identify
|
|
1451
|
-
*/const lsEngine=getStorageEngine(LOCAL_STORAGE);if(lsEngine
|
|
1452
|
-
const csEngine=getStorageEngine(COOKIE_STORAGE);if(!anonymousId&&csEngine
|
|
1549
|
+
*/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
|
|
1550
|
+
const csEngine=getStorageEngine(COOKIE_STORAGE);if(!anonymousId&&csEngine!==null&&csEngine!==void 0&&csEngine.isEnabled){anonymousId=csEngine.getItem(externallyLoadedSessionStorageKeys.segment);}return anonymousId;};
|
|
1453
1551
|
|
|
1454
|
-
const pluginName$9='ExternalAnonymousId';const ExternalAnonymousId=()=>({name:pluginName$9,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$9];},storage:{getAnonymousId(getStorageEngine,options){let anonymousId;if(options
|
|
1552
|
+
const pluginName$9='ExternalAnonymousId';const ExternalAnonymousId=()=>({name:pluginName$9,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$9];},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
|
|
1455
1553
|
switch(source){case 'segment':anonymousId=getSegmentAnonymousId(getStorageEngine);break;}}return anonymousId;}}});
|
|
1456
1554
|
|
|
1457
1555
|
const AMP_LINKER_ANONYMOUS_ID_KEY='rs_amp_id';
|
|
@@ -1474,9 +1572,9 @@ crc=crc>>>8^crcTable[(crc^str.charCodeAt(i))&0xff];}return (crc^-1)>>>0;};
|
|
|
1474
1572
|
* An interface to fetch user device details.
|
|
1475
1573
|
*/const USER_INTERFACE={/**
|
|
1476
1574
|
* @returns {string} user language
|
|
1477
|
-
*/getUserLanguage:()=>navigator
|
|
1575
|
+
*/getUserLanguage:()=>{var _navigator;return (_navigator=navigator)===null||_navigator===void 0?void 0:_navigator.language;},/**
|
|
1478
1576
|
* @returns {string} userAgent
|
|
1479
|
-
*/getUserAgent:()=>navigator
|
|
1577
|
+
*/getUserAgent:()=>{var _navigator2;return (_navigator2=navigator)===null||_navigator2===void 0?void 0:_navigator2.userAgent;}};
|
|
1480
1578
|
|
|
1481
1579
|
/**
|
|
1482
1580
|
* This is utility function for decoding from base 64 to utf8
|
|
@@ -1502,7 +1600,7 @@ const KEY_VALIDATOR=/^[\w.-]+$/;const CHECKSUM_OFFSET_MAX_MIN=1;const VALID_VERS
|
|
|
1502
1600
|
*/const parseLinkerParamValue=value=>{const parts=value.split(DELIMITER);const isEven=parts.length%2===0;if(parts.length<4||!isEven){// Format <version>*<checksum>*<key1>*<value1>
|
|
1503
1601
|
// Note: linker makes sure there's at least one pair of non empty key value
|
|
1504
1602
|
// Make sure there is at least three delimiters.
|
|
1505
|
-
return null;}const version=Number(parts.shift());if(version!==VALID_VERSION){return null;}const checksum=parts.shift();const serializedIds=parts.join(DELIMITER);return {checksum:checksum
|
|
1603
|
+
return null;}const version=Number(parts.shift());if(version!==VALID_VERSION){return null;}const checksum=parts.shift();const serializedIds=parts.join(DELIMITER);return {checksum:checksum!==null&&checksum!==void 0?checksum:'',serializedIds};};/**
|
|
1506
1604
|
* Deserialize the serializedIds and return keyValue pairs.
|
|
1507
1605
|
*
|
|
1508
1606
|
* @param {string} serializedIds
|
|
@@ -1551,13 +1649,13 @@ const IUBENDA_CONSENT_MANAGER_PLUGIN='IubendaConsentManagerPlugin';const IUBENDA
|
|
|
1551
1649
|
const getIubendaCookieName=logger=>{try{// Retrieve cookies as a string and split them into an array
|
|
1552
1650
|
const cookies=document.cookie.split('; ');// Find the cookie that matches the iubenda cookie pattern
|
|
1553
1651
|
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
|
|
1554
|
-
const[name]=matchedCookie.split('=');return name||'';}catch(err){logger
|
|
1652
|
+
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 '';}};/**
|
|
1555
1653
|
* Gets the consent data from the Iubenda's consent cookie
|
|
1556
1654
|
* @param storeManager Store manager instance
|
|
1557
1655
|
* @param logger Logger instance
|
|
1558
1656
|
* @returns Consent data from the consent cookie
|
|
1559
|
-
*/const getIubendaConsentData=(storeManager,logger)=>{let rawConsentCookieData=null;try{const dataStore=storeManager
|
|
1560
|
-
let consentCookieData;try{consentCookieData=JSON.parse(decodeURIComponent(rawConsentCookieData));}catch(err){logger
|
|
1657
|
+
*/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
|
|
1658
|
+
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
|
|
1561
1659
|
const consentPurposes=consentCookieData.purposes;return consentPurposes;};/**
|
|
1562
1660
|
* Gets the consent data in the format expected by the application state
|
|
1563
1661
|
* @param iubendaConsentData Consent data derived from the consent cookie
|
|
@@ -1566,18 +1664,18 @@ const consentPurposes=consentCookieData.purposes;return consentPurposes;};/**
|
|
|
1566
1664
|
|
|
1567
1665
|
const pluginName$7='IubendaConsentManager';const IubendaConsentManager=()=>({name:pluginName$7,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$7];},consentManager:{init(state,logger){// getIubendaUserConsentedPurposes returns current iubenda opted-in purposes
|
|
1568
1666
|
// This will be helpful for debugging
|
|
1569
|
-
globalThis.getIubendaUserConsentedPurposes=()=>state.consents.data.value.allowedConsentIds
|
|
1667
|
+
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
|
|
1570
1668
|
// This will be helpful for debugging
|
|
1571
|
-
globalThis.getIubendaUserDeniedPurposes=()=>state.consents.data.value.deniedConsentIds
|
|
1669
|
+
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
|
|
1572
1670
|
globalThis.updateIubendaConsent=iubendaConsentData=>{updateConsentStateFromData$1(state,iubendaConsentData);};},updateConsentsInfo(state,storeManager,logger){// retrieve consent data and update the state
|
|
1573
1671
|
let iubendaConsentData;// From window
|
|
1574
1672
|
if(!isUndefined(globalThis._iub.cs.consent.purposes)){iubendaConsentData=globalThis._iub.cs.consent.purposes;// From cookie
|
|
1575
1673
|
}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.
|
|
1576
|
-
if(consentManagement){
|
|
1674
|
+
if(consentManagement){var _cmpConfig$resolution;// Get the corresponding consents for the destination
|
|
1577
1675
|
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.
|
|
1578
|
-
if(!cmpConfig
|
|
1676
|
+
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
|
|
1579
1677
|
// the configured resolution strategy
|
|
1580
|
-
switch(resolutionStrategy){case 'or':return configuredConsents.some(matchPredicate)||configuredConsents.length===0;case 'and':default:return configuredConsents.every(matchPredicate);}}return true;}catch(err){errorHandler
|
|
1678
|
+
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;}}}});
|
|
1581
1679
|
|
|
1582
1680
|
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.`;
|
|
1583
1681
|
|
|
@@ -1589,9 +1687,9 @@ const KETCH_CONSENT_MANAGER_PLUGIN='KetchConsentManagerPlugin';const KETCH_CONSE
|
|
|
1589
1687
|
* @param logger Logger instance
|
|
1590
1688
|
* @returns Consent data from the consent cookie
|
|
1591
1689
|
*/const getKetchConsentData=(storeManager,logger)=>{let rawConsentCookieData=null;try{// Create a data store instance to read the consent cookie
|
|
1592
|
-
const dataStore=storeManager
|
|
1593
|
-
let consentCookieData;try{consentCookieData=JSON.parse(fromBase64(rawConsentCookieData));}catch(err){logger
|
|
1594
|
-
const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{const purposeCode=pEntry[0];const purposeValue=pEntry[1];consentPurposes[purposeCode]=purposeValue
|
|
1690
|
+
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
|
|
1691
|
+
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
|
|
1692
|
+
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;};/**
|
|
1595
1693
|
* Gets the consent data in the format expected by the application state
|
|
1596
1694
|
* @param ketchConsentData Consent data derived from the consent cookie
|
|
1597
1695
|
* @returns Consent data
|
|
@@ -1599,21 +1697,21 @@ const consentPurposes={};Object.entries(consentCookieData).forEach(pEntry=>{cons
|
|
|
1599
1697
|
|
|
1600
1698
|
const pluginName$6='KetchConsentManager';const KetchConsentManager=()=>({name:pluginName$6,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$6];},consentManager:{init(state,logger){// getKetchUserConsentedPurposes returns current ketch opted-in purposes
|
|
1601
1699
|
// This will be helpful for debugging
|
|
1602
|
-
globalThis.getKetchUserConsentedPurposes=()=>state.consents.data.value.allowedConsentIds
|
|
1700
|
+
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
|
|
1603
1701
|
// This will be helpful for debugging
|
|
1604
|
-
globalThis.getKetchUserDeniedPurposes=()=>state.consents.data.value.deniedConsentIds
|
|
1702
|
+
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
|
|
1605
1703
|
// this will be called from ketch rudderstack plugin
|
|
1606
1704
|
globalThis.updateKetchConsent=ketchConsentData=>{updateConsentStateFromData(state,ketchConsentData);};},updateConsentsInfo(state,storeManager,logger){// retrieve consent data and update the state
|
|
1607
1705
|
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
|
|
1608
|
-
if(consentManagement){
|
|
1609
|
-
const cmpConsents=consentManagement.find(c=>c.provider===state.consents.provider.value)
|
|
1706
|
+
if(consentManagement){var _consentManagement$fi;// Get the corresponding consents for the destination
|
|
1707
|
+
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.
|
|
1610
1708
|
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
|
|
1611
1709
|
// the configured resolution strategy
|
|
1612
1710
|
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
|
|
1613
1711
|
// TODO: To be removed once the source config API is updated to support generic consent management
|
|
1614
1712
|
}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.
|
|
1615
1713
|
return configuredConsents.some(matchPredicate)||configuredConsents.length===0;}// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1616
|
-
return true;}catch(err){errorHandler
|
|
1714
|
+
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;}}}});
|
|
1617
1715
|
|
|
1618
1716
|
const DEFAULT_QUEUE_OPTIONS={maxItems:100};const QUEUE_NAME$1='rudder_destinations_events';const NATIVE_DESTINATION_QUEUE_PLUGIN='NativeDestinationQueuePlugin';
|
|
1619
1717
|
|
|
@@ -1621,8 +1719,8 @@ const DESTINATION_EVENT_FILTERING_WARNING=(context,eventName,destUserFriendlyId)
|
|
|
1621
1719
|
|
|
1622
1720
|
const getNormalizedQueueOptions$1=queueOpts=>mergeDeepRight(DEFAULT_QUEUE_OPTIONS,queueOpts);const isValidEventName=eventName=>eventName&&typeof eventName==='string';const isEventDenyListed=(eventType,eventName,dest)=>{if(eventType!=='track'){return false;}const{blacklistedEvents,whitelistedEvents,eventFilteringOption}=dest.config;switch(eventFilteringOption){// Blacklist is chosen for filtering events
|
|
1623
1721
|
case 'blacklistedEvents':{if(!isValidEventName(eventName)){return false;}const trimmedEventName=eventName.trim();if(Array.isArray(blacklistedEvents)){return blacklistedEvents.some(eventObj=>eventObj.eventName.trim()===trimmedEventName);}return false;}// Whitelist is chosen for filtering events
|
|
1624
|
-
case 'whitelistedEvents':{if(!isValidEventName(eventName)){return true;}const trimmedEventName=eventName.trim();if(Array.isArray(whitelistedEvents)){return !whitelistedEvents.some(eventObj=>eventObj.eventName.trim()===trimmedEventName);}return true;}case 'disable':default:return false;}};const sendEventToDestination=(item,dest,errorHandler,logger)=>{const methodName=item.type.toString();try{
|
|
1625
|
-
const integrationEvent={message:item};dest.integration[methodName]
|
|
1722
|
+
case 'whitelistedEvents':{if(!isValidEventName(eventName)){return true;}const trimmedEventName=eventName.trim();if(Array.isArray(whitelistedEvents)){return !whitelistedEvents.some(eventObj=>eventObj.eventName.trim()===trimmedEventName);}return true;}case 'disable':default:return false;}};const sendEventToDestination=(item,dest,errorHandler,logger)=>{const methodName=item.type.toString();try{var _ref,_ref2;// Destinations expect the event to be wrapped under the `message` key
|
|
1723
|
+
const integrationEvent={message:item};(_ref=(_ref2=dest.integration)[methodName])===null||_ref===void 0||_ref.call(_ref2,integrationEvent);}catch(err){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:NATIVE_DESTINATION_QUEUE_PLUGIN,customMessage:INTEGRATION_EVENT_FORWARDING_ERROR(methodName,dest.userFriendlyId,item.event),groupingHash:INTEGRATION_EVENT_FORWARDING_ERROR(methodName,dest.displayName,item.event),category:INTEGRATIONS_ERROR_CATEGORY});}};/**
|
|
1626
1724
|
* A function to check if device mode transformation should be applied for a destination.
|
|
1627
1725
|
* @param dest Destination object
|
|
1628
1726
|
* @returns Boolean indicating whether the transformation should be applied
|
|
@@ -1638,7 +1736,7 @@ const pluginName$5='NativeDestinationQueue';const NativeDestinationQueue=()=>({n
|
|
|
1638
1736
|
* @returns IQueue instance
|
|
1639
1737
|
*/init(state,pluginsManager,storeManager,dmtQueue,errorHandler,logger){const finalQOpts=getNormalizedQueueOptions$1(state.loadOptions.value.destinationsQueueOptions);const writeKey=state.lifecycle.writeKey.value;const eventsQueue=new RetryQueue(// adding write key to the queue name to avoid conflicts
|
|
1640
1738
|
`${QUEUE_NAME$1}_${writeKey}`,finalQOpts,(rudderEvent,done)=>{const destinationsToSend=filterDestinations(rudderEvent.integrations,state.nativeDestinations.initializedDestinations.value);// list of destinations which are enable for DMT
|
|
1641
|
-
const destWithTransformationEnabled=[];const clonedRudderEvent=clone(rudderEvent);destinationsToSend.forEach(dest=>{try{const sendEvent=!isEventDenyListed(clonedRudderEvent.type,clonedRudderEvent.event,dest);if(!sendEvent){logger
|
|
1739
|
+
const destWithTransformationEnabled=[];const clonedRudderEvent=clone(rudderEvent);destinationsToSend.forEach(dest=>{try{const sendEvent=!isEventDenyListed(clonedRudderEvent.type,clonedRudderEvent.event,dest);if(!sendEvent){logger===null||logger===void 0||logger.warn(DESTINATION_EVENT_FILTERING_WARNING(NATIVE_DESTINATION_QUEUE_PLUGIN,clonedRudderEvent.event,dest.userFriendlyId));return;}if(shouldApplyTransformation(dest)){destWithTransformationEnabled.push(dest);}else {sendEventToDestination(clonedRudderEvent,dest,errorHandler,logger);}}catch(e){errorHandler===null||errorHandler===void 0||errorHandler.onError({error:e,context:NATIVE_DESTINATION_QUEUE_PLUGIN,category:INTEGRATIONS_ERROR_CATEGORY});}});if(destWithTransformationEnabled.length>0){pluginsManager.invokeSingle('transformEvent.enqueue',state,dmtQueue,clonedRudderEvent,destWithTransformationEnabled,errorHandler,logger);}// Mark success always
|
|
1642
1740
|
done(null);},storeManager,MEMORY_STORAGE);// TODO: This seems to not work as expected. Need to investigate
|
|
1643
1741
|
// effect(() => {
|
|
1644
1742
|
// if (state.nativeDestinations.clientDestinationsReady.value === true) {
|
|
@@ -1667,15 +1765,15 @@ const ONETRUST_ACCESS_ERROR=context=>`${context}${LOG_CONTEXT_SEPARATOR}Failed t
|
|
|
1667
1765
|
const ONETRUST_CONSENT_MANAGER_PLUGIN='OneTrustConsentManagerPlugin';
|
|
1668
1766
|
|
|
1669
1767
|
const pluginName$4='OneTrustConsentManager';const OneTrustConsentManager=()=>({name:pluginName$4,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$4];},consentManager:{init(state,logger){// Nothing to initialize
|
|
1670
|
-
},updateConsentsInfo(state,storeManager,logger){if(!globalThis.OneTrust||!globalThis.OnetrustActiveGroups){logger
|
|
1768
|
+
},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.
|
|
1671
1769
|
const oneTrustAllGroupsInfo=globalThis.OneTrust.GetDomainData().Groups;// OneTrustConsentManager SDK populates a data layer object OnetrustActiveGroups with
|
|
1672
1770
|
// the cookie categories Ids that the user has consented to.
|
|
1673
1771
|
// Eg: ',C0001,C0003,'
|
|
1674
1772
|
// We split it and save it as an array.
|
|
1675
1773
|
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
|
|
1676
1774
|
const{oneTrustCookieCategories,consentManagement}=destConfig;const matchPredicate=consent=>allowedConsentIds.includes(consent);// Generic consent management
|
|
1677
|
-
if(consentManagement){
|
|
1678
|
-
const cmpConsents=consentManagement.find(c=>c.provider===state.consents.provider.value)
|
|
1775
|
+
if(consentManagement){var _consentManagement$fi;// Get the corresponding consents for the destination
|
|
1776
|
+
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.
|
|
1679
1777
|
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
|
|
1680
1778
|
// the configured resolution strategy
|
|
1681
1779
|
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
|
|
@@ -1685,11 +1783,11 @@ switch(state.consents.resolutionStrategy.value){case 'or':return configuredConse
|
|
|
1685
1783
|
// ["Performance Cookies", "Functional Cookies"]
|
|
1686
1784
|
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.
|
|
1687
1785
|
return configuredConsents.every(matchPredicate);}// If there are no consents configured for the destination for the current provider, events should be sent.
|
|
1688
|
-
return true;}catch(err){errorHandler
|
|
1786
|
+
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;}}}});
|
|
1689
1787
|
|
|
1690
1788
|
const pluginName$3='StorageEncryption';const StorageEncryption=()=>({name:pluginName$3,initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$3];},storage:{encrypt(value){return encryptBrowser(value);},decrypt(value){return decryptBrowser(value);}}});
|
|
1691
1789
|
|
|
1692
|
-
|
|
1790
|
+
var _ref,_ref2,_ref3,_ref4,_ref5;/* eslint-disable no-use-before-define */const crypto$1=((_ref=typeof globalThis!='undefined'?globalThis:void 0)===null||_ref===void 0?void 0:_ref.crypto)||((_ref2=typeof global!='undefined'?global:void 0)===null||_ref2===void 0?void 0:_ref2.crypto)||((_ref3=typeof window!='undefined'?window:void 0)===null||_ref3===void 0?void 0:_ref3.crypto)||((_ref4=typeof self!='undefined'?self:void 0)===null||_ref4===void 0?void 0:_ref4.crypto)||((_ref5=typeof frames!='undefined'?frames:void 0)===null||_ref5===void 0||(_ref5=_ref5[0])===null||_ref5===void 0?void 0:_ref5.crypto);let randomWordArray;if(crypto$1){randomWordArray=nBytes=>{const words=[];for(let i=0,rcache;i<nBytes;i+=4){words.push(crypto$1.getRandomValues(new Uint32Array(1))[0]);}return new WordArray(words,nBytes);};}else {// Because there is no global crypto property in this context, cryptographically unsafe Math.random() is used.
|
|
1693
1791
|
randomWordArray=nBytes=>{const words=[];const r=m_w=>{let _m_w=m_w;let _m_z=0x3ade68b1;const mask=0xffffffff;return ()=>{_m_z=0x9069*(_m_z&0xFFFF)+(_m_z>>0x10)&mask;_m_w=0x4650*(_m_w&0xFFFF)+(_m_w>>0x10)&mask;let result=(_m_z<<0x10)+_m_w&mask;result/=0x100000000;result+=0.5;return result*(Math.random()>0.5?1:-1);};};for(let i=0,rcache;i<nBytes;i+=4){const _r=r((rcache||Math.random())*0x100000000);rcache=_r()*0x3ade67b7;words.push(_r()*0x100000000|0);}return new WordArray(words,nBytes);};}/**
|
|
1694
1792
|
* Base class for inheritance.
|
|
1695
1793
|
*/class Base{/**
|
|
@@ -1756,7 +1854,7 @@ this.words=words;this.sigBytes=sigBytes;}}/**
|
|
|
1756
1854
|
* @example
|
|
1757
1855
|
*
|
|
1758
1856
|
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
|
1759
|
-
|
|
1857
|
+
*//**
|
|
1760
1858
|
* Converts this word array to a string.
|
|
1761
1859
|
*
|
|
1762
1860
|
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
|
@@ -1802,7 +1900,7 @@ words[sigBytes>>>2]&=0xffffffff<<32-sigBytes%4*8;words.length=Math.ceil(sigBytes
|
|
|
1802
1900
|
* var clone = wordArray.clone();
|
|
1803
1901
|
*/clone(){const clone=super.clone.call(this);clone.words=this.words.slice(0);return clone;}}/**
|
|
1804
1902
|
* Hex encoding strategy.
|
|
1805
|
-
*/const Hex={/**
|
|
1903
|
+
*/_defineProperty(WordArray,"random",randomWordArray);const Hex={/**
|
|
1806
1904
|
* Converts a word array to a hex string.
|
|
1807
1905
|
*
|
|
1808
1906
|
* @param {WordArray} wordArray The word array.
|
|
@@ -2697,14 +2795,15 @@ while(isString(currentVal)){decryptedVal=decrypt(currentVal);// Decrypt using th
|
|
|
2697
2795
|
decryptedVal=decryptBrowser(decryptedVal);// If the decrypted value is the same as the current value,
|
|
2698
2796
|
// then it's not encrypted anymore
|
|
2699
2797
|
if(decryptedVal===currentVal){break;}// storejs that is used in localstorage engine already deserializes json strings but swallows errors
|
|
2700
|
-
currentVal=JSON.parse(decryptedVal);}return currentVal;}catch(err){const customMessage=STORAGE_MIGRATION_ERROR(key);errorHandler
|
|
2798
|
+
currentVal=JSON.parse(decryptedVal);}return currentVal;}catch(err){const customMessage=STORAGE_MIGRATION_ERROR(key);errorHandler===null||errorHandler===void 0||errorHandler.onError({error:err,context:STORAGE_MIGRATOR_PLUGIN,customMessage,groupingHash:customMessage});return null;}}}});
|
|
2701
2799
|
|
|
2702
|
-
const DEFAULT_RETRY_QUEUE_OPTIONS={maxRetryDelay:
|
|
2800
|
+
const DEFAULT_RETRY_QUEUE_OPTIONS={maxRetryDelay:540000,minRetryDelay:1000,backoffFactor:2,backoffJitter:0.2,maxAttempts:30,// ~3h of retries at these delays
|
|
2801
|
+
maxItems:100};const REQUEST_TIMEOUT_MS=30*1000;// 30 seconds
|
|
2703
2802
|
const DATA_PLANE_API_VERSION='v1';const QUEUE_NAME='rudder';const XHR_QUEUE_PLUGIN='XhrQueuePlugin';
|
|
2704
2803
|
|
|
2705
2804
|
const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,originalErrorMsg)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s). Cause: ${originalErrorMsg}.`;
|
|
2706
2805
|
|
|
2707
|
-
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
|
|
2806
|
+
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
|
|
2708
2807
|
logger.warn(logMsg);}else {logger.error(`${logMsg} Retries exhausted (${qItemProcessInfo.maxRetryAttempts}). ${dropMsg}`);}}else {// Use error for non-retryable failures
|
|
2709
2808
|
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
|
|
2710
2809
|
// The same value is added in the event payload as well
|
|
@@ -2726,11 +2825,11 @@ const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initial
|
|
|
2726
2825
|
* @param logger Logger instance
|
|
2727
2826
|
* @returns RetryQueue instance
|
|
2728
2827
|
*/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
|
|
2729
|
-
`${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)=>{
|
|
2730
|
-
if(isUndefined(details
|
|
2731
|
-
done(null);return;}const isRetryable=isErrRetryable(details
|
|
2732
|
-
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
|
|
2733
|
-
return getBatchDeliveryPayload(events,currentTime,logger)
|
|
2828
|
+
`${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
|
|
2829
|
+
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)
|
|
2830
|
+
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)
|
|
2831
|
+
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
|
|
2832
|
+
return (_getBatchDeliveryPayl=getBatchDeliveryPayload(events,currentTime,logger))===null||_getBatchDeliveryPayl===void 0?void 0:_getBatchDeliveryPayl.length;});return eventsQueue;},/**
|
|
2734
2833
|
* Add event to the queue for delivery
|
|
2735
2834
|
* @param state Application state
|
|
2736
2835
|
* @param eventsQueue RetryQueue instance
|
|
@@ -2756,7 +2855,7 @@ AnonymousId:toBase64(event.anonymousId)};eventsQueue.addItem({url,headers,event}
|
|
|
2756
2855
|
* Map of optional plugin names and direct imports for legacy builds
|
|
2757
2856
|
*/const getOptionalPluginsMap=()=>{return getBundledBuildPluginImports();};/**
|
|
2758
2857
|
* Map of optional plugin names and dynamic imports for modern builds
|
|
2759
|
-
*/const getRemotePluginsMap=activePluginNames=>{{return {};}};const pluginsInventory={
|
|
2858
|
+
*/const getRemotePluginsMap=activePluginNames=>{{return {};}};const pluginsInventory=_objectSpread2(_objectSpread2({},getMandatoryPluginsMap()),getOptionalPluginsMap());const remotePluginsInventory=activePluginNames=>_objectSpread2({},getRemotePluginsMap());
|
|
2760
2859
|
|
|
2761
2860
|
// TODO: add retry mechanism for getting remote plugins
|
|
2762
2861
|
// TODO: add timeout error mechanism for marking remote plugins that failed to load as failed in state
|
|
@@ -2781,8 +2880,26 @@ const availablePlugins=[...Object.keys(pluginsInventory),...pluginNamesList];con
|
|
|
2781
2880
|
* Register plugins that are direct imports to PluginEngine
|
|
2782
2881
|
*/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));}}/**
|
|
2783
2882
|
* Register plugins that are dynamic imports to PluginEngine
|
|
2784
|
-
*/registerRemotePlugins(){const remotePluginsList=remotePluginsInventory(state.plugins.activePlugins.value);
|
|
2785
|
-
|
|
2883
|
+
*/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
|
|
2884
|
+
// unknown plugins from setActivePlugins, unavailable local plugins from
|
|
2885
|
+
// registerLocalPlugins and registration failures from register(). Reporting
|
|
2886
|
+
// the global list would attribute those to this remote load incident.
|
|
2887
|
+
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
|
|
2888
|
+
// undefined factory blind reports a per-build minified name.
|
|
2889
|
+
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
|
|
2890
|
+
failedRemotePlugins.push(remotePluginKey);state.plugins.failedPlugins.value=[...state.plugins.failedPlugins.value,remotePluginKey];// A rejection is not guaranteed to be an Error, so without the
|
|
2891
|
+
// fallback the log reads "- undefined".
|
|
2892
|
+
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
|
|
2893
|
+
// fan-out is one incident and gets one report, raised only after every
|
|
2894
|
+
// import has settled so it names all of them.
|
|
2895
|
+
//
|
|
2896
|
+
// An import that never settles therefore means no report. That is
|
|
2897
|
+
// deliberate: a dynamic import has no timeout of its own, and holding a
|
|
2898
|
+
// timer open to salvage a partial report would spend page resources on
|
|
2899
|
+
// error reporting, which is the lowest priority thing the SDK does.
|
|
2900
|
+
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
|
|
2901
|
+
// federation runtime names its own local, renamed by the host bundler per build.
|
|
2902
|
+
remoteEntryUrl);}).catch(err=>{this.onError(err);});}/**
|
|
2786
2903
|
* Extension point invoke that allows multiple plugins to be registered to it with error handling
|
|
2787
2904
|
*/invokeMultiple(extPoint,...args){try{return this.engine.invokeMultiple(extPoint,...args);}catch(e){this.onError(e,extPoint);return [];}}/**
|
|
2788
2905
|
* Extension point invoke that allows a single plugin to be registered to it with error handling
|
|
@@ -2801,8 +2918,8 @@ const legacyGetHostname=href=>{const l=document.createElement('a');l.href=href;r
|
|
|
2801
2918
|
* Levels returns all levels of the given url
|
|
2802
2919
|
*
|
|
2803
2920
|
* The method returns an empty array when the hostname is an ip.
|
|
2804
|
-
*/const levelsFunc=url=>{
|
|
2805
|
-
const host=typeof globalThis.URL!=='function'?legacyGetHostname(url):new URL(url).hostname;const parts=host
|
|
2921
|
+
*/const levelsFunc=url=>{var _host$split;// This is called before the polyfills load thus new URL cannot be used
|
|
2922
|
+
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.
|
|
2806
2923
|
if(parts.length===4&&last&&last===parseInt(last,10).toString()){return levels;}// Localhost.
|
|
2807
2924
|
if(parts.length<=1){// Fix to support localhost
|
|
2808
2925
|
if(parts[0]&&parts[0].indexOf('localhost')!==-1){return ['localhost'];}return levels;}// Create levels.
|
|
@@ -2818,16 +2935,16 @@ for(let i=parts.length-2;i>=0;i-=1){levels.push(parts.slice(i).join('.'));}retur
|
|
|
2818
2935
|
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
|
|
2819
2936
|
cookie(cname,1,opts);// If successful
|
|
2820
2937
|
if(cookie(cname)){// Remove cookie from domain
|
|
2821
|
-
cookie(cname,null,opts);return domain;}}catch{// Silently continue to next domain level if cookie access is restricted or setting fails
|
|
2938
|
+
cookie(cname,null,opts);return domain;}}catch(_unused){// Silently continue to next domain level if cookie access is restricted or setting fails
|
|
2822
2939
|
// Best-effort cleanup to avoid leaking the test cookie
|
|
2823
|
-
try{cookie(cname,null,opts);}catch{// Ignore if we are unable to delete the cookie
|
|
2940
|
+
try{cookie(cname,null,opts);}catch(_unused2){// Ignore if we are unable to delete the cookie
|
|
2824
2941
|
}}}return '';};
|
|
2825
2942
|
|
|
2826
2943
|
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});
|
|
2827
2944
|
|
|
2828
2945
|
/**
|
|
2829
2946
|
* A storage utility to retain values in memory via Storage interface
|
|
2830
|
-
*/class InMemoryStorage{isEnabled
|
|
2947
|
+
*/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);
|
|
2831
2948
|
|
|
2832
2949
|
function getDefaultExportFromCjs (x) {
|
|
2833
2950
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -2850,24 +2967,24 @@ const store = /*@__PURE__*/getDefaultExportFromCjs(storeExports);
|
|
|
2850
2967
|
// https://www.npmjs.com/package/storejs
|
|
2851
2968
|
/**
|
|
2852
2969
|
* A storage utility to persist values in localstorage via Storage interface
|
|
2853
|
-
*/class LocalStorage{isSupportAvailable
|
|
2854
|
-
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]
|
|
2970
|
+
*/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
|
|
2971
|
+
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
|
|
2855
2972
|
keys(){return store.keys();}}const defaultLocalStorage=new LocalStorage(defaultLogger);
|
|
2856
2973
|
|
|
2857
2974
|
/**
|
|
2858
2975
|
* A storage utility to persist values in SessionStorage via Storage interface
|
|
2859
|
-
*/class SessionStorage{isSupportAvailable
|
|
2860
|
-
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
|
|
2976
|
+
*/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
|
|
2977
|
+
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);
|
|
2861
2978
|
|
|
2862
2979
|
/**
|
|
2863
2980
|
* A storage utility to persist values in cookies via Storage interface
|
|
2864
|
-
*/class CookieStorage{isSupportAvailable
|
|
2981
|
+
*/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
|
|
2865
2982
|
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
|
|
2866
2983
|
clear(){// Not implemented
|
|
2867
2984
|
// getting a list of all cookie storage keys and remove all values
|
|
2868
2985
|
// sounds risky to do as it will take on all top domain cookies
|
|
2869
2986
|
// better to explicitly clear specific ones if needed
|
|
2870
|
-
}key(index){const curKeys=this.keys();return curKeys[index]
|
|
2987
|
+
}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
|
|
2871
2988
|
keys(){return Object.keys(cookie());}}const defaultCookieStorage=new CookieStorage(defaultLogger);
|
|
2872
2989
|
|
|
2873
2990
|
/**
|
|
@@ -2887,12 +3004,12 @@ state.storage.cookie.value={maxage:cookieStorageOptions.maxage,path:cookieStorag
|
|
|
2887
3004
|
|
|
2888
3005
|
/**
|
|
2889
3006
|
* Store Implementation with dedicated storage
|
|
2890
|
-
*/class Store{constructor(config,engine,pluginsManager){this.id=config.id;this.name=config.name;this.isEncrypted=config.isEncrypted
|
|
3007
|
+
*/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;}/**
|
|
2891
3008
|
* Ensure the key is valid and with correct format
|
|
2892
3009
|
*/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
|
|
2893
3010
|
let compoundKey;Object.values(validKeys).forEach(validKeyName=>{if(validKeyName===key){compoundKey=noCompoundKey?key:[name,id,key].join('.');}});return compoundKey;}/**
|
|
2894
3011
|
* Switch to inMemoryEngine, bringing any existing data with.
|
|
2895
|
-
*/swapQueueStoreToInMemoryEngine(){const{validKeys,noCompoundKey}=this;const inMemoryStorage=getStorageEngine(MEMORY_STORAGE)
|
|
3012
|
+
*/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
|
|
2896
3013
|
// better to keep other queues in localstorage to be flushed later
|
|
2897
3014
|
// than to pull them into memory and remove them from durable storage
|
|
2898
3015
|
const existingEntries=Object.values(validKeys).map(storeKey=>[storeKey,this.get(storeKey)]);// Client data stores keep their durable copy. Dropping rl_user_id and the
|
|
@@ -2902,7 +3019,7 @@ const canDropDurableCopy=!noCompoundKey&&durableEngine!==inMemoryStorage;this.en
|
|
|
2902
3019
|
this.set(storeKey,value);// Only give up the durable copy once the value is readable from memory:
|
|
2903
3020
|
// set() swallows serialisation and storage failures, and get() returns
|
|
2904
3021
|
// null on a parse or decryption failure.
|
|
2905
|
-
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
|
|
3022
|
+
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
|
|
2906
3023
|
// value is already safe in memory, so leave the stale copy for a later
|
|
2907
3024
|
// cleanup rather than aborting the migration - this runs inside set()'s
|
|
2908
3025
|
// catch, and throwing here would lose the value that triggered it.
|
|
@@ -2913,8 +3030,18 @@ this.engine.setItem(validKey,this.encrypt(stringifyWithoutCircular(value,false,[
|
|
|
2913
3030
|
this.swapQueueStoreToInMemoryEngine();// and save it there
|
|
2914
3031
|
this.set(key,value);}else {const customMessage=STORE_DATA_SAVE_ERROR(key);this.onError(err,customMessage,customMessage);}}}/**
|
|
2915
3032
|
* Get by Key.
|
|
2916
|
-
*/get(key){const validKey=this.createValidKey(key);let decryptedValue;try{if(!validKey){return null;}
|
|
2917
|
-
return JSON.parse(decryptedValue);}catch(err){
|
|
3033
|
+
*/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
|
|
3034
|
+
return JSON.parse(decryptedValue);}catch(err){// Both encryption plugins, and `crypto` with no decrypt extension point registered, return
|
|
3035
|
+
// an unrecognised format untouched, so an unchanged value may still be readable; keep it.
|
|
3036
|
+
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
|
|
3037
|
+
// poll, and only while the entry still holds what was read. Web Storage has no conditional
|
|
3038
|
+
// delete, so that narrows rather than closes the window in which another tab's write is
|
|
3039
|
+
// dropped; the cost there is a restarted reclaim handshake, since queued events are written
|
|
3040
|
+
// only by the context that owns the store. The compare is serialized because storejs
|
|
3041
|
+
// deserializes on every read, and uses `JSON.stringify` because `stringifyWithoutCircular`
|
|
3042
|
+
// returns null on failure, which would make two unserializable values compare equal.
|
|
3043
|
+
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.
|
|
3044
|
+
}const encryptionPluginName=state.storage.encryptionPluginName.value;// Skip error reporting only when the encryption plugin is configured but failed to load
|
|
2918
3045
|
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;}}/**
|
|
2919
3046
|
* Remove by Key.
|
|
2920
3047
|
*/remove(key){const validKey=this.createValidKey(key);if(validKey){this.engine.removeItem(validKey);}}/**
|
|
@@ -2925,31 +3052,31 @@ const shouldReportError=!encryptionPluginName||!state.plugins.failedPlugins.valu
|
|
|
2925
3052
|
* Encrypt value
|
|
2926
3053
|
*/encrypt(value){return this.crypto(value,'encrypt');}/**
|
|
2927
3054
|
* Extension point to use with encryption plugins
|
|
2928
|
-
*/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
|
|
3055
|
+
*/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:'';}/**
|
|
2929
3056
|
* Handle errors
|
|
2930
3057
|
*/onError(error,customMessage,groupingHash){this.errorHandler.onError({error,context:`Store ${this.id}`,customMessage,groupingHash});}}
|
|
2931
3058
|
|
|
2932
|
-
const getStorageTypeFromPreConsentIfApplicable=(state,sessionKey)=>{let overriddenStorageType;if(state.consents.preConsent.value.enabled){switch(state.consents.preConsent.value.storage
|
|
3059
|
+
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;};
|
|
2933
3060
|
|
|
2934
3061
|
/**
|
|
2935
3062
|
* A service to manage stores & available storage client configurations
|
|
2936
|
-
*/class StoreManager{
|
|
3063
|
+
*/class StoreManager{constructor(pluginsManager,errorHandler,logger){_defineProperty(this,"stores",{});_defineProperty(this,"isInitialized",false);this.errorHandler=errorHandler;this.logger=logger;this.pluginsManager=pluginsManager;}/**
|
|
2937
3064
|
* Configure available storage client instances
|
|
2938
|
-
*/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
|
|
3065
|
+
*/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;}/**
|
|
2939
3066
|
* Create store to persist data used by the SDK like session, used details etc
|
|
2940
3067
|
*/initClientDataStores(){this.initializeStorageState();// TODO: fill in extra config values and bring them in from StoreManagerOptions if needed
|
|
2941
3068
|
// TODO: should we pass the keys for all in order to validate or leave free as v1.1?
|
|
2942
3069
|
// Initializing all the enabled store because previous user data might be in different storage
|
|
2943
3070
|
// that needs auto migration
|
|
2944
|
-
const storageTypes=[MEMORY_STORAGE,LOCAL_STORAGE,COOKIE_STORAGE,SESSION_STORAGE];storageTypes.forEach(storageType=>{if(getStorageEngine(storageType)
|
|
2945
|
-
const postConsentStorageOpts=state.consents.postConsent.value.storage;if(isDefined(postConsentStorageOpts
|
|
3071
|
+
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
|
|
3072
|
+
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
|
|
2946
3073
|
// persisted before consent is given. Only the fallback changes: nothing is persisted unless
|
|
2947
3074
|
// a storage type has been explicitly configured.
|
|
2948
|
-
const preConsentOpts=state.consents.preConsent.value;const isStorageFromLoadOptionsBeforeConsent=preConsentOpts.enabled===true&&!preConsentOpts.storage
|
|
3075
|
+
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
|
|
2949
3076
|
// resolved here, against the default that applies to the current consent phase
|
|
2950
|
-
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
|
|
2951
|
-
let storageType=preConsentStorageType
|
|
2952
|
-
if(getStorageEngine(COOKIE_STORAGE)
|
|
3077
|
+
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
|
|
3078
|
+
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
|
|
3079
|
+
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;}/**
|
|
2953
3080
|
* Create a new store
|
|
2954
3081
|
*/setStore(storeConfig){const storageEngine=getStorageEngine(storeConfig.type);this.stores[storeConfig.id]=new Store(storeConfig,storageEngine,this.pluginsManager);return this.stores[storeConfig.id];}/**
|
|
2955
3082
|
* Retrieve a store
|
|
@@ -2961,7 +3088,7 @@ const isValidSourceConfig=res=>isObjectLiteralAndNotNull(res)&&isObjectLiteralAn
|
|
|
2961
3088
|
* @param storageOpts Storage options from the load API options or the consent API options
|
|
2962
3089
|
* @param context Logger context
|
|
2963
3090
|
* @param logger Logger instance
|
|
2964
|
-
*/const validateStorageOptions=(storageOpts,context,logger)=>{if(!isObjectLiteralAndNotNull(storageOpts)){return;}const{type,entries}=storageOpts;if(isDefined(type)&&!isValidStorageType(type)){logger
|
|
3091
|
+
*/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));}});}};/**
|
|
2965
3092
|
* Parses a URL without the URL constructor, which is unavailable on legacy JS engines
|
|
2966
3093
|
* until the polyfills load.
|
|
2967
3094
|
*/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,
|
|
@@ -2985,11 +3112,11 @@ if(hostOnlyCookies||!webpageTopDomain){return dataServiceHostname===globalThis.l
|
|
|
2985
3112
|
* Removes trailing slash from url
|
|
2986
3113
|
* @param url
|
|
2987
3114
|
* @returns url
|
|
2988
|
-
*/const removeTrailingSlashes=url=>url
|
|
3115
|
+
*/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;}};/**
|
|
2989
3116
|
* Get the referring domain from the referrer URL
|
|
2990
3117
|
* @param referrer Page referrer
|
|
2991
3118
|
* @returns Page referring domain
|
|
2992
|
-
*/const getReferringDomain=referrer=>getDomain(referrer)
|
|
3119
|
+
*/const getReferringDomain=referrer=>{var _getDomain;return (_getDomain=getDomain(referrer))!==null&&_getDomain!==void 0?_getDomain:'';};/**
|
|
2993
3120
|
* Extracts UTM parameters from the URL
|
|
2994
3121
|
* @param url Page URL
|
|
2995
3122
|
* @returns UTM parameters
|
|
@@ -3004,7 +3131,7 @@ if(utmParam==='campaign'){utmParam='name';}result[utmParam]=value;}});}catch(err
|
|
|
3004
3131
|
|
|
3005
3132
|
const DEFAULT_PRE_CONSENT_STORAGE_STRATEGY='none';const DEFAULT_PRE_CONSENT_EVENTS_DELIVERY_TYPE='immediate';
|
|
3006
3133
|
|
|
3007
|
-
const isErrorReportingEnabled=sourceConfig=>sourceConfig
|
|
3134
|
+
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;};
|
|
3008
3135
|
|
|
3009
3136
|
/**
|
|
3010
3137
|
* Validates and normalizes the consent options provided by the user
|
|
@@ -3028,7 +3155,7 @@ provider=undefined;}return {provider,consentManagerPluginName};};/**
|
|
|
3028
3155
|
* @param consentManagementOpts Consent management options provided by the user
|
|
3029
3156
|
* @param logger logger instance
|
|
3030
3157
|
* @returns An object containing the consent manager plugin name, initialized, enabled and consents data
|
|
3031
|
-
*/const getConsentManagementData=(consentManagementOpts,logger)=>{let consentManagerPluginName;let allowedConsentIds=[];let deniedConsentIds=[];let initialized=false;let provider;let enabled=consentManagementOpts
|
|
3158
|
+
*/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
|
|
3032
3159
|
({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
|
|
3033
3160
|
enabled=enabled&&Boolean(consentManagerPluginName);return {provider,consentManagerPluginName,initialized,enabled,consentsData};};
|
|
3034
3161
|
|
|
@@ -3064,11 +3191,11 @@ const cookieDomain=removeLeadingPeriod(providedCookieDomain).toLowerCase();/**
|
|
|
3064
3191
|
* The cookie domain also has to sit at or below the browser-verified domain of the webpage.
|
|
3065
3192
|
* Anything above it is a public suffix, ex: 'co.uk', which the browser refuses to scope
|
|
3066
3193
|
* cookies to however well it matches as a string suffix.
|
|
3067
|
-
*/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
|
|
3194
|
+
*/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;/**
|
|
3068
3195
|
* Based on the following conditions, we decide whether to use the exact domain or not to determine the data service URL:
|
|
3069
3196
|
* 1. If the cookie domain is provided and it is not a top-level domain, then use the exact domain
|
|
3070
3197
|
* 2. If the sameDomainCookiesOnly flag is set to true, then use the exact domain
|
|
3071
|
-
*/const useExactDomain=isDefined(providedCookieDomain)&&!isWebpageTopLevelDomain(removeLeadingPeriod(providedCookieDomain))||sameDomainCookiesOnly;const{hostname:webpageHostname}=globalThis.location;const{topDomain:webpageTopDomain,topHost:webpageTopHost}=getWebpageTopDomain();const dataServiceUrl=getDataServiceUrl(dataServiceEndpoint
|
|
3198
|
+
*/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,
|
|
3072
3199
|
// in which case the data service host cannot be verified
|
|
3073
3200
|
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
|
|
3074
3201
|
// cross-site request. Cookies are not isolated by port, hence it plays no part here.
|
|
@@ -3076,29 +3203,29 @@ const dataServiceHostname=getHostname(dataServiceUrl);if(isValidURL(dataServiceU
|
|
|
3076
3203
|
// One round of cookie options manipulation is taking place here
|
|
3077
3204
|
// Based on these(setCookieDomain/storage.cookie or sameDomainCookiesOnly) two load-options, final cookie options are set in the storage module
|
|
3078
3205
|
// TODO: Refactor the cookie options manipulation logic in one place
|
|
3079
|
-
if(sscEnabled&&webpageHostname!==dataServiceHostname){cookieOptions={
|
|
3080
|
-
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
|
|
3206
|
+
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
|
|
3207
|
+
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
|
|
3081
3208
|
// values are resolved in the store manager.
|
|
3082
|
-
validateStorageOptions(storageOptsFromLoad,CONFIG_MANAGER,logger);let storageEncryptionVersion=storageOptsFromLoad
|
|
3209
|
+
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
|
|
3083
3210
|
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
|
|
3084
|
-
const configuredMigrationValue=storageOptsFromLoad
|
|
3085
|
-
const preConsentOpts=state.loadOptions.value.preConsent;const configuredStrategy=preConsentOpts
|
|
3211
|
+
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
|
|
3212
|
+
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,
|
|
3086
3213
|
// so an existing configuration keeps persisting nothing before consent is given. Enabling it
|
|
3087
3214
|
// takes precedence over the deprecated strategy, otherwise a migration that leaves the strategy
|
|
3088
3215
|
// in place would silently do nothing.
|
|
3089
|
-
let storageStrategy;if(preConsentOpts
|
|
3216
|
+
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
|
|
3090
3217
|
// if it is not already initialized and
|
|
3091
3218
|
// if consent management is enabled
|
|
3092
|
-
enabled:state.loadOptions.value.preConsent
|
|
3219
|
+
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}};});};/**
|
|
3093
3220
|
* Determines the consent management state variables from the source config data
|
|
3094
3221
|
* @param resp Source config response
|
|
3095
3222
|
* @param logger Logger instance
|
|
3096
|
-
*/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)
|
|
3223
|
+
*/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
|
|
3097
3224
|
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}`;};/**
|
|
3098
3225
|
* Transforms destinations config from source config response to Destination format
|
|
3099
3226
|
* @param destinations Array of destination items from config response
|
|
3100
3227
|
* @returns Array of transformed Destination objects
|
|
3101
|
-
*/const getDestinationsFromConfig=destinations=>destinations.map(destination=>
|
|
3228
|
+
*/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};});
|
|
3102
3229
|
|
|
3103
3230
|
/**
|
|
3104
3231
|
* A function that determines the base URL for the integrations or plugins SDK
|
|
@@ -3143,10 +3270,10 @@ state.nativeDestinations.loadOnlyIntegrations.value=integrations;});this.getConf
|
|
|
3143
3270
|
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
|
|
3144
3271
|
if(res.source.enabled===false){this.logger.error(SOURCE_DISABLED_ERROR);return;}// set the values in state for reporting slice
|
|
3145
3272
|
updateReportingState(res);const nativeDestinations=res.source.destinations.length>0?getDestinationsFromConfig(res.source.destinations):[];// set in the state --> source, destination, lifecycle, reporting
|
|
3146
|
-
n(()=>{
|
|
3273
|
+
n(()=>{var _state$loadOptions$va;// set source related information in state
|
|
3147
3274
|
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
|
|
3148
3275
|
state.nativeDestinations.configuredDestinations.value=nativeDestinations;// set the desired optional plugins
|
|
3149
|
-
state.plugins.pluginsToLoadFromConfig.value=state.loadOptions.value.plugins
|
|
3276
|
+
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
|
|
3150
3277
|
state.lifecycle.status.value='configured';});}/**
|
|
3151
3278
|
* A function to fetch source config either from /sourceConfig endpoint
|
|
3152
3279
|
* or from getSourceConfig load option
|
|
@@ -3161,19 +3288,19 @@ this.httpClient.getAsyncData({url:state.lifecycle.sourceConfigUrl.value,options:
|
|
|
3161
3288
|
* @returns string
|
|
3162
3289
|
*/const getTimezone=()=>{// Not susceptible to super-linear backtracking
|
|
3163
3290
|
// eslint-disable-next-line sonarjs/slow-regex
|
|
3164
|
-
const timezone=/([A-Z]+[+-]\d+)/.exec(new Date().toString());return timezone
|
|
3291
|
+
const timezone=/([A-Z]+[+-]\d+)/.exec(new Date().toString());return timezone!==null&&timezone!==void 0&&timezone[1]?timezone[1]:'NA';};
|
|
3165
3292
|
|
|
3166
3293
|
/**
|
|
3167
3294
|
* Get the referrer URL
|
|
3168
3295
|
* @returns The referrer URL
|
|
3169
|
-
*/const getReferrer=(getDocument=()=>document)=>getDocument()
|
|
3296
|
+
*/const getReferrer=(getDocument=()=>document)=>{var _getDocument;return ((_getDocument=getDocument())===null||_getDocument===void 0?void 0:_getDocument.referrer)||'$direct';};/**
|
|
3170
3297
|
* To get the canonical URL of the page
|
|
3171
3298
|
* @returns canonical URL
|
|
3172
|
-
*/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')
|
|
3299
|
+
*/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,
|
|
3173
3300
|
// add "Brave/<version>" to the user agent with the version value from the Chrome component
|
|
3174
3301
|
if(brave&&Object.getPrototypeOf(brave).isBrave){// Example:
|
|
3175
3302
|
// 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
|
|
3176
|
-
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
|
|
3303
|
+
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;};/**
|
|
3177
3304
|
* Default page properties
|
|
3178
3305
|
* @returns Default page properties
|
|
3179
3306
|
*/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.
|
|
@@ -3181,17 +3308,19 @@ if(canonicalUrl){try{const urlObj=new URL(canonicalUrl);// If existing, query pa
|
|
|
3181
3308
|
if(urlObj.search===''){pageUrl=canonicalUrl+search;}else {pageUrl=canonicalUrl;}path=urlObj.pathname;}catch(err){// Do nothing
|
|
3182
3309
|
}}const url=getUrlWithoutHash(pageUrl);const{title}=getDocument();const referrer=getReferrer(getDocument);return {path,referrer,referring_domain:getReferringDomain(referrer),search,title,url,tab_url:tabUrl};};
|
|
3183
3310
|
|
|
3184
|
-
const getUserAgentClientHint=(callback,level='none')=>{if(level==='none'){callback(undefined);}if(level==='default'){callback(navigator.userAgentData);}if(level==='full'){navigator.userAgentData
|
|
3185
|
-
|
|
3186
|
-
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
|
|
3187
|
-
// the polyfill service serves them under the same feature name, "URL".
|
|
3188
|
-
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
|
|
3189
|
-
// the polyfill service serves them under the same feature name, "TextEncoder".
|
|
3190
|
-
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".
|
|
3191
|
-
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;};
|
|
3311
|
+
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();});}};
|
|
3192
3312
|
|
|
3193
|
-
const
|
|
3194
|
-
|
|
3313
|
+
const detectAdBlockers=httpClient=>{state.capabilities.isAdBlockerDetectionInProgress.value=true;try{// Apparently, '?view=ad' is a query param that is blocked by majority of adblockers
|
|
3314
|
+
// Use source config URL here as it is very unlikely to be blocked by adblockers
|
|
3315
|
+
// Only the extra query param should make it vulnerable to adblockers
|
|
3316
|
+
// This will work even if the users proxies it.
|
|
3317
|
+
// The edge case where this doesn't work is when HEAD method is not allowed by the server (user's)
|
|
3318
|
+
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
|
|
3319
|
+
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
|
|
3320
|
+
// Often adblockers instead of blocking the request, they redirect it to an internal URL
|
|
3321
|
+
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
|
|
3322
|
+
state.capabilities.isAdBlockerDetectionInProgress.value=false;// Re-throw the error to be handled by the caller
|
|
3323
|
+
throw err;}};
|
|
3195
3324
|
|
|
3196
3325
|
const hasCrypto=()=>!isNullOrUndefined(globalThis.crypto)&&isFunction(globalThis.crypto.getRandomValues);// eslint-disable-next-line compat/compat -- We are checking for the existence of navigator.userAgentData
|
|
3197
3326
|
const hasUAClientHints=()=>!isNullOrUndefined(globalThis.navigator.userAgentData);const hasBeacon=()=>!isNullOrUndefined(globalThis.navigator.sendBeacon)&&isFunction(globalThis.navigator.sendBeacon);
|
|
@@ -3207,10 +3336,13 @@ state.capabilities.isBeaconAvailable.value=hasBeacon();state.capabilities.isUaCH
|
|
|
3207
3336
|
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
|
|
3208
3337
|
j(()=>{if(state.loadOptions.value.sendAdblockPage===true&&state.lifecycle.sourceConfigUrl.value!==undefined){detectAdBlockers(this.httpClient);}});}/**
|
|
3209
3338
|
* Detect if polyfills are required and then load script from polyfill URL
|
|
3210
|
-
*/prepareBrowserCapabilities(){
|
|
3211
|
-
//
|
|
3212
|
-
|
|
3213
|
-
|
|
3339
|
+
*/prepareBrowserCapabilities(){// The snippet only hands the modern build to engines that ship every polyfill-list API the
|
|
3340
|
+
// SDK and integrations call (replaceAll is listed but unused), so this is legacy-only.
|
|
3341
|
+
{this.onReady();return;}}/**
|
|
3342
|
+
* Report the features that the polyfill script did not apply and then set the
|
|
3343
|
+
* lifecycle status to next phase
|
|
3344
|
+
*/onPolyfillLoaded(){// Guarded too so the detection list is dropped from the modern bundle
|
|
3345
|
+
this.onReady();}/**
|
|
3214
3346
|
* Attach listeners to window to observe event that update capabilities state values
|
|
3215
3347
|
*/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));}/**
|
|
3216
3348
|
* Set the lifecycle status to next phase
|
|
@@ -3218,7 +3350,7 @@ delete globalThis[polyfillCallbackName];};globalThis[polyfillCallbackName]=polyf
|
|
|
3218
3350
|
onReady(){this.detectBrowserCapabilities();state.lifecycle.status.value='browserCapabilitiesReady';}/**
|
|
3219
3351
|
* Handles error
|
|
3220
3352
|
* @param error The error object
|
|
3221
|
-
*/onError(error,groupingHash){this.errorHandler.onError({error,context:CAPABILITIES_MANAGER,groupingHash});}}
|
|
3353
|
+
*/onError(error,groupingHash){void this.errorHandler.onError({error,context:CAPABILITIES_MANAGER,groupingHash});}}
|
|
3222
3354
|
|
|
3223
3355
|
const CHANNEL='web';// These are the top-level elements in the standard RudderStack event spec
|
|
3224
3356
|
const TOP_LEVEL_ELEMENTS=['integrations','anonymousId','originalTimestamp'];// Reserved elements in the context of standard RudderStack event spec
|
|
@@ -3226,7 +3358,7 @@ const TOP_LEVEL_ELEMENTS=['integrations','anonymousId','originalTimestamp'];// R
|
|
|
3226
3358
|
const CONTEXT_RESERVED_ELEMENTS=['library','consentManagement','userAgent','ua-ch','screen'];// Reserved elements in the standard RudderStack event spec
|
|
3227
3359
|
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'];
|
|
3228
3360
|
|
|
3229
|
-
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;}};
|
|
3361
|
+
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;}};
|
|
3230
3362
|
|
|
3231
3363
|
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={};}}
|
|
3232
3364
|
|
|
@@ -3245,7 +3377,7 @@ class CustomContextStore{constructor(state,logger){this.state=state;this.logger=
|
|
|
3245
3377
|
* @returns boolean
|
|
3246
3378
|
*/const isPositiveInteger=num=>isNumber(num)&&num>=0&&Number.isInteger(num);
|
|
3247
3379
|
|
|
3248
|
-
const MIN_SESSION_ID_LENGTH=10;const isCutOffTimeExceeded=sessionInfo=>{const{cutOff}=sessionInfo;const timestamp=Date.now();return Boolean(cutOff
|
|
3380
|
+
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);};/**
|
|
3249
3381
|
* A function to validate whether the current auto tracking session has expired or not.
|
|
3250
3382
|
* It checks for the current session expiry and the cut off time expiry.
|
|
3251
3383
|
* @param sessionInfo session info
|
|
@@ -3258,13 +3390,13 @@ const MIN_SESSION_ID_LENGTH=10;const isCutOffTimeExceeded=sessionInfo=>{const{cu
|
|
|
3258
3390
|
* @param {number} sessionId
|
|
3259
3391
|
* @param logger logger
|
|
3260
3392
|
* @returns
|
|
3261
|
-
*/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
|
|
3393
|
+
*/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;};/**
|
|
3262
3394
|
* A function to generate new auto tracking session
|
|
3263
3395
|
* @param sessionInfo session info
|
|
3264
3396
|
* @returns SessionInfo
|
|
3265
|
-
*/const generateAutoTrackingSession=sessionInfo=>{const{timeout,cutOff}=sessionInfo;const timestamp=Date.now();return {id:timestamp,// set the current timestamp
|
|
3397
|
+
*/const generateAutoTrackingSession=sessionInfo=>{const{timeout,cutOff}=sessionInfo;const timestamp=Date.now();return _objectSpread2({id:timestamp,// set the current timestamp
|
|
3266
3398
|
expiresAt:timestamp+timeout,// set the expiry time of the session
|
|
3267
|
-
timeout,autoTrack:true
|
|
3399
|
+
timeout,autoTrack:true},cutOff&&{cutOff});};/**
|
|
3268
3400
|
* A function to generate new manual tracking session
|
|
3269
3401
|
* @param id Provided sessionId
|
|
3270
3402
|
* @param logger Logger module
|
|
@@ -3273,19 +3405,19 @@ timeout,autoTrack:true,...(cutOff&&{cutOff})};};/**
|
|
|
3273
3405
|
* Generate a new anonymousId
|
|
3274
3406
|
* @returns string anonymousID
|
|
3275
3407
|
*/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
|
|
3276
|
-
if(isBoolean(options)){const{entries
|
|
3277
|
-
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 {
|
|
3408
|
+
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
|
|
3409
|
+
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);};
|
|
3278
3410
|
|
|
3279
3411
|
/**
|
|
3280
3412
|
* To get the page properties for context object
|
|
3281
3413
|
* @param pageProps Page properties
|
|
3282
3414
|
* @returns page properties object for context
|
|
3283
3415
|
*/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
|
|
3284
|
-
const curPageProps=getDefaultPageProperties();const ctxPageProps={};Object.keys(curPageProps).forEach(key=>{ctxPageProps[key]=pageProps
|
|
3416
|
+
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;};/**
|
|
3285
3417
|
* Add any missing default page properties using values from options and defaults
|
|
3286
3418
|
* @param properties Input page properties
|
|
3287
3419
|
* @param options API options
|
|
3288
|
-
*/const getUpdatedPageProperties=(properties,options)=>{const optionsPageProps=options
|
|
3420
|
+
*/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
|
|
3289
3421
|
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;};/**
|
|
3290
3422
|
* Utility to check for reserved keys in the input object
|
|
3291
3423
|
* @param obj Generic object
|
|
@@ -3318,20 +3450,18 @@ rudderEvent.context=getMergedContext(rudderEvent.context,options,logger);}};/**
|
|
|
3318
3450
|
* Returns the final integrations config for the event based on the global config and event's config
|
|
3319
3451
|
* @param integrationsConfig Event's integrations config
|
|
3320
3452
|
* @returns Final integrations config
|
|
3321
|
-
*/const getEventIntegrationsConfig=integrationsConfig=>{let finalIntgConfig;if(state.loadOptions.value.useGlobalIntegrationsConfigInEvents){
|
|
3322
|
-
finalIntgConfig=state.consents.postConsent.value.integrations
|
|
3453
|
+
*/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
|
|
3454
|
+
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);};/**
|
|
3323
3455
|
* Enrich the base event object with data from state and the API options
|
|
3324
3456
|
* @param rudderEvent RudderEvent object
|
|
3325
3457
|
* @param options API options
|
|
3326
3458
|
* @param pageProps Page properties
|
|
3327
3459
|
* @param logger logger
|
|
3328
3460
|
* @returns Enriched RudderEvent object
|
|
3329
|
-
*/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
|
|
3330
|
-
...(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
|
|
3331
|
-
...(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
|
|
3461
|
+
*/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
|
|
3332
3462
|
commonEventData.anonymousId=generateAnonymousId();}else {// Type casting to string as the user session manager will take care of initializing the value
|
|
3333
3463
|
commonEventData.anonymousId=state.session.anonymousId.value;}// set truly anonymous tracking flag
|
|
3334
|
-
if(state.storage.trulyAnonymousTracking.value){commonEventData.context.trulyAnonymousTracking=true;}if(rudderEvent.type==='identify'){commonEventData.context.traits=state.storage.entries.value.userTraits
|
|
3464
|
+
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
|
|
3335
3465
|
// matching with v1.1 payload
|
|
3336
3466
|
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
|
|
3337
3467
|
processedEvent.integrations=getEventIntegrationsConfig(processedEvent.integrations);return processedEvent;};
|
|
@@ -3342,7 +3472,7 @@ class RudderEventFactory{constructor(logger){this.logger=logger;}/**
|
|
|
3342
3472
|
* @param name Page name
|
|
3343
3473
|
* @param properties Page properties
|
|
3344
3474
|
* @param options API options
|
|
3345
|
-
*/generatePageEvent(category,name,properties,options,customContext={}){let props=properties
|
|
3475
|
+
*/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);}/**
|
|
3346
3476
|
* Generate a 'track' event based on the user-input fields
|
|
3347
3477
|
* @param event The event name
|
|
3348
3478
|
* @param properties Event properties
|
|
@@ -3358,7 +3488,7 @@ class RudderEventFactory{constructor(logger){this.logger=logger;}/**
|
|
|
3358
3488
|
* @param from Old user ID
|
|
3359
3489
|
* @param options API options
|
|
3360
3490
|
*/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
|
|
3361
|
-
enrichedEvent.userId=to
|
|
3491
|
+
enrichedEvent.userId=to!==null&&to!==void 0?to:enrichedEvent.userId;return enrichedEvent;}/**
|
|
3362
3492
|
* Generate a 'group' event based on the user-input fields
|
|
3363
3493
|
* @param groupId New group ID
|
|
3364
3494
|
* @param traits new group traits
|
|
@@ -3399,16 +3529,16 @@ class UserSessionManager{/**
|
|
|
3399
3529
|
* Initialize User session with values from storage
|
|
3400
3530
|
*/init(){this.syncStorageDataToState();// Register the effect to sync with storage
|
|
3401
3531
|
this.registerEffects();}syncStorageDataToState(){this.migrateStorageIfNeeded();this.migrateDataFromPreviousStorage();// get the values from storage and set it again
|
|
3402
|
-
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
|
|
3532
|
+
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
|
|
3403
3533
|
sessionInfo={// If manualTrack is set to true in the storage, then do not enable auto tracking even if configured.
|
|
3404
3534
|
// Once manual tracking ends (endSession is called), auto tracking will be enabled in the next SDK run.
|
|
3405
3535
|
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
|
|
3406
|
-
if(!sessionInfo.autoTrack&&sessionInfo.manualTrack!==true){sessionInfo=DEFAULT_USER_SESSION_VALUES.sessionInfo;}else if(configuredSessionTrackingInfo.cutOff
|
|
3407
|
-
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]
|
|
3536
|
+
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
|
|
3537
|
+
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
|
|
3408
3538
|
// as those values indicate there is no need for migration or
|
|
3409
3539
|
// migration failed
|
|
3410
|
-
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
|
|
3411
|
-
if(!autoTrack){return {autoTrack};}let timeout;const configuredSessionTimeout=state.loadOptions.value.sessions
|
|
3540
|
+
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
|
|
3541
|
+
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
|
|
3412
3542
|
// and will proceed with it
|
|
3413
3543
|
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
|
|
3414
3544
|
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};}/**
|
|
@@ -3419,23 +3549,23 @@ cutOffDuration=DEFAULT_SESSION_CUT_OFF_DURATION_MS;}else if(cutOffDuration<sessi
|
|
|
3419
3549
|
* @param cookiesData
|
|
3420
3550
|
* @param store
|
|
3421
3551
|
* @returns
|
|
3422
|
-
*/getEncryptedCookieData(cookiesData,store){const encryptedCookieData=[];cookiesData.forEach(cData=>{const encryptedValue=store
|
|
3552
|
+
*/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;}/**
|
|
3423
3553
|
* A function that makes request to data service to set the cookie
|
|
3424
3554
|
* @param encryptedCookieData
|
|
3425
3555
|
* @param callback
|
|
3426
|
-
*/makeRequestToSetCookie(encryptedCookieData,callback){this.httpClient
|
|
3556
|
+
*/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});}/**
|
|
3427
3557
|
* A function to make an external request to set the cookie from server side
|
|
3428
3558
|
* @param sessionToCookiesMap map of session key to cookie name
|
|
3429
3559
|
* @param cb callback function to be called when the cookie is set
|
|
3430
3560
|
* @param store store to be used to get the cookie value
|
|
3431
3561
|
*/setServerSideCookies(sessionToCookiesMap,cb,store){// Retrieve the cookie value from the state
|
|
3432
3562
|
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
|
|
3433
|
-
const originalCookieValues={};sessionKeys.forEach(sessionKey=>{originalCookieValues[sessionToCookiesMap[sessionKey].name]=store
|
|
3563
|
+
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
|
|
3434
3564
|
const encryptedCookieData=this.getEncryptedCookieData(getCurrentCookieValuesFromState(),store);if(encryptedCookieData.length>0){// make request to data service to set the cookie from server side
|
|
3435
|
-
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{
|
|
3436
|
-
clearInProgressFlags();if(details
|
|
3565
|
+
this.makeRequestToSetCookie(encryptedCookieData,(res,details)=>{var _details$xhr;// Mark the cookie req status as done
|
|
3566
|
+
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
|
|
3437
3567
|
// both halves of the diagnostic are drawn from the same set
|
|
3438
|
-
const sentCookieNames=new Set(encryptedCookieData.map(each=>each.name));const unappliedCookies=[];getCurrentCookieValuesFromState().forEach(cData=>{const originalCookieVal=originalCookieValues[cData.name];const currentCookieVal=store
|
|
3568
|
+
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.
|
|
3439
3569
|
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
|
|
3440
3570
|
// or other cookie requests might have updated the cookie value.
|
|
3441
3571
|
// Left exactly as the request found it, so the server did not apply this
|
|
@@ -3453,7 +3583,7 @@ if(isNull(originalCookieVal)&&isNull(currentCookieVal)){this.logger.error(FAILED
|
|
|
3453
3583
|
// attributes usually leave none of them set.
|
|
3454
3584
|
// Counted from what was actually sent, not from the queued keys: encryption can
|
|
3455
3585
|
// drop a key, and reporting it as sent would overstate the batch.
|
|
3456
|
-
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
|
|
3586
|
+
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
|
|
3457
3587
|
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
|
|
3458
3588
|
clearInProgressFlags();}}/**
|
|
3459
3589
|
* A function to send every queued server-side cookie as a single request
|
|
@@ -3461,10 +3591,10 @@ clearInProgressFlags();}}/**
|
|
|
3461
3591
|
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
|
|
3462
3592
|
// queued for the next batch rather than being sent twice
|
|
3463
3593
|
this.serverSideCookiesPending={};if(Object.keys(sessionToCookiesMap).length===0){return;}// Every batched key is backed by cookie storage by construction, so they share a store
|
|
3464
|
-
const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[COOKIE_STORAGE]);this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore
|
|
3594
|
+
const curStore=this.storeManager.getStore(storageClientDataStoreNameMap[COOKIE_STORAGE]);this.setServerSideCookies(sessionToCookiesMap,(cookieName,cookieValue)=>{curStore===null||curStore===void 0||curStore.set(cookieName,cookieValue);},curStore);}/**
|
|
3465
3595
|
* A function to sync values in storage
|
|
3466
3596
|
* @param sessionKey
|
|
3467
|
-
*/syncValueToStorage(sessionKey){const entries=state.storage.entries.value;const storageType=entries[sessionKey]
|
|
3597
|
+
*/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
|
|
3468
3598
|
// set the cookie from server side
|
|
3469
3599
|
if(state.serverCookies.isEnabledServerSideCookies.value&&storageType===COOKIE_STORAGE){// Mark the requests as in progress.
|
|
3470
3600
|
this.serverSideCookiesRequestInProgress[sessionKey]=true;// Queue this key and restart the shared debounce, so everything that changes in
|
|
@@ -3473,7 +3603,7 @@ this.serverSideCookiesPending[sessionKey]=cookieName;// Restarting the shared ti
|
|
|
3473
3603
|
// keep postponing the flush for every other key, where per-key timers only ever
|
|
3474
3604
|
// delayed their own. That needs changes arriving closer together than the
|
|
3475
3605
|
// debounce, continuously, so it is accepted rather than capped with a max wait.
|
|
3476
|
-
if(this.serverSideCookiesDebounceTimer){globalThis.clearTimeout(this.serverSideCookiesDebounceTimer);}this.serverSideCookiesDebounceTimer=globalThis.setTimeout(()=>{this.flushServerSideCookies();},SERVER_SIDE_COOKIES_DEBOUNCE_TIME);}else {curStore
|
|
3606
|
+
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);}}}/**
|
|
3477
3607
|
* Function to update storage whenever state value changes
|
|
3478
3608
|
*/registerEffects(){// This will work as long as the user session entry key names are same as the state keys
|
|
3479
3609
|
USER_SESSION_KEYS.forEach(sessionKey=>{j(()=>{// Read before syncing so the effect subscribes to the signal, and record after
|
|
@@ -3485,16 +3615,16 @@ const value=state.session[sessionKey].value;this.syncValueToStorage(sessionKey);
|
|
|
3485
3615
|
* 2. rudderAmpLinkerParam: value generated from linker query parm (rudderstack)
|
|
3486
3616
|
* using parseLinker util.
|
|
3487
3617
|
* 3. generateUUID: A new unique id is generated and assigned.
|
|
3488
|
-
*/setAnonymousId(anonymousId,rudderAmpLinkerParam){let finalAnonymousId=anonymousId;if(!isString(anonymousId)||!finalAnonymousId){finalAnonymousId=undefined;}if(this.isPersistenceEnabledForStorageEntry('anonymousId')){if(!finalAnonymousId&&rudderAmpLinkerParam){const linkerPluginsResult=this.pluginsManager
|
|
3618
|
+
*/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;}/**
|
|
3489
3619
|
* Fetches anonymousId
|
|
3490
3620
|
* @param options option to fetch it from external source
|
|
3491
3621
|
* @returns anonymousId
|
|
3492
|
-
*/getAnonymousId(options){const storage=state.storage.entries.value.anonymousId
|
|
3493
|
-
if(!persistedAnonymousId||persistedAnonymousId===DEFAULT_USER_SESSION_VALUES.anonymousId){persistedAnonymousId=this.getEntryValue('anonymousId');}if(!persistedAnonymousId&&options){
|
|
3494
|
-
const autoCapturedAnonymousId=this.pluginsManager
|
|
3622
|
+
*/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
|
|
3623
|
+
if(!persistedAnonymousId||persistedAnonymousId===DEFAULT_USER_SESSION_VALUES.anonymousId){persistedAnonymousId=this.getEntryValue('anonymousId');}if(!persistedAnonymousId&&options){var _this$pluginsManager3;// fetch anonymousId from external source
|
|
3624
|
+
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
|
|
3495
3625
|
// This is needed for entries that are fetched from the storage
|
|
3496
3626
|
// during the current session (for example, session info)
|
|
3497
|
-
this.migrateStorageIfNeeded([store],[sessionKey]);const storageKey=entries[sessionKey]
|
|
3627
|
+
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;}/**
|
|
3498
3628
|
* Fetches the value for a session key. Preferably from storage, so that changes made by
|
|
3499
3629
|
* other tabs are picked up. Falls back to the state whenever storage is known to be
|
|
3500
3630
|
* behind it.
|
|
@@ -3543,20 +3673,20 @@ return this.getEntryValue(sessionKey);}/**
|
|
|
3543
3673
|
*/getAuthToken(){return this.getUserSessionValue('authToken');}/**
|
|
3544
3674
|
* If session is active it returns the sessionId
|
|
3545
3675
|
* @returns
|
|
3546
|
-
*/getSessionId(){const sessionInfo=this.getSessionInfo()
|
|
3676
|
+
*/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;}/**
|
|
3547
3677
|
* A function to keep the session information up to date in the state
|
|
3548
3678
|
* before using it for building event payloads.
|
|
3549
|
-
*/refreshSession(){let sessionInfo=this.getSessionInfo()
|
|
3679
|
+
*/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.
|
|
3550
3680
|
// So, we needn't update the session info.
|
|
3551
3681
|
//
|
|
3552
3682
|
// For other scenarios,
|
|
3553
3683
|
// 1. If sessionStart is undefined, then it's a new session.
|
|
3554
3684
|
// Mark it as sessionStart.
|
|
3555
3685
|
// 2. If sessionStart is true, then need to flip it for the future events.
|
|
3556
|
-
if(sessionInfo.sessionStart===undefined){sessionInfo={
|
|
3686
|
+
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.
|
|
3557
3687
|
state.session.sessionInfo.value=sessionInfo;if(state.lifecycle.status.value!=='readyExecuted'){// Force update the storage as the 'effect' blocks are not getting triggered
|
|
3558
3688
|
// when processing preload buffered requests
|
|
3559
|
-
this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session=state.session;const{manualTrack,autoTrack,timeout,cutOff}=session.sessionInfo.value;if(autoTrack){const sessionInfo={
|
|
3689
|
+
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();}}/**
|
|
3560
3690
|
* Reset state values
|
|
3561
3691
|
* @param options options for reset
|
|
3562
3692
|
* @returns
|
|
@@ -3566,13 +3696,13 @@ this.syncValueToStorage('sessionInfo');}}resetAndStartNewSession(){const session
|
|
|
3566
3696
|
*/setUserId(userId){state.session.userId.value=this.isPersistenceEnabledForStorageEntry('userId')&&userId?userId:DEFAULT_USER_SESSION_VALUES.userId;}/**
|
|
3567
3697
|
* Set user traits
|
|
3568
3698
|
* @param traits
|
|
3569
|
-
*/setUserTraits(traits){state.session.userTraits.value=this.isPersistenceEnabledForStorageEntry('userTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight(state.session.userTraits.value
|
|
3699
|
+
*/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;}/**
|
|
3570
3700
|
* Set group Id
|
|
3571
3701
|
* @param groupId
|
|
3572
3702
|
*/setGroupId(groupId){state.session.groupId.value=this.isPersistenceEnabledForStorageEntry('groupId')&&groupId?groupId:DEFAULT_USER_SESSION_VALUES.groupId;}/**
|
|
3573
3703
|
* Set group traits
|
|
3574
3704
|
* @param traits
|
|
3575
|
-
*/setGroupTraits(traits){state.session.groupTraits.value=this.isPersistenceEnabledForStorageEntry('groupTraits')&&isObjectLiteralAndNotNull(traits)?mergeDeepRight(state.session.groupTraits.value
|
|
3705
|
+
*/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;}/**
|
|
3576
3706
|
* Set initial referrer
|
|
3577
3707
|
* @param referrer
|
|
3578
3708
|
*/setInitialReferrer(referrer){state.session.initialReferrer.value=this.isPersistenceEnabledForStorageEntry('initialReferrer')&&referrer?referrer:DEFAULT_USER_SESSION_VALUES.initialReferrer;}/**
|
|
@@ -3603,7 +3733,7 @@ state.session.sessionInfo.value=finalSessionInfo;}/**
|
|
|
3603
3733
|
const defaultOptionalPluginsList=allOptionalPlugins;
|
|
3604
3734
|
|
|
3605
3735
|
const normalizeLoadOptions=(loadOptionsFromState,loadOptions)=>{// TODO: Maybe add warnings for invalid values
|
|
3606
|
-
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
|
|
3736
|
+
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;};
|
|
3607
3737
|
|
|
3608
3738
|
const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATIONS_QUEUE_EXT_POINT_PREFIX='destinationsEventsQueue';const DMT_EXT_POINT_PREFIX='transformEvent';
|
|
3609
3739
|
|
|
@@ -3619,7 +3749,7 @@ const DATA_PLANE_QUEUE_EXT_POINT_PREFIX='dataplaneEventsQueue';const DESTINATION
|
|
|
3619
3749
|
* @returns Mutated event with final integrations config
|
|
3620
3750
|
*/const getFinalEvent=(event,state)=>{const finalEvent=clone(event);// Merge the destination specific integrations config with the event's integrations config
|
|
3621
3751
|
// In general, the preference is given to the event's integrations config
|
|
3622
|
-
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
|
|
3752
|
+
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';};
|
|
3623
3753
|
|
|
3624
3754
|
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));}};
|
|
3625
3755
|
|
|
@@ -3634,12 +3764,12 @@ const safelyInvokeCallback=(callback,args,apiName,logger)=>{if(!isDefined(callba
|
|
|
3634
3764
|
*/constructor(pluginsManager,storeManager,httpClient,errorHandler,logger){this.pluginsManager=pluginsManager;this.errorHandler=errorHandler;this.httpClient=httpClient;this.logger=logger;this.storeManager=storeManager;}/**
|
|
3635
3765
|
* Initializes the event repository
|
|
3636
3766
|
*/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
|
|
3637
|
-
j(()=>{if(state.nativeDestinations.clientDestinationsReady.value===true){this.destinationsEventsQueue
|
|
3767
|
+
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
|
|
3638
3768
|
// However, events will be enqueued for now.
|
|
3639
3769
|
// At the time of processing the events, the integrations config data from destinations
|
|
3640
3770
|
// is merged into the event object
|
|
3641
|
-
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
|
|
3642
|
-
if(state.loadOptions.value.bufferDataPlaneEventsUntilReady===true){timeoutId=globalThis.setTimeout(()=>{if(this.dataplaneEventsQueue
|
|
3771
|
+
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
|
|
3772
|
+
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();}}/**
|
|
3643
3773
|
* Enqueues the event for processing
|
|
3644
3774
|
* @param event RudderEvent object
|
|
3645
3775
|
* @param callback API callback function
|
|
@@ -3648,15 +3778,15 @@ const apiName=`${event.type.charAt(0).toUpperCase()}${event.type.slice(1)}${API_
|
|
|
3648
3778
|
|
|
3649
3779
|
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);
|
|
3650
3780
|
|
|
3651
|
-
|
|
3781
|
+
const _excluded=["context"];/*
|
|
3652
3782
|
* Analytics class with lifecycle based on state ad user triggered events
|
|
3653
3783
|
*/class Analytics{/**
|
|
3654
3784
|
* Initialize services and components or use default ones if singletons
|
|
3655
3785
|
*/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);}/**
|
|
3656
3786
|
* Start application lifecycle if not already started
|
|
3657
|
-
*/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
|
|
3787
|
+
*/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
|
|
3658
3788
|
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
|
|
3659
|
-
this.logger.setMinLogLevel(state.loadOptions.value.logLevel
|
|
3789
|
+
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
|
|
3660
3790
|
setExposedGlobal('state',state,writeKey);// Configure initial config of any services or components here
|
|
3661
3791
|
// State application lifecycle
|
|
3662
3792
|
this.startLifecycle();}setCustomContext(context){if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['setCustomContext',context]];return;}this.customContextStore.set(context);}getCustomContext(){return this.customContextStore.get();}clearCustomContext(){if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,['clearCustomContext']];return;}this.customContextStore.clear();}// Start lifecycle methods
|
|
@@ -3672,15 +3802,15 @@ if(state.consents.preConsent.value.enabled===true){state.lifecycle.status.value=
|
|
|
3672
3802
|
* Process the buffer preloaded events by passing their arguments to the respective facade methods
|
|
3673
3803
|
*/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);}/**
|
|
3674
3804
|
* Load configuration
|
|
3675
|
-
*/loadConfig(){if(state.lifecycle.writeKey.value){this.httpClient.setAuthHeader(state.lifecycle.writeKey.value);}this.configManager
|
|
3805
|
+
*/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();}/**
|
|
3676
3806
|
* Initialize the storage and event queue
|
|
3677
|
-
*/onPluginsReady(){
|
|
3678
|
-
this.storeManager
|
|
3679
|
-
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager
|
|
3680
|
-
this.eventManager
|
|
3807
|
+
*/onPluginsReady(){var _this$storeManager,_this$userSessionMana,_this$eventManager;// Initialize storage
|
|
3808
|
+
(_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
|
|
3809
|
+
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
|
|
3810
|
+
(_this$eventManager=this.eventManager)===null||_this$eventManager===void 0||_this$eventManager.init();// Mark the SDK as initialized
|
|
3681
3811
|
state.lifecycle.status.value='initialized';}/**
|
|
3682
3812
|
* Load plugins
|
|
3683
|
-
*/onConfigured(){this.pluginsManager
|
|
3813
|
+
*/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?
|
|
3684
3814
|
// registerCustomPlugins(state.loadOptions.value.customPlugins);
|
|
3685
3815
|
}/**
|
|
3686
3816
|
* Trigger onLoaded callback if any is provided in config & emit initialised event
|
|
@@ -3699,12 +3829,12 @@ dispatchSDKEvent('RSA_Ready');}/**
|
|
|
3699
3829
|
*/processBufferedEvents(){// This logic has been intentionally implemented without a simple
|
|
3700
3830
|
// for-loop as the individual events that are processed may
|
|
3701
3831
|
// add more events to the buffer (this is needed for the consent API)
|
|
3702
|
-
let bufferedEvents=state.eventBuffer.toBeProcessedArray.value;while(bufferedEvents.length>0){const bufferedEvent=bufferedEvents.shift();state.eventBuffer.toBeProcessedArray.value=bufferedEvents;if(bufferedEvent){this.processBufferedEvent(bufferedEvent);}bufferedEvents=state.eventBuffer.toBeProcessedArray.value;}}processBufferedEvent(bufferedEvent){switch(bufferedEvent[0]){case 'setCustomContext':this.setCustomContext(bufferedEvent[1]);break;case 'clearCustomContext':this.clearCustomContext();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;}}}getInvocationContext(preservedCustomContext){if(preservedCustomContext===undefined){return this.customContextStore.get();}const preparedContext=prepareCustomContextUpdate(preservedCustomContext,this.logger);return preparedContext
|
|
3832
|
+
let bufferedEvents=state.eventBuffer.toBeProcessedArray.value;while(bufferedEvents.length>0){const bufferedEvent=bufferedEvents.shift();state.eventBuffer.toBeProcessedArray.value=bufferedEvents;if(bufferedEvent){this.processBufferedEvent(bufferedEvent);}bufferedEvents=state.eventBuffer.toBeProcessedArray.value;}}processBufferedEvent(bufferedEvent){switch(bufferedEvent[0]){case 'setCustomContext':this.setCustomContext(bufferedEvent[1]);break;case 'clearCustomContext':this.clearCustomContext();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;}}}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:{};}/**
|
|
3703
3833
|
* Load device mode destinations
|
|
3704
|
-
*/loadDestinations(){
|
|
3834
|
+
*/loadDestinations(){var _this$pluginsManager4,_this$pluginsManager5;// If the integrations load is already triggered or completed, skip the rest of the logic
|
|
3705
3835
|
if(state.lifecycle.status.value==='destinationsLoading'||state.nativeDestinations.clientDestinationsReady.value===true){return;}// Set in state the desired activeDestinations to inject in DOM
|
|
3706
|
-
this.pluginsManager
|
|
3707
|
-
state.lifecycle.status.value='destinationsLoading';this.pluginsManager
|
|
3836
|
+
(_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
|
|
3837
|
+
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
|
|
3708
3838
|
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;});}});}/**
|
|
3709
3839
|
* Move to the ready state
|
|
3710
3840
|
*/// eslint-disable-next-line class-methods-use-this
|
|
@@ -3716,31 +3846,31 @@ ready(callback,isBufferedInvocation=false){const type='ready';if(!state.lifecycl
|
|
|
3716
3846
|
* If destinations are loaded or no integration is available for loading
|
|
3717
3847
|
* execute the callback immediately else push the callbacks to a queue that
|
|
3718
3848
|
* will be executed after loading completes
|
|
3719
|
-
*/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(!state.lifecycle.loaded.value){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.eventManager
|
|
3849
|
+
*/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(!state.lifecycle.loaded.value){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.
|
|
3720
3850
|
// Send automatic ad blocked page event if ad-blockers are detected on the page
|
|
3721
3851
|
// Check page category to avoid infinite loop
|
|
3722
3852
|
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
|
|
3723
3853
|
// in v3 implementation
|
|
3724
|
-
path:ADBLOCK_PAGE_PATH},state.loadOptions.value.sendAdblockPageOptions),isBufferedInvocation,invocationContext);}}track(payload,isBufferedInvocation=false,preservedCustomContext){const type='track';if(!state.lifecycle.loaded.value){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.eventManager
|
|
3725
|
-
if(!isNull(payload.userId)){this.userSessionManager
|
|
3726
|
-
if(!isNull(payload.groupId)){this.userSessionManager
|
|
3727
|
-
if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,anonymousId,rudderAmpLinkerParam]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);this.userSessionManager
|
|
3854
|
+
path:ADBLOCK_PAGE_PATH},state.loadOptions.value.sendAdblockPageOptions),isBufferedInvocation,invocationContext);}}track(payload,isBufferedInvocation=false,preservedCustomContext){var _this$eventManager3;const type='track';if(!state.lifecycle.loaded.value){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(!state.lifecycle.loaded.value){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){this.reset();}// `null` value indicates that previous user ID needs to be retained
|
|
3855
|
+
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(!state.lifecycle.loaded.value){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(!state.lifecycle.loaded.value){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
|
|
3856
|
+
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(!state.lifecycle.loaded.value){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
|
|
3857
|
+
if(!state.lifecycle.loaded.value){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
|
|
3728
3858
|
getUserId(){return state.session.userId.value;}// eslint-disable-next-line class-methods-use-this
|
|
3729
3859
|
getUserTraits(){return state.session.userTraits.value;}// eslint-disable-next-line class-methods-use-this
|
|
3730
3860
|
getGroupId(){return state.session.groupId.value;}// eslint-disable-next-line class-methods-use-this
|
|
3731
|
-
getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId,isBufferedInvocation=false){const type='startSession';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,sessionId]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);this.userSessionManager
|
|
3732
|
-
getSessionId(){const sessionId=this.userSessionManager
|
|
3733
|
-
if(state.consents.enabled.value&&!state.consents.initialized.value){this.pluginsManager
|
|
3734
|
-
this.storeManager
|
|
3735
|
-
this.userSessionManager
|
|
3736
|
-
this.eventManager
|
|
3861
|
+
getGroupTraits(){return state.session.groupTraits.value;}startSession(sessionId,isBufferedInvocation=false){var _this$userSessionMana0;const type='startSession';if(!state.lifecycle.loaded.value){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(!state.lifecycle.loaded.value){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
|
|
3862
|
+
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(!state.lifecycle.loaded.value){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
|
|
3863
|
+
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
|
|
3864
|
+
(_this$storeManager2=this.storeManager)===null||_this$storeManager2===void 0||_this$storeManager2.initializeStorageState();// Re-init user session manager
|
|
3865
|
+
(_this$userSessionMana11=this.userSessionManager)===null||_this$userSessionMana11===void 0||_this$userSessionMana11.syncStorageDataToState();// Resume event manager to process the events to destinations
|
|
3866
|
+
(_this$eventManager7=this.eventManager)===null||_this$eventManager7===void 0||_this$eventManager7.resume();this.loadDestinations();this.sendTrackingEvents(isBufferedInvocation);}sendTrackingEvents(isBufferedInvocation){// If isBufferedInvocation is true, then the tracking events will be added to the end of the
|
|
3737
3867
|
// events buffer array so that any other preload events (mainly from query string API) will be processed first.
|
|
3738
|
-
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
|
|
3868
|
+
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);}/**
|
|
3739
3869
|
* Add a custom integration for a custom destination.
|
|
3740
3870
|
* @param destinationId - The ID of the custom destination from the RudderStack dashboard.
|
|
3741
3871
|
* @param integration - The custom integration object.
|
|
3742
3872
|
* @param isBufferedInvocation - Whether the invocation is buffered.
|
|
3743
|
-
*/addCustomIntegration(destinationId,integration,isBufferedInvocation=false){const type='addCustomIntegration';if(isBufferedInvocation){this.errorHandler.leaveBreadcrumb(`New ${type} invocation`);this.pluginsManager
|
|
3873
|
+
*/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
|
|
3744
3874
|
}
|
|
3745
3875
|
|
|
3746
3876
|
/*
|
|
@@ -3748,11 +3878,9 @@ if(state.consents.postConsent.value.trackConsent){const trackOptions=trackArgume
|
|
|
3748
3878
|
* expose overloaded methods
|
|
3749
3879
|
* handle multiple Analytics instances
|
|
3750
3880
|
* consume SDK preload event buffer
|
|
3751
|
-
*/class RudderAnalytics{//
|
|
3752
|
-
//
|
|
3753
|
-
|
|
3754
|
-
analyticsInstances={};defaultAnalyticsKey='';logger=defaultLogger;// Singleton with constructor bind methods
|
|
3755
|
-
constructor(){try{if(RudderAnalytics.globalSingleton){// START-NO-SONAR-SCAN
|
|
3881
|
+
*/class RudderAnalytics{// Singleton with constructor bind methods
|
|
3882
|
+
constructor(){// END-NO-SONAR-SCAN
|
|
3883
|
+
_defineProperty(this,"analyticsInstances",{});_defineProperty(this,"defaultAnalyticsKey",'');_defineProperty(this,"logger",defaultLogger);try{if(RudderAnalytics.globalSingleton){// START-NO-SONAR-SCAN
|
|
3756
3884
|
// eslint-disable-next-line no-constructor-return
|
|
3757
3885
|
return RudderAnalytics.globalSingleton;// END-NO-SONAR-SCAN
|
|
3758
3886
|
}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
|
|
@@ -3780,15 +3908,15 @@ if(isString(writeKey)&&writeKey){this.defaultAnalyticsKey=writeKey;}}/**
|
|
|
3780
3908
|
* @param dataPlaneUrl Data plane URL
|
|
3781
3909
|
* @param loadOptions Additional options for loading the SDK
|
|
3782
3910
|
* @returns none
|
|
3783
|
-
*/load(writeKey,dataPlaneUrl,loadOptions){try{if(this.analyticsInstances[writeKey]){return;}this.setDefaultInstanceKey(writeKey);// Track page loaded lifecycle event if enabled
|
|
3911
|
+
*/load(writeKey,dataPlaneUrl,loadOptions){try{var _this$getAnalyticsIns;if(this.analyticsInstances[writeKey]){return;}this.setDefaultInstanceKey(writeKey);// Track page loaded lifecycle event if enabled
|
|
3784
3912
|
this.trackPageLifecycleEvents(loadOptions);// Get the preloaded events array from global buffer instead of window.rudderanalytics
|
|
3785
3913
|
// as the constructor must have already pushed the events to the global buffer
|
|
3786
3914
|
const preloadedEventsArray=getExposedGlobal(GLOBAL_PRELOAD_BUFFER);// The array will be mutated in the below method
|
|
3787
|
-
promotePreloadedConsentEventsToTop(preloadedEventsArray);setExposedGlobal(GLOBAL_PRELOAD_BUFFER,clone(preloadedEventsArray));this.getAnalyticsInstance(writeKey)
|
|
3915
|
+
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);}}/**
|
|
3788
3916
|
* A function to track page lifecycle events like page loaded and page unloaded
|
|
3789
3917
|
* @param loadOptions
|
|
3790
3918
|
* @returns
|
|
3791
|
-
*/trackPageLifecycleEvents(loadOptions){const{autoTrack,useBeacon}=loadOptions
|
|
3919
|
+
*/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
|
|
3792
3920
|
// if at least one of the autoTrack options is enabled
|
|
3793
3921
|
// IMPORTANT: make sure this is done at the end as it depends on the above states
|
|
3794
3922
|
state.autoTrack.enabled.value=autoTrackEnabled||pageLifecycleEnabled;if(!pageLifecycleEnabled){return;}this.setupPageUnloadTracking(events,useBeacon,options);}/**
|
|
@@ -3796,7 +3924,7 @@ state.autoTrack.enabled.value=autoTrackEnabled||pageLifecycleEnabled;if(!pageLif
|
|
|
3796
3924
|
* @param events
|
|
3797
3925
|
* @param useBeacon
|
|
3798
3926
|
* @param options
|
|
3799
|
-
*/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},{
|
|
3927
|
+
*/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
|
|
3800
3928
|
this.logger.warn(PAGE_UNLOAD_ON_BEACON_DISABLED_WARNING(RSA));}}}/**
|
|
3801
3929
|
* Trigger load event in buffer queue if exists and stores the
|
|
3802
3930
|
* remaining preloaded events array in global object
|
|
@@ -3810,22 +3938,22 @@ loadEvent.shift();// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
3810
3938
|
// @ts-ignore
|
|
3811
3939
|
this.load.apply(null,loadEvent);}}/**
|
|
3812
3940
|
* Get ready callback arguments and forward to ready call
|
|
3813
|
-
*/ready(callback){try{this.getAnalyticsInstance()
|
|
3941
|
+
*/ready(callback){try{var _this$getAnalyticsIns2;(_this$getAnalyticsIns2=this.getAnalyticsInstance())===null||_this$getAnalyticsIns2===void 0||_this$getAnalyticsIns2.ready(getSanitizedValue(callback));}catch(error){dispatchErrorEvent(error);}}/**
|
|
3814
3942
|
* Process page arguments and forward to page call
|
|
3815
3943
|
*/// These overloads should be same as AnalyticsPageMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
3816
|
-
page(category,name,properties,options,callback){try{this.getAnalyticsInstance()
|
|
3944
|
+
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);}}/**
|
|
3817
3945
|
* Process track arguments and forward to page call
|
|
3818
3946
|
*/// These overloads should be same as AnalyticsTrackMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
3819
|
-
track(event,properties,options,callback){try{this.getAnalyticsInstance()
|
|
3947
|
+
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);}}/**
|
|
3820
3948
|
* Process identify arguments and forward to page call
|
|
3821
3949
|
*/// These overloads should be same as AnalyticsIdentifyMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
3822
|
-
identify(userId,traits,options,callback){try{this.getAnalyticsInstance()
|
|
3950
|
+
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);}}/**
|
|
3823
3951
|
* Process alias arguments and forward to page call
|
|
3824
3952
|
*/// These overloads should be same as AnalyticsAliasMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
3825
|
-
alias(to,from,options,callback){try{this.getAnalyticsInstance()
|
|
3953
|
+
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);}}/**
|
|
3826
3954
|
* Process group arguments and forward to page call
|
|
3827
3955
|
*/// These overloads should be same as AnalyticsGroupMethod in @rudderstack/analytics-js-common/types/IRudderAnalytics
|
|
3828
|
-
group(groupId,traits,options,callback){try{this.getAnalyticsInstance()
|
|
3956
|
+
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);}}/**
|
|
3829
3957
|
* Reset the analytics instance
|
|
3830
3958
|
* @param options Reset options. Except for anonymousId, initialReferrer, and initialReferringDomain
|
|
3831
3959
|
* all other values will be reset by default.
|
|
@@ -3852,6 +3980,8 @@ group(groupId,traits,options,callback){try{this.getAnalyticsInstance()?.group(gr
|
|
|
3852
3980
|
* @param resetAnonymousId Reset anonymous ID
|
|
3853
3981
|
* @returns none
|
|
3854
3982
|
* @deprecated Use reset(options) instead
|
|
3855
|
-
*/reset(options){try{this.getAnalyticsInstance()
|
|
3983
|
+
*/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
|
|
3984
|
+
// eslint-disable-next-line sonarjs/public-static-readonly
|
|
3985
|
+
_defineProperty(RudderAnalytics,"globalSingleton",null);
|
|
3856
3986
|
|
|
3857
3987
|
exports.RudderAnalytics = RudderAnalytics;
|