@rudderstack/analytics-js 3.0.0-beta.16 → 3.0.0-beta.18

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.
@@ -417,7 +417,7 @@ if(isDefined(payload.groupId)){payload.groupId=tryStringify(payload.groupId);}el
417
417
 
418
418
  const CAPABILITIES_MANAGER='CapabilitiesManager';const CONFIG_MANAGER='ConfigManager';const EVENT_MANAGER='EventManager';const PLUGINS_MANAGER='PluginsManager';const USER_SESSION_MANAGER='UserSessionManager';const ERROR_HANDLER='ErrorHandler';const PLUGIN_ENGINE='PluginEngine';const STORE_MANAGER='StoreManager';const READY_API='readyApi';const EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';const RS_APP='RudderStackApplication';const ANALYTICS_CORE='AnalyticsCore';
419
419
 
420
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.16';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';
420
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.18';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';
421
421
 
422
422
  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';
423
423
 
@@ -650,6 +650,11 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
650
650
  * List of plugin names that are loaded as dynamic imports in modern builds
651
651
  */const pluginNamesList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
652
652
 
653
+ /**
654
+ * To get the current timestamp in ISO string format
655
+ * @returns ISO formatted timestamp string
656
+ */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
657
+
653
658
  const COOKIE_STORAGE='cookieStorage';const LOCAL_STORAGE='localStorage';const SESSION_STORAGE='sessionStorage';const MEMORY_STORAGE='memoryStorage';const NO_STORAGE='none';
654
659
 
655
660
  const removeDuplicateSlashes=str=>str.replace(/\/{2,}/g,'/');
@@ -667,11 +672,6 @@ const generateUUID=()=>{if(hasCrypto$1()){return v4$1();}return v4();};
667
672
  const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=details.xhr.status;// same as in v1.1
668
673
  isRetryableNWFailure=xhrStatus===429||xhrStatus>=500&&xhrStatus<600;}return isRetryableNWFailure;};
669
674
 
670
- /**
671
- * To get the current timestamp in ISO string format
672
- * @returns ISO formatted timestamp string
673
- */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
674
-
675
675
  const EVENT_PAYLOAD_SIZE_BYTES_LIMIT=32*1024;// 32 KB
676
676
 
677
677
  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';/**
@@ -688,8 +688,8 @@ const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${
688
688
  * Updates certain parameters like sentAt timestamp, integrations config etc.
689
689
  * @param event RudderEvent object
690
690
  * @returns Final event ready to be delivered
691
- */const getFinalEventForDeliveryMutator=event=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
692
- finalEvent.sentAt=getCurrentTimeFormatted();return finalEvent;};
691
+ */const getFinalEventForDeliveryMutator=(event,currentTime)=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
692
+ finalEvent.sentAt=currentTime;return finalEvent;};
693
693
 
694
694
  const ENCRYPTION_PREFIX_V3='RS_ENC_v3_';
695
695
 
@@ -707,7 +707,7 @@ const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flush
707
707
  * @param events RudderEvent object array
708
708
  * @param logger Logger instance
709
709
  * @returns stringified events payload as Blob, undefined if error occurs.
