@rudderstack/analytics-js 3.11.6 → 3.11.7
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +12 -0
- package/dist/npm/legacy/bundled/cjs/index.cjs +52 -33
- package/dist/npm/legacy/bundled/esm/index.mjs +52 -33
- package/dist/npm/legacy/bundled/umd/index.js +52 -33
- package/dist/npm/legacy/cjs/index.cjs +52 -33
- package/dist/npm/legacy/content-script/cjs/index.cjs +52 -33
- package/dist/npm/legacy/content-script/esm/index.mjs +52 -33
- package/dist/npm/legacy/content-script/umd/index.js +52 -33
- package/dist/npm/legacy/esm/index.mjs +52 -33
- package/dist/npm/legacy/umd/index.js +52 -33
- package/dist/npm/modern/bundled/cjs/index.cjs +52 -33
- package/dist/npm/modern/bundled/esm/index.mjs +52 -33
- package/dist/npm/modern/bundled/umd/index.js +52 -33
- package/dist/npm/modern/cjs/index.cjs +51 -32
- package/dist/npm/modern/content-script/cjs/index.cjs +52 -33
- package/dist/npm/modern/content-script/esm/index.mjs +52 -33
- package/dist/npm/modern/content-script/umd/index.js +52 -33
- package/dist/npm/modern/esm/index.mjs +51 -32
- package/dist/npm/modern/umd/index.js +51 -32
- package/package.json +1 -1
@@ -273,6 +273,10 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
273
273
|
* @param value input value
|
274
274
|
* @returns boolean
|
275
275
|
*/const isNullOrUndefined=value=>isNull(value)||isUndefined(value);/**
|
276
|
+
* Checks if the input is a BigInt
|
277
|
+
* @param value input value
|
278
|
+
* @returns True if the input is a BigInt
|
279
|
+
*/const isBigInt=value=>typeof value==='bigint';/**
|
276
280
|
* A function to check given value is defined
|
277
281
|
* @param value input value
|
278
282
|
* @returns boolean
|
@@ -290,6 +294,8 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
290
294
|
* @returns true if the input is an instance of Error and false otherwise
|
291
295
|
*/const isTypeOfError=obj=>obj instanceof Error;
|
292
296
|
|
297
|
+
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
298
|
+
|
293
299
|
const getValueByPath=(obj,keyPath)=>{const pathParts=keyPath.split('.');return path(pathParts,obj);};const hasValueByPath=(obj,path)=>Boolean(getValueByPath(obj,path));const isObject=value=>typeof value==='object';/**
|
294
300
|
* Checks if the input is an object literal or built-in object type and not null
|
295
301
|
* @param value Input value
|
@@ -311,7 +317,28 @@ mergeDeepRight(mergedArray[index],value):value;});return mergedArray;};const mer
|
|
311
317
|
* A utility to recursively remove undefined and null values from an object
|
312
318
|
* @param obj input object
|
313
319
|
* @returns a new object
|
314
|
-
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};
|
320
|
+
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};const getReplacer=logger=>{const ancestors=[];// Array to track ancestor objects
|
321
|
+
// Using a regular function to use `this` for the parent context
|
322
|
+
return function replacer(key,value){if(isBigInt(value)){return '[BigInt]';// Replace BigInt values
|
323
|
+
}// `this` is the object that value is contained in, i.e., its direct parent.
|
324
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
325
|
+
// @ts-ignore-next-line
|
326
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();// Remove ancestors that are no longer part of the chain
|
327
|
+
}// Check for circular references (if the value is already in the ancestors)
|
328
|
+
if(ancestors.includes(value)){return '[Circular Reference]';}// Add current value to ancestors
|
329
|
+
ancestors.push(value);return value;};};const traverseWithThis=(obj,replacer)=>{// Create a new result object or array
|
330
|
+
const result=Array.isArray(obj)?[]:{};// Traverse object properties or array elements
|
331
|
+
// eslint-disable-next-line no-restricted-syntax
|
332
|
+
for(const key in obj){if(Object.hasOwnProperty.call(obj,key)){const value=obj[key];// Recursively apply the replacer and traversal
|
333
|
+
const sanitizedValue=replacer.call(obj,key,value);// If the value is an object or array, continue traversal
|
334
|
+
if(isObjectLiteralAndNotNull(sanitizedValue)||Array.isArray(sanitizedValue)){result[key]=traverseWithThis(sanitizedValue,replacer);}else {result[key]=sanitizedValue;}}}return result;};/**
|
335
|
+
* Recursively traverses an object similar to JSON.stringify,
|
336
|
+
* sanitizing BigInts and circular references
|
337
|
+
* @param value Input object
|
338
|
+
* @param logger Logger instance
|
339
|
+
* @returns Sanitized value
|
340
|
+
*/const getSanitizedValue=(value,logger)=>{const replacer=getReplacer();// This is needed for registering the first ancestor
|
341
|
+
const newValue=replacer.call(value,'',value);if(isObjectLiteralAndNotNull(value)||Array.isArray(value)){return traverseWithThis(value,replacer);}return newValue;};
|
315
342
|
|
316
343
|
const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value=>value.replace(/ {2,}/g,' ');const removeLeadingPeriod=value=>value.replace(/^\.+/,'');/**
|
317
344
|
* A function to convert values to string
|
@@ -328,59 +355,37 @@ const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value
|
|
328
355
|
* @returns base64 encoded string
|
329
356
|
*/const toBase64=value=>bytesToBase64(new TextEncoder().encode(value));
|
330
357
|
|
331
|
-
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
332
|
-
|
333
|
-
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
334
|
-
// eslint-disable-next-line func-names
|
335
|
-
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
336
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
337
|
-
// @ts-ignore-next-line
|
338
|
-
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
339
|
-
* Utility method for JSON stringify object excluding null values & circular references
|
340
|
-
*
|
341
|
-
* @param {*} value input
|
342
|
-
* @param {boolean} excludeNull if it should exclude nul or not
|
343
|
-
* @param {function} logger optional logger methods for warning
|
344
|
-
* @returns string
|
345
|
-
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};/**
|
346
|
-
* Recursively traverses an object similar to JSON.stringify,
|
347
|
-
* sanitizing BigInts and circular references
|
348
|
-
* @param value Input object
|
349
|
-
* @param logger Logger instance
|
350
|
-
* @returns Sanitized value
|
351
|
-
*/const getSanitizedValue=(value,logger)=>value;
|
352
|
-
|
353
358
|
// if yes make them null instead of omitting in overloaded cases
|
354
359
|
/*
|
355
360
|
* Normalise the overloaded arguments of the page call facade
|
356
|
-
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const
|
361
|
+
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const payload={category:category,name:name,properties:properties,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.category=category;payload.name=name;payload.properties=properties;payload.options=undefined;payload.callback=options;}if(isFunction(properties)){payload.category=category;payload.name=name;payload.properties=undefined;payload.options=undefined;payload.callback=properties;}if(isFunction(name)){payload.category=category;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=name;}if(isFunction(category)){payload.category=undefined;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=category;}if(isObjectLiteralAndNotNull(category)){payload.name=undefined;payload.category=undefined;payload.properties=category;if(!isFunction(name)){payload.options=name;}else {payload.options=undefined;}}else if(isObjectLiteralAndNotNull(name)){payload.name=undefined;payload.properties=name;if(!isFunction(properties)){payload.options=properties;}else {payload.options=undefined;}}// if the category argument alone is provided b/w category and name,
|
357
362
|
// use it as name and set category to undefined
|
358
|
-
if(isString(
|
363
|
+
if(isString(category)&&!isString(name)){payload.category=undefined;payload.name=category;}// Rest of the code is just to clean up undefined values
|
359
364
|
// and set some proper defaults
|
360
365
|
// Also, to clone the incoming object type arguments
|
361
366
|
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
|
362
367
|
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{...(nameForProperties&&{name:nameForProperties}),...(categoryForProperties&&{category:categoryForProperties})});return payload;};/*
|
363
368
|
* Normalise the overloaded arguments of the track call facade
|
364
|
-
*/const trackArgumentsToCallOptions=(event,properties,options,callback)=>{const
|
369
|
+
*/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
|
365
370
|
// and set some proper defaults
|
366
371
|
// Also, to clone the incoming object type arguments
|
367
372
|
payload.properties=isDefinedAndNotNull(payload.properties)?clone(payload.properties):{};if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
368
373
|
* Normalise the overloaded arguments of the identify call facade
|
369
|
-
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const
|
374
|
+
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const payload={userId:userId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.userId=userId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.userId=userId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(userId)||isNull(userId)){// Explicitly set null to prevent resetting the existing value
|
370
375
|
// in the Analytics class
|
371
|
-
payload.userId=null;payload.traits=
|
376
|
+
payload.userId=null;payload.traits=userId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
372
377
|
// and set some proper defaults
|
373
378
|
// Also, to clone the incoming object type arguments
|
374
379
|
payload.userId=tryStringify(payload.userId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
375
380
|
* Normalise the overloaded arguments of the alias call facade
|
376
|
-
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const
|
381
|
+
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const payload={to,from:from,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.to=to;payload.from=from;payload.options=undefined;payload.callback=options;}if(isFunction(from)){payload.to=to;payload.from=undefined;payload.options=undefined;payload.callback=from;}else if(isObjectLiteralAndNotNull(from)||isNull(from)){payload.to=to;payload.from=undefined;payload.options=from;}// Rest of the code is just to clean up undefined values
|
377
382
|
// and set some proper defaults
|
378
383
|
// Also, to clone the incoming object type arguments
|
379
384
|
if(isDefined(payload.to)){payload.to=tryStringify(payload.to);}if(isDefined(payload.from)){payload.from=tryStringify(payload.from);}else {payload.from=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
380
385
|
* Normalise the overloaded arguments of the group call facade
|
381
|
-
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const
|
386
|
+
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const payload={groupId:groupId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.groupId=groupId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.groupId=groupId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(groupId)||isNull(groupId)){// Explicitly set null to prevent resetting the existing value
|
382
387
|
// in the Analytics class
|
383
|
-
payload.groupId=null;payload.traits=
|
388
|
+
payload.groupId=null;payload.traits=groupId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
384
389
|
// and set some proper defaults
|
385
390
|
// Also, to clone the incoming object type arguments
|
386
391
|
payload.groupId=tryStringify(payload.groupId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};
|
@@ -428,6 +433,20 @@ const getFormattedTimestamp=date=>date.toISOString();/**
|
|
428
433
|
* @returns ISO formatted timestamp string
|
429
434
|
*/const getCurrentTimeFormatted=()=>getFormattedTimestamp(new Date());
|
430
435
|
|
436
|
+
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
437
|
+
// eslint-disable-next-line func-names
|
438
|
+
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
439
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
440
|
+
// @ts-ignore-next-line
|
441
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
442
|
+
* Utility method for JSON stringify object excluding null values & circular references
|
443
|
+
*
|
444
|
+
* @param {*} value input
|
445
|
+
* @param {boolean} excludeNull if it should exclude nul or not
|
446
|
+
* @param {function} logger optional logger methods for warning
|
447
|
+
* @returns string
|
448
|
+
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};
|
449
|
+
|
431
450
|
const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
432
451
|
* Get mutated error with issue prepended to error message
|
433
452
|
* @param err Original error
|
@@ -435,7 +454,7 @@ const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
|
435
454
|
* @returns Instance of Error with message prepended with issue
|
436
455
|
*/const getMutatedError=(err,issue)=>{let finalError=err;if(!isTypeOfError(err)){finalError=new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}else {finalError.message=`${issue}: ${err.message}`;}return finalError;};const dispatchErrorEvent=error=>{if(isTypeOfError(error)){error.stack=`${error.stack??''}\n${MANUAL_ERROR_IDENTIFIER}`;}globalThis.dispatchEvent(new ErrorEvent('error',{error}));};
|
437
456
|
|
438
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.
|
457
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.7';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
|
439
458
|
|
440
459
|
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';
|
441
460
|
|
@@ -273,6 +273,10 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
273
273
|
* @param value input value
|
274
274
|
* @returns boolean
|
275
275
|
*/const isNullOrUndefined=value=>isNull(value)||isUndefined(value);/**
|
276
|
+
* Checks if the input is a BigInt
|
277
|
+
* @param value input value
|
278
|
+
* @returns True if the input is a BigInt
|
279
|
+
*/const isBigInt=value=>typeof value==='bigint';/**
|
276
280
|
* A function to check given value is defined
|
277
281
|
* @param value input value
|
278
282
|
* @returns boolean
|
@@ -290,6 +294,8 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
290
294
|
* @returns true if the input is an instance of Error and false otherwise
|
291
295
|
*/const isTypeOfError=obj=>obj instanceof Error;
|
292
296
|
|
297
|
+
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
298
|
+
|
293
299
|
const getValueByPath=(obj,keyPath)=>{const pathParts=keyPath.split('.');return path(pathParts,obj);};const hasValueByPath=(obj,path)=>Boolean(getValueByPath(obj,path));const isObject=value=>typeof value==='object';/**
|
294
300
|
* Checks if the input is an object literal or built-in object type and not null
|
295
301
|
* @param value Input value
|
@@ -311,7 +317,28 @@ mergeDeepRight(mergedArray[index],value):value;});return mergedArray;};const mer
|
|
311
317
|
* A utility to recursively remove undefined and null values from an object
|
312
318
|
* @param obj input object
|
313
319
|
* @returns a new object
|
314
|
-
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};
|
320
|
+
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};const getReplacer=logger=>{const ancestors=[];// Array to track ancestor objects
|
321
|
+
// Using a regular function to use `this` for the parent context
|
322
|
+
return function replacer(key,value){if(isBigInt(value)){return '[BigInt]';// Replace BigInt values
|
323
|
+
}// `this` is the object that value is contained in, i.e., its direct parent.
|
324
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
325
|
+
// @ts-ignore-next-line
|
326
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();// Remove ancestors that are no longer part of the chain
|
327
|
+
}// Check for circular references (if the value is already in the ancestors)
|
328
|
+
if(ancestors.includes(value)){return '[Circular Reference]';}// Add current value to ancestors
|
329
|
+
ancestors.push(value);return value;};};const traverseWithThis=(obj,replacer)=>{// Create a new result object or array
|
330
|
+
const result=Array.isArray(obj)?[]:{};// Traverse object properties or array elements
|
331
|
+
// eslint-disable-next-line no-restricted-syntax
|
332
|
+
for(const key in obj){if(Object.hasOwnProperty.call(obj,key)){const value=obj[key];// Recursively apply the replacer and traversal
|
333
|
+
const sanitizedValue=replacer.call(obj,key,value);// If the value is an object or array, continue traversal
|
334
|
+
if(isObjectLiteralAndNotNull(sanitizedValue)||Array.isArray(sanitizedValue)){result[key]=traverseWithThis(sanitizedValue,replacer);}else {result[key]=sanitizedValue;}}}return result;};/**
|
335
|
+
* Recursively traverses an object similar to JSON.stringify,
|
336
|
+
* sanitizing BigInts and circular references
|
337
|
+
* @param value Input object
|
338
|
+
* @param logger Logger instance
|
339
|
+
* @returns Sanitized value
|
340
|
+
*/const getSanitizedValue=(value,logger)=>{const replacer=getReplacer();// This is needed for registering the first ancestor
|
341
|
+
const newValue=replacer.call(value,'',value);if(isObjectLiteralAndNotNull(value)||Array.isArray(value)){return traverseWithThis(value,replacer);}return newValue;};
|
315
342
|
|
316
343
|
const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value=>value.replace(/ {2,}/g,' ');const removeLeadingPeriod=value=>value.replace(/^\.+/,'');/**
|
317
344
|
* A function to convert values to string
|
@@ -337,59 +364,37 @@ const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value
|
|
337
364
|
* @returns decoded string
|
338
365
|
*/const fromBase64=value=>new TextDecoder().decode(base64ToBytes(value));
|
339
366
|
|
340
|
-
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
341
|
-
|
342
|
-
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
343
|
-
// eslint-disable-next-line func-names
|
344
|
-
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
345
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
346
|
-
// @ts-ignore-next-line
|
347
|
-
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
348
|
-
* Utility method for JSON stringify object excluding null values & circular references
|
349
|
-
*
|
350
|
-
* @param {*} value input
|
351
|
-
* @param {boolean} excludeNull if it should exclude nul or not
|
352
|
-
* @param {function} logger optional logger methods for warning
|
353
|
-
* @returns string
|
354
|
-
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};/**
|
355
|
-
* Recursively traverses an object similar to JSON.stringify,
|
356
|
-
* sanitizing BigInts and circular references
|
357
|
-
* @param value Input object
|
358
|
-
* @param logger Logger instance
|
359
|
-
* @returns Sanitized value
|
360
|
-
*/const getSanitizedValue=(value,logger)=>value;
|
361
|
-
|
362
367
|
// if yes make them null instead of omitting in overloaded cases
|
363
368
|
/*
|
364
369
|
* Normalise the overloaded arguments of the page call facade
|
365
|
-
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const
|
370
|
+
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const payload={category:category,name:name,properties:properties,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.category=category;payload.name=name;payload.properties=properties;payload.options=undefined;payload.callback=options;}if(isFunction(properties)){payload.category=category;payload.name=name;payload.properties=undefined;payload.options=undefined;payload.callback=properties;}if(isFunction(name)){payload.category=category;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=name;}if(isFunction(category)){payload.category=undefined;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=category;}if(isObjectLiteralAndNotNull(category)){payload.name=undefined;payload.category=undefined;payload.properties=category;if(!isFunction(name)){payload.options=name;}else {payload.options=undefined;}}else if(isObjectLiteralAndNotNull(name)){payload.name=undefined;payload.properties=name;if(!isFunction(properties)){payload.options=properties;}else {payload.options=undefined;}}// if the category argument alone is provided b/w category and name,
|
366
371
|
// use it as name and set category to undefined
|
367
|
-
if(isString(
|
372
|
+
if(isString(category)&&!isString(name)){payload.category=undefined;payload.name=category;}// Rest of the code is just to clean up undefined values
|
368
373
|
// and set some proper defaults
|
369
374
|
// Also, to clone the incoming object type arguments
|
370
375
|
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
|
371
376
|
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{...(nameForProperties&&{name:nameForProperties}),...(categoryForProperties&&{category:categoryForProperties})});return payload;};/*
|
372
377
|
* Normalise the overloaded arguments of the track call facade
|
373
|
-
*/const trackArgumentsToCallOptions=(event,properties,options,callback)=>{const
|
378
|
+
*/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
|
374
379
|
// and set some proper defaults
|
375
380
|
// Also, to clone the incoming object type arguments
|
376
381
|
payload.properties=isDefinedAndNotNull(payload.properties)?clone(payload.properties):{};if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
377
382
|
* Normalise the overloaded arguments of the identify call facade
|
378
|
-
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const
|
383
|
+
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const payload={userId:userId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.userId=userId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.userId=userId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(userId)||isNull(userId)){// Explicitly set null to prevent resetting the existing value
|
379
384
|
// in the Analytics class
|
380
|
-
payload.userId=null;payload.traits=
|
385
|
+
payload.userId=null;payload.traits=userId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
381
386
|
// and set some proper defaults
|
382
387
|
// Also, to clone the incoming object type arguments
|
383
388
|
payload.userId=tryStringify(payload.userId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
384
389
|
* Normalise the overloaded arguments of the alias call facade
|
385
|
-
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const
|
390
|
+
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const payload={to,from:from,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.to=to;payload.from=from;payload.options=undefined;payload.callback=options;}if(isFunction(from)){payload.to=to;payload.from=undefined;payload.options=undefined;payload.callback=from;}else if(isObjectLiteralAndNotNull(from)||isNull(from)){payload.to=to;payload.from=undefined;payload.options=from;}// Rest of the code is just to clean up undefined values
|
386
391
|
// and set some proper defaults
|
387
392
|
// Also, to clone the incoming object type arguments
|
388
393
|
if(isDefined(payload.to)){payload.to=tryStringify(payload.to);}if(isDefined(payload.from)){payload.from=tryStringify(payload.from);}else {payload.from=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
389
394
|
* Normalise the overloaded arguments of the group call facade
|
390
|
-
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const
|
395
|
+
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const payload={groupId:groupId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.groupId=groupId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.groupId=groupId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(groupId)||isNull(groupId)){// Explicitly set null to prevent resetting the existing value
|
391
396
|
// in the Analytics class
|
392
|
-
payload.groupId=null;payload.traits=
|
397
|
+
payload.groupId=null;payload.traits=groupId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
393
398
|
// and set some proper defaults
|
394
399
|
// Also, to clone the incoming object type arguments
|
395
400
|
payload.groupId=tryStringify(payload.groupId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};
|
@@ -437,6 +442,20 @@ const getFormattedTimestamp=date=>date.toISOString();/**
|
|
437
442
|
* @returns ISO formatted timestamp string
|
438
443
|
*/const getCurrentTimeFormatted=()=>getFormattedTimestamp(new Date());
|
439
444
|
|
445
|
+
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
446
|
+
// eslint-disable-next-line func-names
|
447
|
+
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
448
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
449
|
+
// @ts-ignore-next-line
|
450
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
451
|
+
* Utility method for JSON stringify object excluding null values & circular references
|
452
|
+
*
|
453
|
+
* @param {*} value input
|
454
|
+
* @param {boolean} excludeNull if it should exclude nul or not
|
455
|
+
* @param {function} logger optional logger methods for warning
|
456
|
+
* @returns string
|
457
|
+
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};
|
458
|
+
|
440
459
|
const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
441
460
|
* Get mutated error with issue prepended to error message
|
442
461
|
* @param err Original error
|
@@ -444,7 +463,7 @@ const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
|
444
463
|
* @returns Instance of Error with message prepended with issue
|
445
464
|
*/const getMutatedError=(err,issue)=>{let finalError=err;if(!isTypeOfError(err)){finalError=new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}else {finalError.message=`${issue}: ${err.message}`;}return finalError;};const dispatchErrorEvent=error=>{if(isTypeOfError(error)){error.stack=`${error.stack??''}\n${MANUAL_ERROR_IDENTIFIER}`;}globalThis.dispatchEvent(new ErrorEvent('error',{error}));};
|
446
465
|
|
447
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.
|
466
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.7';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
|
448
467
|
|
449
468
|
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';
|
450
469
|
|
@@ -692,7 +711,7 @@ const removeDuplicateSlashes=str=>str.replace(/\/{2,}/g,'/');/**
|
|
692
711
|
if(isFunction(globalThis.URL)){// eslint-disable-next-line no-new
|
693
712
|
new URL(url);}return URL_PATTERN.test(url);}catch(e){return false;}};
|
694
713
|
|
695
|
-
const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=details.xhr.status;// same as in v1.1
|
714
|
+
const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=getSanitizedValue(details.xhr).status;// same as in v1.1
|
696
715
|
isRetryableNWFailure=xhrStatus===429||xhrStatus>=500&&xhrStatus<600;}return isRetryableNWFailure;};
|
697
716
|
|
698
717
|
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_';
|
@@ -269,6 +269,10 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
269
269
|
* @param value input value
|
270
270
|
* @returns boolean
|
271
271
|
*/const isNullOrUndefined=value=>isNull(value)||isUndefined(value);/**
|
272
|
+
* Checks if the input is a BigInt
|
273
|
+
* @param value input value
|
274
|
+
* @returns True if the input is a BigInt
|
275
|
+
*/const isBigInt=value=>typeof value==='bigint';/**
|
272
276
|
* A function to check given value is defined
|
273
277
|
* @param value input value
|
274
278
|
* @returns boolean
|
@@ -286,6 +290,8 @@ const isFunction=value=>typeof value==='function'&&Boolean(value.constructor&&va
|
|
286
290
|
* @returns true if the input is an instance of Error and false otherwise
|
287
291
|
*/const isTypeOfError=obj=>obj instanceof Error;
|
288
292
|
|
293
|
+
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
294
|
+
|
289
295
|
const getValueByPath=(obj,keyPath)=>{const pathParts=keyPath.split('.');return path(pathParts,obj);};const hasValueByPath=(obj,path)=>Boolean(getValueByPath(obj,path));const isObject=value=>typeof value==='object';/**
|
290
296
|
* Checks if the input is an object literal or built-in object type and not null
|
291
297
|
* @param value Input value
|
@@ -307,7 +313,28 @@ mergeDeepRight(mergedArray[index],value):value;});return mergedArray;};const mer
|
|
307
313
|
* A utility to recursively remove undefined and null values from an object
|
308
314
|
* @param obj input object
|
309
315
|
* @returns a new object
|
310
|
-
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};
|
316
|
+
*/const removeUndefinedAndNullValues=obj=>{const result=pickBy(isDefinedAndNotNull,obj);Object.keys(result).forEach(key=>{const value=result[key];if(isObjectLiteralAndNotNull(value)){result[key]=removeUndefinedAndNullValues(value);}});return result;};const getReplacer=logger=>{const ancestors=[];// Array to track ancestor objects
|
317
|
+
// Using a regular function to use `this` for the parent context
|
318
|
+
return function replacer(key,value){if(isBigInt(value)){return '[BigInt]';// Replace BigInt values
|
319
|
+
}// `this` is the object that value is contained in, i.e., its direct parent.
|
320
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
321
|
+
// @ts-ignore-next-line
|
322
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();// Remove ancestors that are no longer part of the chain
|
323
|
+
}// Check for circular references (if the value is already in the ancestors)
|
324
|
+
if(ancestors.includes(value)){return '[Circular Reference]';}// Add current value to ancestors
|
325
|
+
ancestors.push(value);return value;};};const traverseWithThis=(obj,replacer)=>{// Create a new result object or array
|
326
|
+
const result=Array.isArray(obj)?[]:{};// Traverse object properties or array elements
|
327
|
+
// eslint-disable-next-line no-restricted-syntax
|
328
|
+
for(const key in obj){if(Object.hasOwnProperty.call(obj,key)){const value=obj[key];// Recursively apply the replacer and traversal
|
329
|
+
const sanitizedValue=replacer.call(obj,key,value);// If the value is an object or array, continue traversal
|
330
|
+
if(isObjectLiteralAndNotNull(sanitizedValue)||Array.isArray(sanitizedValue)){result[key]=traverseWithThis(sanitizedValue,replacer);}else {result[key]=sanitizedValue;}}}return result;};/**
|
331
|
+
* Recursively traverses an object similar to JSON.stringify,
|
332
|
+
* sanitizing BigInts and circular references
|
333
|
+
* @param value Input object
|
334
|
+
* @param logger Logger instance
|
335
|
+
* @returns Sanitized value
|
336
|
+
*/const getSanitizedValue=(value,logger)=>{const replacer=getReplacer();// This is needed for registering the first ancestor
|
337
|
+
const newValue=replacer.call(value,'',value);if(isObjectLiteralAndNotNull(value)||Array.isArray(value)){return traverseWithThis(value,replacer);}return newValue;};
|
311
338
|
|
312
339
|
const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value=>value.replace(/ {2,}/g,' ');const removeLeadingPeriod=value=>value.replace(/^\.+/,'');/**
|
313
340
|
* A function to convert values to string
|
@@ -333,59 +360,37 @@ const trim=value=>value.replace(/^\s+|\s+$/gm,'');const removeDoubleSpaces=value
|
|
333
360
|
* @returns decoded string
|
334
361
|
*/const fromBase64=value=>new TextDecoder().decode(base64ToBytes(value));
|
335
362
|
|
336
|
-
const LOG_CONTEXT_SEPARATOR=':: ';const SCRIPT_ALREADY_EXISTS_ERROR=id=>`A script with the id "${id}" is already loaded. Skipping the loading of this script to prevent conflicts.`;const SCRIPT_LOAD_ERROR=(id,url)=>`Failed to load the script with the id "${id}" from URL "${url}".`;const SCRIPT_LOAD_TIMEOUT_ERROR=(id,url,timeout)=>`A timeout of ${timeout} ms occurred while trying to load the script with id "${id}" from URL "${url}".`;const CIRCULAR_REFERENCE_WARNING=(context,key)=>`${context}${LOG_CONTEXT_SEPARATOR}A circular reference has been detected in the object and the property "${key}" has been dropped from the output.`;const JSON_STRINGIFY_WARNING=`Failed to convert the value to a JSON string.`;
|
337
|
-
|
338
|
-
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
339
|
-
// eslint-disable-next-line func-names
|
340
|
-
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
341
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
342
|
-
// @ts-ignore-next-line
|
343
|
-
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
344
|
-
* Utility method for JSON stringify object excluding null values & circular references
|
345
|
-
*
|
346
|
-
* @param {*} value input
|
347
|
-
* @param {boolean} excludeNull if it should exclude nul or not
|
348
|
-
* @param {function} logger optional logger methods for warning
|
349
|
-
* @returns string
|
350
|
-
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};/**
|
351
|
-
* Recursively traverses an object similar to JSON.stringify,
|
352
|
-
* sanitizing BigInts and circular references
|
353
|
-
* @param value Input object
|
354
|
-
* @param logger Logger instance
|
355
|
-
* @returns Sanitized value
|
356
|
-
*/const getSanitizedValue=(value,logger)=>value;
|
357
|
-
|
358
363
|
// if yes make them null instead of omitting in overloaded cases
|
359
364
|
/*
|
360
365
|
* Normalise the overloaded arguments of the page call facade
|
361
|
-
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const
|
366
|
+
*/const pageArgumentsToCallOptions=(category,name,properties,options,callback)=>{const payload={category:category,name:name,properties:properties,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.category=category;payload.name=name;payload.properties=properties;payload.options=undefined;payload.callback=options;}if(isFunction(properties)){payload.category=category;payload.name=name;payload.properties=undefined;payload.options=undefined;payload.callback=properties;}if(isFunction(name)){payload.category=category;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=name;}if(isFunction(category)){payload.category=undefined;payload.name=undefined;payload.properties=undefined;payload.options=undefined;payload.callback=category;}if(isObjectLiteralAndNotNull(category)){payload.name=undefined;payload.category=undefined;payload.properties=category;if(!isFunction(name)){payload.options=name;}else {payload.options=undefined;}}else if(isObjectLiteralAndNotNull(name)){payload.name=undefined;payload.properties=name;if(!isFunction(properties)){payload.options=properties;}else {payload.options=undefined;}}// if the category argument alone is provided b/w category and name,
|
362
367
|
// use it as name and set category to undefined
|
363
|
-
if(isString(
|
368
|
+
if(isString(category)&&!isString(name)){payload.category=undefined;payload.name=category;}// Rest of the code is just to clean up undefined values
|
364
369
|
// and set some proper defaults
|
365
370
|
// Also, to clone the incoming object type arguments
|
366
371
|
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
|
367
372
|
payload.properties=mergeDeepRight(isObjectLiteralAndNotNull(payload.properties)?payload.properties:{},{...(nameForProperties&&{name:nameForProperties}),...(categoryForProperties&&{category:categoryForProperties})});return payload;};/*
|
368
373
|
* Normalise the overloaded arguments of the track call facade
|
369
|
-
*/const trackArgumentsToCallOptions=(event,properties,options,callback)=>{const
|
374
|
+
*/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
|
370
375
|
// and set some proper defaults
|
371
376
|
// Also, to clone the incoming object type arguments
|
372
377
|
payload.properties=isDefinedAndNotNull(payload.properties)?clone(payload.properties):{};if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
373
378
|
* Normalise the overloaded arguments of the identify call facade
|
374
|
-
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const
|
379
|
+
*/const identifyArgumentsToCallOptions=(userId,traits,options,callback)=>{const payload={userId:userId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.userId=userId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.userId=userId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(userId)||isNull(userId)){// Explicitly set null to prevent resetting the existing value
|
375
380
|
// in the Analytics class
|
376
|
-
payload.userId=null;payload.traits=
|
381
|
+
payload.userId=null;payload.traits=userId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
377
382
|
// and set some proper defaults
|
378
383
|
// Also, to clone the incoming object type arguments
|
379
384
|
payload.userId=tryStringify(payload.userId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
380
385
|
* Normalise the overloaded arguments of the alias call facade
|
381
|
-
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const
|
386
|
+
*/const aliasArgumentsToCallOptions=(to,from,options,callback)=>{const payload={to,from:from,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.to=to;payload.from=from;payload.options=undefined;payload.callback=options;}if(isFunction(from)){payload.to=to;payload.from=undefined;payload.options=undefined;payload.callback=from;}else if(isObjectLiteralAndNotNull(from)||isNull(from)){payload.to=to;payload.from=undefined;payload.options=from;}// Rest of the code is just to clean up undefined values
|
382
387
|
// and set some proper defaults
|
383
388
|
// Also, to clone the incoming object type arguments
|
384
389
|
if(isDefined(payload.to)){payload.to=tryStringify(payload.to);}if(isDefined(payload.from)){payload.from=tryStringify(payload.from);}else {payload.from=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};/*
|
385
390
|
* Normalise the overloaded arguments of the group call facade
|
386
|
-
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const
|
391
|
+
*/const groupArgumentsToCallOptions=(groupId,traits,options,callback)=>{const payload={groupId:groupId,traits:traits,options:options,callback:undefined};if(isFunction(callback)){payload.callback=callback;}if(isFunction(options)){payload.groupId=groupId;payload.traits=traits;payload.options=undefined;payload.callback=options;}if(isFunction(traits)){payload.groupId=groupId;payload.traits=undefined;payload.options=undefined;payload.callback=traits;}if(isObjectLiteralAndNotNull(groupId)||isNull(groupId)){// Explicitly set null to prevent resetting the existing value
|
387
392
|
// in the Analytics class
|
388
|
-
payload.groupId=null;payload.traits=
|
393
|
+
payload.groupId=null;payload.traits=groupId;if(!isFunction(traits)){payload.options=traits;}else {payload.options=undefined;}}// Rest of the code is just to clean up undefined values
|
389
394
|
// and set some proper defaults
|
390
395
|
// Also, to clone the incoming object type arguments
|
391
396
|
payload.groupId=tryStringify(payload.groupId);if(isObjectLiteralAndNotNull(payload.traits)){payload.traits=clone(payload.traits);}else {payload.traits=undefined;}if(isDefined(payload.options)){payload.options=clone(payload.options);}else {payload.options=undefined;}return payload;};
|
@@ -433,6 +438,20 @@ const getFormattedTimestamp=date=>date.toISOString();/**
|
|
433
438
|
* @returns ISO formatted timestamp string
|
434
439
|
*/const getCurrentTimeFormatted=()=>getFormattedTimestamp(new Date());
|
435
440
|
|
441
|
+
const JSON_STRINGIFY='JSONStringify';const getCircularReplacer=(excludeNull,excludeKeys,logger)=>{const ancestors=[];// Here we do not want to use arrow function to use "this" in function context
|
442
|
+
// eslint-disable-next-line func-names
|
443
|
+
return function(key,value){if(excludeKeys?.includes(key)){return undefined;}if(excludeNull&&isNullOrUndefined(value)){return undefined;}if(typeof value!=='object'||isNull(value)){return value;}// `this` is the object that value is contained in, i.e., its direct parent.
|
444
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
445
|
+
// @ts-ignore-next-line
|
446
|
+
while(ancestors.length>0&&ancestors[ancestors.length-1]!==this){ancestors.pop();}if(ancestors.includes(value)){logger?.warn(CIRCULAR_REFERENCE_WARNING(JSON_STRINGIFY,key));return '[Circular Reference]';}ancestors.push(value);return value;};};/**
|
447
|
+
* Utility method for JSON stringify object excluding null values & circular references
|
448
|
+
*
|
449
|
+
* @param {*} value input
|
450
|
+
* @param {boolean} excludeNull if it should exclude nul or not
|
451
|
+
* @param {function} logger optional logger methods for warning
|
452
|
+
* @returns string
|
453
|
+
*/const stringifyWithoutCircular=(value,excludeNull,excludeKeys,logger)=>{try{return JSON.stringify(value,getCircularReplacer(excludeNull,excludeKeys,logger));}catch(err){logger?.warn(JSON_STRINGIFY_WARNING,err);return null;}};
|
454
|
+
|
436
455
|
const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
437
456
|
* Get mutated error with issue prepended to error message
|
438
457
|
* @param err Original error
|
@@ -440,7 +459,7 @@ const MANUAL_ERROR_IDENTIFIER='[MANUAL ERROR]';/**
|
|
440
459
|
* @returns Instance of Error with message prepended with issue
|
441
460
|
*/const getMutatedError=(err,issue)=>{let finalError=err;if(!isTypeOfError(err)){finalError=new Error(`${issue}: ${stringifyWithoutCircular(err)}`);}else {finalError.message=`${issue}: ${err.message}`;}return finalError;};const dispatchErrorEvent=error=>{if(isTypeOfError(error)){error.stack=`${error.stack??''}\n${MANUAL_ERROR_IDENTIFIER}`;}globalThis.dispatchEvent(new ErrorEvent('error',{error}));};
|
442
461
|
|
443
|
-
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.
|
462
|
+
const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.11.7';const APP_NAMESPACE='com.rudderlabs.javascript';const MODULE_TYPE='npm';const ADBLOCK_PAGE_CATEGORY='RudderJS-Initiated';const ADBLOCK_PAGE_NAME='ad-block page request';const ADBLOCK_PAGE_PATH='/ad-blocked';const GLOBAL_PRELOAD_BUFFER='preloadedEventsBuffer';const CONSENT_TRACK_EVENT_NAME='Consent Management Interaction';
|
444
463
|
|
445
464
|
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';
|
446
465
|
|
@@ -688,7 +707,7 @@ const removeDuplicateSlashes=str=>str.replace(/\/{2,}/g,'/');/**
|
|
688
707
|
if(isFunction(globalThis.URL)){// eslint-disable-next-line no-new
|
689
708
|
new URL(url);}return URL_PATTERN.test(url);}catch(e){return false;}};
|
690
709
|
|
691
|
-
const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=details.xhr.status;// same as in v1.1
|
710
|
+
const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=getSanitizedValue(details.xhr).status;// same as in v1.1
|
692
711
|
isRetryableNWFailure=xhrStatus===429||xhrStatus>=500&&xhrStatus<600;}return isRetryableNWFailure;};
|
693
712
|
|
694
713
|
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_';
|