710
- */const getBatchDeliveryPayload$1=(events,logger)=>{const data={batch:events};try{const blobPayload=stringifyWithoutCircular(data,true);const blobOptions={type:'text/plain'};if(blobPayload){return new Blob([blobPayload],blobOptions);}logger?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
710
+ */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?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
711
711
 
712
712
  const QueueStatuses={IN_PROGRESS:'inProgress',QUEUE:'queue',RECLAIM_START:'reclaimStart',RECLAIM_END:'reclaimEnd',ACK:'ack',BATCH_QUEUE:'batchQueue'};
713
713
 
@@ -810,11 +810,11 @@ const pluginName$e='BeaconQueue';const BeaconQueue=()=>({name:pluginName$e,deps:
810
810
  * @param errorHandler Error handler instance
811
811
  * @param logger Logger instance
812
812
  * @returns BeaconItemsQueue instance
813
- */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));const data=getBatchDeliveryPayload$1(finalEvents,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
813
+ */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const currentTime=getCurrentTimeFormatted();const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event,currentTime));const data=getBatchDeliveryPayload$1(finalEvents,currentTime,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
814
814
  done(null);}}else {// Mark the item as done so that it can be removed from the queue
815
815
  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
816
- maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
817
- return getBatchDeliveryPayload$1(events,logger).size;});return eventsQueue;},/**
816
+ maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,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
817
+ return getBatchDeliveryPayload$1(events,currentTime,logger).size;});return eventsQueue;},/**
818
818
  * Add event to the queue for delivery
819
819
  * @param state Application state
820
820
  * @param eventsQueue IQueue instance
@@ -853,7 +853,7 @@ event.context='Script load failures';}// eslint-disable-next-line no-param-reass
853
853
  event.severity='error';};const onError=state=>{const metadataSource=state.source.value?.id;return event=>{try{// Discard the event if it's not originated at the SDK
854
854
  if(!isRudderSDKError(event)){return false;}enhanceErrorEventMutator(event,metadataSource);return true;}catch{// Drop the error event if it couldn't be filtered as
855
855
  // it is most likely a non-SDK error
856
- return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.16',// Set SDK version as the app version from build config
856
+ return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.18',// Set SDK version as the app version from build config
857
857
  metaData:{SDK:{name:'JS',installType:'npm'}},beforeSend:onError(state),autoCaptureSessions:false,// auto capture sessions is disabled
858
858
  collectUserIp:false,// collecting user's IP is disabled
859
859
  // enabledBreadcrumbTypes: ['error', 'log', 'user'], // for v7 and above
@@ -861,7 +861,8 @@ maxEvents:100,maxBreadcrumbs:40,releaseStage:getReleaseStage(),user:{id:state.li
861
861
  globalThis.setTimeout(initBugsnagClient,SDK_LOAD_POLL_INTERVAL_MS,state,promiseResolve,promiseReject,logger,time+SDK_LOAD_POLL_INTERVAL_MS);}};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):undefined;};
862
862
 
863
863
  const pluginName$d='Bugsnag';const Bugsnag=()=>({name:pluginName$d,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$d];},errorReportingProvider:{init:(state,externalSrcLoader,logger)=>new Promise((resolve,reject)=>{// If API key token is not parsed or invalid, don't proceed to initialize the client
864
- if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
864
+ if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}// If SDK URL is empty, don't proceed to initialize the client
865
+ loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
865
866
 
866
867
  const CUSTOM_CONSENT_MANAGER_PLUGIN='CustomConsentManagerPlugin';
867
868
 
@@ -2284,7 +2285,7 @@ const DATA_PLANE_API_VERSION='v1';const QUEUE_NAME='rudder';const XHR_QUEUE_PLUG
2284
2285
 
2285
2286
  const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,url)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s) to ${url}.`;
2286
2287
 
2287
- const getBatchDeliveryPayload=(events,logger)=>{const batchPayload={batch:events};return stringifyWithoutCircular(batchPayload,true,undefined,logger);};const getNormalizedQueueOptions=queueOpts=>mergeDeepRight(DEFAULT_RETRY_QUEUE_OPTIONS,queueOpts);const getDeliveryUrl=(dataplaneUrl,endpoint)=>{const dpUrl=new URL(dataplaneUrl);return new URL(removeDuplicateSlashes([dpUrl.pathname,'/',DATA_PLANE_API_VERSION,'/',endpoint].join('')),dpUrl).href;};const getBatchDeliveryUrl=dataplaneUrl=>getDeliveryUrl(dataplaneUrl,'batch');const logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;if(Array.isArray(itemData)){const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));data=getBatchDeliveryPayload(finalEvents,logger);headers=itemData[0]?clone$1(itemData[0].headers):{};url=getBatchDeliveryUrl(state.lifecycle.activeDataplaneUrl.value);}else {const{url:eventUrl,event,headers:eventHeaders}=itemData;const finalEvent=getFinalEventForDeliveryMutator(event);data=getDeliveryPayload(finalEvent,logger);headers=clone$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2288
+ 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 logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;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$1(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$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2288
2289
 
2289
2290
  const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName];},dataplaneEventsQueue:{/**
2290
2291
  * Initialize the queue for delivery
@@ -2296,8 +2297,8 @@ const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initial
2296
2297
  * @returns RetryQueue instance
2297
2298
  */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
2298
2299
  `${QUEUE_NAME}_${writeKey}`,finalQOpts,(itemData,done,attemptNumber,maxRetryAttempts,willBeRetried)=>{const{data,url,headers}=getRequestInfo(itemData,state,logger);httpClient.getAsyncData({url,options:{method:'POST',headers,data:data,sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS,callback:(result,details)=>{// null means item will not be requeued
2299
- const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to string as we know that the event has already been validated prior to enqueue
2300
- return getBatchDeliveryPayload(events,logger)?.length;});return eventsQueue;},/**
2300
+ const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,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
2301
+ return getBatchDeliveryPayload(events,currentTime,logger)?.length;});return eventsQueue;},/**
2301
2302
  * Add event to the queue for delivery
2302
2303
  * @param state Application state
2303
2304
  * @param eventsQueue RetryQueue instance
@@ -3181,7 +3182,7 @@ ready(callback,isBufferedInvocation=false){const type='ready';if(!state.lifecycl
3181
3182
  * If destinations are loaded or no integration is available for loading
3182
3183
  * execute the callback immediately else push the callbacks to a queue that
3183
3184
  * will be executed after loading completes
3184
- */if(state.lifecycle.status.value==='ready'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3185
+ */if(state.lifecycle.status.value==='readyExecuted'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3185
3186
  // Send automatic ad blocked page event if ad-blockers are detected on the page
3186
3187
  // Check page category to avoid infinite loop
3187
3188
  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
@@ -413,7 +413,7 @@ if(isDefined(payload.groupId)){payload.groupId=tryStringify(payload.groupId);}el
413
413
 
414
414
  const CAPABILITIES_MANAGER='CapabilitiesManager';const CONFIG_MANAGER='ConfigManager';const EVENT_MANAGER='EventManager';const PLUGINS_MANAGER='PluginsManager';const USER_SESSION_MANAGER='UserSessionManager';const ERROR_HANDLER='ErrorHandler';const PLUGIN_ENGINE='PluginEngine';const STORE_MANAGER='StoreManager';const READY_API='readyApi';const EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';const RS_APP='RudderStackApplication';const ANALYTICS_CORE='AnalyticsCore';
415
415
 
416
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.16';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';
416
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.18';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';
417
417
 
418
418
  const QUERY_PARAM_TRAIT_PREFIX='ajs_trait_';const QUERY_PARAM_PROPERTY_PREFIX='ajs_prop_';const QUERY_PARAM_ANONYMOUS_ID_KEY='ajs_aid';const QUERY_PARAM_USER_ID_KEY='ajs_uid';const QUERY_PARAM_TRACK_EVENT_NAME_KEY='ajs_event';
419
419
 
@@ -646,6 +646,11 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
646
646
  * List of plugin names that are loaded as dynamic imports in modern builds
647
647
  */const pluginNamesList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
648
648
 
649
+ /**
650
+ * To get the current timestamp in ISO string format
651
+ * @returns ISO formatted timestamp string
652
+ */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
653
+
649
654
  const COOKIE_STORAGE='cookieStorage';const LOCAL_STORAGE='localStorage';const SESSION_STORAGE='sessionStorage';const MEMORY_STORAGE='memoryStorage';const NO_STORAGE='none';
650
655
 
651
656
  const removeDuplicateSlashes=str=>str.replace(/\/{2,}/g,'/');
@@ -663,11 +668,6 @@ const generateUUID=()=>{if(hasCrypto$1()){return v4$1();}return v4();};
663
668
  const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=details.xhr.status;// same as in v1.1
664
669
  isRetryableNWFailure=xhrStatus===429||xhrStatus>=500&&xhrStatus<600;}return isRetryableNWFailure;};
665
670
 
666
- /**
667
- * To get the current timestamp in ISO string format
668
- * @returns ISO formatted timestamp string
669
- */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
670
-
671
671
  const EVENT_PAYLOAD_SIZE_BYTES_LIMIT=32*1024;// 32 KB
672
672
 
673
673
  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';/**
@@ -684,8 +684,8 @@ const EVENT_PAYLOAD_SIZE_CHECK_FAIL_WARNING=(context,payloadSize,sizeLimit)=>`${
684
684
  * Updates certain parameters like sentAt timestamp, integrations config etc.
685
685
  * @param event RudderEvent object
686
686
  * @returns Final event ready to be delivered
687
- */const getFinalEventForDeliveryMutator=event=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
688
- finalEvent.sentAt=getCurrentTimeFormatted();return finalEvent;};
687
+ */const getFinalEventForDeliveryMutator=(event,currentTime)=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
688
+ finalEvent.sentAt=currentTime;return finalEvent;};
689
689
 
690
690
  const ENCRYPTION_PREFIX_V3='RS_ENC_v3_';
691
691
 
@@ -703,7 +703,7 @@ const DEFAULT_BEACON_QUEUE_OPTIONS={maxItems:DEFAULT_BEACON_QUEUE_MAX_SIZE,flush
703
703
  * @param events RudderEvent object array
704
704
  * @param logger Logger instance
705
705
  * @returns stringified events payload as Blob, undefined if error occurs.
706
- */const getBatchDeliveryPayload$1=(events,logger)=>{const data={batch:events};try{const blobPayload=stringifyWithoutCircular(data,true);const blobOptions={type:'text/plain'};if(blobPayload){return new Blob([blobPayload],blobOptions);}logger?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
706
+ */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?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
707
707
 
708
708
  const QueueStatuses={IN_PROGRESS:'inProgress',QUEUE:'queue',RECLAIM_START:'reclaimStart',RECLAIM_END:'reclaimEnd',ACK:'ack',BATCH_QUEUE:'batchQueue'};
709
709
 
@@ -806,11 +806,11 @@ const pluginName$e='BeaconQueue';const BeaconQueue=()=>({name:pluginName$e,deps:
806
806
  * @param errorHandler Error handler instance
807
807
  * @param logger Logger instance
808
808
  * @returns BeaconItemsQueue instance
809
- */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));const data=getBatchDeliveryPayload$1(finalEvents,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
809
+ */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const currentTime=getCurrentTimeFormatted();const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event,currentTime));const data=getBatchDeliveryPayload$1(finalEvents,currentTime,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
810
810
  done(null);}}else {// Mark the item as done so that it can be removed from the queue
811
811
  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
812
- maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
813
- return getBatchDeliveryPayload$1(events,logger).size;});return eventsQueue;},/**
812
+ maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,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
813
+ return getBatchDeliveryPayload$1(events,currentTime,logger).size;});return eventsQueue;},/**
814
814
  * Add event to the queue for delivery
815
815
  * @param state Application state
816
816
  * @param eventsQueue IQueue instance
@@ -849,7 +849,7 @@ event.context='Script load failures';}// eslint-disable-next-line no-param-reass
849
849
  event.severity='error';};const onError=state=>{const metadataSource=state.source.value?.id;return event=>{try{// Discard the event if it's not originated at the SDK
850
850
  if(!isRudderSDKError(event)){return false;}enhanceErrorEventMutator(event,metadataSource);return true;}catch{// Drop the error event if it couldn't be filtered as
851
851
  // it is most likely a non-SDK error
852
- return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.16',// Set SDK version as the app version from build config
852
+ return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.18',// Set SDK version as the app version from build config
853
853
  metaData:{SDK:{name:'JS',installType:'npm'}},beforeSend:onError(state),autoCaptureSessions:false,// auto capture sessions is disabled
854
854
  collectUserIp:false,// collecting user's IP is disabled
855
855
  // enabledBreadcrumbTypes: ['error', 'log', 'user'], // for v7 and above
@@ -857,7 +857,8 @@ maxEvents:100,maxBreadcrumbs:40,releaseStage:getReleaseStage(),user:{id:state.li
857
857
  globalThis.setTimeout(initBugsnagClient,SDK_LOAD_POLL_INTERVAL_MS,state,promiseResolve,promiseReject,logger,time+SDK_LOAD_POLL_INTERVAL_MS);}};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):undefined;};
858
858
 
859
859
  const pluginName$d='Bugsnag';const Bugsnag=()=>({name:pluginName$d,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$d];},errorReportingProvider:{init:(state,externalSrcLoader,logger)=>new Promise((resolve,reject)=>{// If API key token is not parsed or invalid, don't proceed to initialize the client
860
- if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
860
+ if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}// If SDK URL is empty, don't proceed to initialize the client
861
+ loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
861
862
 
862
863
  const CUSTOM_CONSENT_MANAGER_PLUGIN='CustomConsentManagerPlugin';
863
864
 
@@ -2280,7 +2281,7 @@ const DATA_PLANE_API_VERSION='v1';const QUEUE_NAME='rudder';const XHR_QUEUE_PLUG
2280
2281
 
2281
2282
  const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,url)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s) to ${url}.`;
2282
2283
 
2283
- const getBatchDeliveryPayload=(events,logger)=>{const batchPayload={batch:events};return stringifyWithoutCircular(batchPayload,true,undefined,logger);};const getNormalizedQueueOptions=queueOpts=>mergeDeepRight(DEFAULT_RETRY_QUEUE_OPTIONS,queueOpts);const getDeliveryUrl=(dataplaneUrl,endpoint)=>{const dpUrl=new URL(dataplaneUrl);return new URL(removeDuplicateSlashes([dpUrl.pathname,'/',DATA_PLANE_API_VERSION,'/',endpoint].join('')),dpUrl).href;};const getBatchDeliveryUrl=dataplaneUrl=>getDeliveryUrl(dataplaneUrl,'batch');const logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;if(Array.isArray(itemData)){const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));data=getBatchDeliveryPayload(finalEvents,logger);headers=itemData[0]?clone$1(itemData[0].headers):{};url=getBatchDeliveryUrl(state.lifecycle.activeDataplaneUrl.value);}else {const{url:eventUrl,event,headers:eventHeaders}=itemData;const finalEvent=getFinalEventForDeliveryMutator(event);data=getDeliveryPayload(finalEvent,logger);headers=clone$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2284
+ 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 logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;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$1(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$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2284
2285
 
2285
2286
  const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName];},dataplaneEventsQueue:{/**
2286
2287
  * Initialize the queue for delivery
@@ -2292,8 +2293,8 @@ const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initial
2292
2293
  * @returns RetryQueue instance
2293
2294
  */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
2294
2295
  `${QUEUE_NAME}_${writeKey}`,finalQOpts,(itemData,done,attemptNumber,maxRetryAttempts,willBeRetried)=>{const{data,url,headers}=getRequestInfo(itemData,state,logger);httpClient.getAsyncData({url,options:{method:'POST',headers,data:data,sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS,callback:(result,details)=>{// null means item will not be requeued
2295
- const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to string as we know that the event has already been validated prior to enqueue
2296
- return getBatchDeliveryPayload(events,logger)?.length;});return eventsQueue;},/**
2296
+ const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,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
2297
+ return getBatchDeliveryPayload(events,currentTime,logger)?.length;});return eventsQueue;},/**
2297
2298
  * Add event to the queue for delivery
2298
2299
  * @param state Application state
2299
2300
  * @param eventsQueue RetryQueue instance
@@ -3177,7 +3178,7 @@ ready(callback,isBufferedInvocation=false){const type='ready';if(!state.lifecycl
3177
3178
  * If destinations are loaded or no integration is available for loading
3178
3179
  * execute the callback immediately else push the callbacks to a queue that
3179
3180
  * will be executed after loading completes
3180
- */if(state.lifecycle.status.value==='ready'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3181
+ */if(state.lifecycle.status.value==='readyExecuted'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3181
3182
  // Send automatic ad blocked page event if ad-blockers are detected on the page
3182
3183
  // Check page category to avoid infinite loop
3183
3184
  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
@@ -419,7 +419,7 @@
419
419
 
420
420
  const CAPABILITIES_MANAGER='CapabilitiesManager';const CONFIG_MANAGER='ConfigManager';const EVENT_MANAGER='EventManager';const PLUGINS_MANAGER='PluginsManager';const USER_SESSION_MANAGER='UserSessionManager';const ERROR_HANDLER='ErrorHandler';const PLUGIN_ENGINE='PluginEngine';const STORE_MANAGER='StoreManager';const READY_API='readyApi';const EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';const RS_APP='RudderStackApplication';const ANALYTICS_CORE='AnalyticsCore';
421
421
 
422
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.16';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';
422
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.18';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';
423
423
 
424
424
  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';
425
425
 
@@ -652,6 +652,11 @@
652
652
  * List of plugin names that are loaded as dynamic imports in modern builds
653
653
  */const pluginNamesList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
654
654
 
655
+ /**
656
+ * To get the current timestamp in ISO string format
657
+ * @returns ISO formatted timestamp string
658
+ */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
659
+
655
660
  const COOKIE_STORAGE='cookieStorage';const LOCAL_STORAGE='localStorage';const SESSION_STORAGE='sessionStorage';const MEMORY_STORAGE='memoryStorage';const NO_STORAGE='none';
656
661
 
657
662
  const removeDuplicateSlashes=str=>str.replace(/\/{2,}/g,'/');
@@ -669,11 +674,6 @@
669
674
  const isErrRetryable=details=>{let isRetryableNWFailure=false;if(details?.error&&details?.xhr){const xhrStatus=details.xhr.status;// same as in v1.1
670
675
  isRetryableNWFailure=xhrStatus===429||xhrStatus>=500&&xhrStatus<600;}return isRetryableNWFailure;};
671
676
 
672
- /**
673
- * To get the current timestamp in ISO string format
674
- * @returns ISO formatted timestamp string
675
- */const getCurrentTimeFormatted=()=>{const curDateTime=new Date().toISOString();return curDateTime;};
676
-
677
677
  const EVENT_PAYLOAD_SIZE_BYTES_LIMIT=32*1024;// 32 KB
678
678
 
679
679
  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';/**
@@ -690,8 +690,8 @@
690
690
  * Updates certain parameters like sentAt timestamp, integrations config etc.
691
691
  * @param event RudderEvent object
692
692
  * @returns Final event ready to be delivered
693
- */const getFinalEventForDeliveryMutator=event=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
694
- finalEvent.sentAt=getCurrentTimeFormatted();return finalEvent;};
693
+ */const getFinalEventForDeliveryMutator=(event,currentTime)=>{const finalEvent=clone$1(event);// Update sentAt timestamp to the latest timestamp
694
+ finalEvent.sentAt=currentTime;return finalEvent;};
695
695
 
696
696
  const ENCRYPTION_PREFIX_V3='RS_ENC_v3_';
697
697
 
@@ -709,7 +709,7 @@
709
709
  * @param events RudderEvent object array
710
710
  * @param logger Logger instance
711
711
  * @returns stringified events payload as Blob, undefined if error occurs.
712
- */const getBatchDeliveryPayload$1=(events,logger)=>{const data={batch:events};try{const blobPayload=stringifyWithoutCircular(data,true);const blobOptions={type:'text/plain'};if(blobPayload){return new Blob([blobPayload],blobOptions);}logger?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
712
+ */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?.error(BEACON_QUEUE_STRING_CONVERSION_FAILURE_ERROR(BEACON_QUEUE_PLUGIN));}catch(err){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;};
713
713
 
714
714
  const QueueStatuses={IN_PROGRESS:'inProgress',QUEUE:'queue',RECLAIM_START:'reclaimStart',RECLAIM_END:'reclaimEnd',ACK:'ack',BATCH_QUEUE:'batchQueue'};
715
715
 
@@ -812,11 +812,11 @@
812
812
  * @param errorHandler Error handler instance
813
813
  * @param logger Logger instance
814
814
  * @returns BeaconItemsQueue instance
815
- */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));const data=getBatchDeliveryPayload$1(finalEvents,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
815
+ */init(state,httpClient,storeManager,errorHandler,logger){const writeKey=state.lifecycle.writeKey.value;const dataplaneUrl=state.lifecycle.activeDataplaneUrl.value;const url=getDeliveryUrl$1(dataplaneUrl,writeKey);const finalQOpts=getNormalizedBeaconQueueOptions(state.loadOptions.value.beaconQueueOptions??{});const queueProcessCallback=(itemData,done)=>{logger?.debug(BEACON_PLUGIN_EVENTS_QUEUE_DEBUG(BEACON_QUEUE_PLUGIN));const currentTime=getCurrentTimeFormatted();const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event,currentTime));const data=getBatchDeliveryPayload$1(finalEvents,currentTime,logger);if(data){try{const isEnqueuedInBeacon=navigator.sendBeacon(url,data);if(!isEnqueuedInBeacon){logger?.error(BEACON_QUEUE_SEND_ERROR(BEACON_QUEUE_PLUGIN));}done(null,isEnqueuedInBeacon);}catch(err){errorHandler?.onError(err,BEACON_QUEUE_PLUGIN,BEACON_QUEUE_DELIVERY_ERROR(url));// Remove the item from queue
816
816
  done(null);}}else {// Mark the item as done so that it can be removed from the queue
817
817
  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
818
- maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to Blob as we know that the event has already been validated prior to enqueue
819
- return getBatchDeliveryPayload$1(events,logger).size;});return eventsQueue;},/**
818
+ maxItems:finalQOpts.maxItems}},queueProcessCallback,storeManager,LOCAL_STORAGE,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
819
+ return getBatchDeliveryPayload$1(events,currentTime,logger).size;});return eventsQueue;},/**
820
820
  * Add event to the queue for delivery
821
821
  * @param state Application state
822
822
  * @param eventsQueue IQueue instance
@@ -855,7 +855,7 @@
855
855
  event.severity='error';};const onError=state=>{const metadataSource=state.source.value?.id;return event=>{try{// Discard the event if it's not originated at the SDK
856
856
  if(!isRudderSDKError(event)){return false;}enhanceErrorEventMutator(event,metadataSource);return true;}catch{// Drop the error event if it couldn't be filtered as
857
857
  // it is most likely a non-SDK error
858
- return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.16',// Set SDK version as the app version from build config
858
+ return false;}};};const getReleaseStage=()=>{const host=globalThis.location.hostname;return host&&DEV_HOSTS.includes(host)?'development':'production';};const getGlobalBugsnagLibInstance=()=>globalThis[BUGSNAG_LIB_INSTANCE_GLOBAL_KEY_NAME];const getNewClient=(state,logger)=>{const globalBugsnagLibInstance=getGlobalBugsnagLibInstance();const clientConfig={apiKey:API_KEY,appVersion:'3.0.0-beta.18',// Set SDK version as the app version from build config
859
859
  metaData:{SDK:{name:'JS',installType:'npm'}},beforeSend:onError(state),autoCaptureSessions:false,// auto capture sessions is disabled
860
860
  collectUserIp:false,// collecting user's IP is disabled
861
861
  // enabledBreadcrumbTypes: ['error', 'log', 'user'], // for v7 and above
@@ -863,7 +863,8 @@
863
863
  globalThis.setTimeout(initBugsnagClient,SDK_LOAD_POLL_INTERVAL_MS,state,promiseResolve,promiseReject,logger,time+SDK_LOAD_POLL_INTERVAL_MS);}};const getAppStateForMetadata=state=>{const stateStr=stringifyWithoutCircular(state,false,APP_STATE_EXCLUDE_KEYS);return stateStr!==null?JSON.parse(stateStr):undefined;};
864
864
 
865
865
  const pluginName$d='Bugsnag';const Bugsnag=()=>({name:pluginName$d,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName$d];},errorReportingProvider:{init:(state,externalSrcLoader,logger)=>new Promise((resolve,reject)=>{// If API key token is not parsed or invalid, don't proceed to initialize the client
866
- if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
866
+ if(!isApiKeyValid(API_KEY)){reject(new Error(BUGSNAG_API_KEY_VALIDATION_ERROR(API_KEY)));return;}// If SDK URL is empty, don't proceed to initialize the client
867
+ loadBugsnagSDK(externalSrcLoader,logger);initBugsnagClient(state,resolve,reject,logger);}),notify:(client,error,state,logger)=>{client?.notify(error,{metaData:{state:getAppStateForMetadata(state)}});},breadcrumb:(client,message,logger)=>{client?.leaveBreadcrumb(message);}}});
867
868
 
868
869
  const CUSTOM_CONSENT_MANAGER_PLUGIN='CustomConsentManagerPlugin';
869
870
 
@@ -2286,7 +2287,7 @@
2286
2287
 
2287
2288
  const EVENT_DELIVERY_FAILURE_ERROR_PREFIX=(context,url)=>`${context}${LOG_CONTEXT_SEPARATOR}Failed to deliver event(s) to ${url}.`;
2288
2289
 
2289
- const getBatchDeliveryPayload=(events,logger)=>{const batchPayload={batch:events};return stringifyWithoutCircular(batchPayload,true,undefined,logger);};const getNormalizedQueueOptions=queueOpts=>mergeDeepRight(DEFAULT_RETRY_QUEUE_OPTIONS,queueOpts);const getDeliveryUrl=(dataplaneUrl,endpoint)=>{const dpUrl=new URL(dataplaneUrl);return new URL(removeDuplicateSlashes([dpUrl.pathname,'/',DATA_PLANE_API_VERSION,'/',endpoint].join('')),dpUrl).href;};const getBatchDeliveryUrl=dataplaneUrl=>getDeliveryUrl(dataplaneUrl,'batch');const logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;if(Array.isArray(itemData)){const finalEvents=itemData.map(queueItemData=>getFinalEventForDeliveryMutator(queueItemData.event));data=getBatchDeliveryPayload(finalEvents,logger);headers=itemData[0]?clone$1(itemData[0].headers):{};url=getBatchDeliveryUrl(state.lifecycle.activeDataplaneUrl.value);}else {const{url:eventUrl,event,headers:eventHeaders}=itemData;const finalEvent=getFinalEventForDeliveryMutator(event);data=getDeliveryPayload(finalEvent,logger);headers=clone$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2290
+ 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 logErrorOnFailure=(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger)=>{if(isUndefined(details?.error)||isUndefined(logger)){return;}const isRetryableFailure=isErrRetryable(details);let errMsg=EVENT_DELIVERY_FAILURE_ERROR_PREFIX(XHR_QUEUE_PLUGIN,url);const dropMsg=`The event(s) will be dropped.`;if(isRetryableFailure){if(willBeRetried){errMsg=`${errMsg} It/they will be retried.`;if(attemptNumber>0){errMsg=`${errMsg} Retry attempt ${attemptNumber} of ${maxRetryAttempts}.`;}}else {errMsg=`${errMsg} Retries exhausted (${maxRetryAttempts}). ${dropMsg}`;}}else {errMsg=`${errMsg} ${dropMsg}`;}logger?.error(errMsg);};const getRequestInfo=(itemData,state,logger)=>{let data;let headers;let url;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$1(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$1(eventHeaders);url=eventUrl;}return {data,headers,url};};
2290
2291
 
2291
2292
  const pluginName='XhrQueue';const XhrQueue=()=>({name:pluginName,deps:[],initialize:state=>{state.plugins.loadedPlugins.value=[...state.plugins.loadedPlugins.value,pluginName];},dataplaneEventsQueue:{/**
2292
2293
  * Initialize the queue for delivery
@@ -2298,8 +2299,8 @@
2298
2299
  * @returns RetryQueue instance
2299
2300
  */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
2300
2301
  `${QUEUE_NAME}_${writeKey}` ,finalQOpts,(itemData,done,attemptNumber,maxRetryAttempts,willBeRetried)=>{const{data,url,headers}=getRequestInfo(itemData,state,logger);httpClient.getAsyncData({url,options:{method:'POST',headers,data:data,sendRawData:true},isRawResponse:true,timeout:REQUEST_TIMEOUT_MS,callback:(result,details)=>{// null means item will not be requeued
2301
- const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,logger,itemData=>{const events=itemData.map(queueItemData=>queueItemData.event);// type casting to string as we know that the event has already been validated prior to enqueue
2302
- return getBatchDeliveryPayload(events,logger)?.length;});return eventsQueue;},/**
2302
+ const queueErrResp=isErrRetryable(details)?details:null;logErrorOnFailure(details,url,willBeRetried,attemptNumber,maxRetryAttempts,logger);done(queueErrResp,result);}});},storeManager,LOCAL_STORAGE,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
2303
+ return getBatchDeliveryPayload(events,currentTime,logger)?.length;});return eventsQueue;},/**
2303
2304
  * Add event to the queue for delivery
2304
2305
  * @param state Application state
2305
2306
  * @param eventsQueue RetryQueue instance
@@ -3183,7 +3184,7 @@
3183
3184
  * If destinations are loaded or no integration is available for loading
3184
3185
  * execute the callback immediately else push the callbacks to a queue that
3185
3186
  * will be executed after loading completes
3186
- */if(state.lifecycle.status.value==='ready'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3187
+ */if(state.lifecycle.status.value==='readyExecuted'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
3187
3188
  // Send automatic ad blocked page event if ad-blockers are detected on the page
3188
3189
  // Check page category to avoid infinite loop
3189
3190
  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
@@ -408,7 +408,7 @@ if(isDefined(payload.groupId)){payload.groupId=tryStringify(payload.groupId);}el
408
408
 
409
409
  const CAPABILITIES_MANAGER='CapabilitiesManager';const CONFIG_MANAGER='ConfigManager';const EVENT_MANAGER='EventManager';const PLUGINS_MANAGER='PluginsManager';const USER_SESSION_MANAGER='UserSessionManager';const ERROR_HANDLER='ErrorHandler';const PLUGIN_ENGINE='PluginEngine';const STORE_MANAGER='StoreManager';const READY_API='readyApi';const EVENT_REPOSITORY='EventRepository';const EXTERNAL_SRC_LOADER='ExternalSrcLoader';const HTTP_CLIENT='HttpClient';const RS_APP='RudderStackApplication';const ANALYTICS_CORE='AnalyticsCore';
410
410
 
411
- const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.16';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';
411
+ const APP_NAME='RudderLabs JavaScript SDK';const APP_VERSION='3.0.0-beta.18';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';
412
412
 
413
413
  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';
414
414
 
@@ -642,7 +642,7 @@ destination.config.useNativeSDK===true);const isHybridModeDestination=destinatio
642
642
  */const pluginNamesList=['BeaconQueue','Bugsnag','CustomConsentManager','DeviceModeDestinations','DeviceModeTransformation','ErrorReporting','ExternalAnonymousId','GoogleLinker','KetchConsentManager','NativeDestinationQueue','OneTrustConsentManager','StorageEncryption','StorageEncryptionLegacy','StorageMigrator','XhrQueue'];
643
643
 
644
644
  const remotesMap = {
645
- 'rudderAnalyticsRemotePlugins':{url:()=>Promise.resolve(window.RudderStackGlobals && window.RudderStackGlobals.app && window.RudderStackGlobals.app.pluginsCDNPath ? "" + window.RudderStackGlobals.app.pluginsCDNPath + "/rsa-plugins.js" : "https://cdn.rudderlabs.com/3.0.0-beta.16/modern/plugins/rsa-plugins.js"),format:'esm',from:'vite'}
645
+ 'rudderAnalyticsRemotePlugins':{url:()=>Promise.resolve(window.RudderStackGlobals && window.RudderStackGlobals.app && window.RudderStackGlobals.app.pluginsCDNPath ? "" + window.RudderStackGlobals.app.pluginsCDNPath + "/rsa-plugins.js" : "https://cdn.rudderlabs.com/3.0.0-beta.18/modern/plugins/rsa-plugins.js"),format:'esm',from:'vite'}
646
646
  };
647
647
  const loadJS = async (url, fn) => {
648
648
  const resolvedUrl = typeof url === 'function' ? await url() : url;
@@ -1604,7 +1604,7 @@ ready(callback,isBufferedInvocation=false){const type='ready';if(!state.lifecycl
1604
1604
  * If destinations are loaded or no integration is available for loading
1605
1605
  * execute the callback immediately else push the callbacks to a queue that
1606
1606
  * will be executed after loading completes
1607
- */if(state.lifecycle.status.value==='ready'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
1607
+ */if(state.lifecycle.status.value==='readyExecuted'){try{callback();}catch(err){this.errorHandler.onError(err,ANALYTICS_CORE,READY_CALLBACK_INVOKE_ERROR);}}else {state.eventBuffer.readyCallbacksArray.value=[...state.eventBuffer.readyCallbacksArray.value,callback];}}page(payload,isBufferedInvocation=false){const type='page';if(!state.lifecycle.loaded.value){state.eventBuffer.toBeProcessedArray.value=[...state.eventBuffer.toBeProcessedArray.value,[type,payload]];return;}this.errorHandler.leaveBreadcrumb(`New ${type} event`);state.metrics.triggered.value+=1;this.eventManager?.addEvent({type:'page',category:payload.category,name:payload.name,properties:payload.properties,options:payload.options,callback:payload.callback});// TODO: Maybe we should alter the behavior to send the ad-block page event even if the SDK is still loaded. It'll be pushed into the to be processed queue.
1608
1608
  // Send automatic ad blocked page event if ad-blockers are detected on the page
1609
1609
  // Check page category to avoid infinite loop
1610
1610
  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