UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

117 lines (112 loc) 4.17 kB
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '../analytics'; import { isSSR } from '../core-utils'; /** * Error codes for synced blocks preloading * Used for tracking and monitoring errors during SSR preload phase */ export const SyncedBlocksSSRErrorCodeMap = { /** * Occurs when the fetch operation returns fewer results than requested. * This indicates incomplete data retrieval or potential data loss. * Included in error: list of missing block identifiers */ FETCH_INCOMPLETE: 'SYNCED_BLOCKS_FETCH_INCOMPLETE', /** * Occurs when the batch fetch operation throws an error during execution. * This indicates a network error, timeout, or API failure. * Included in error: resource IDs that failed to fetch */ BATCH_FETCH_FAILED: 'SYNCED_BLOCKS_BATCH_FETCH_FAILED', /** * Occurs when the fetch operation times out without returning results. * This is specific to the bulk fetch operation with a configurable timeout. */ FETCH_TIMEOUT: 'SYNCED_BLOCKS_FETCH_TIMEOUT' }; /** * This is the metadata structure for SSR errors stored in the window object. */ const isSyncedBlocksSSRErrorObj = maybeSSRErrorObj => { if (!maybeSSRErrorObj || typeof maybeSSRErrorObj !== 'object') { return false; } const errorWrapper = maybeSSRErrorObj; // Check for meta object with valid code const hasValidMeta = errorWrapper.meta && typeof errorWrapper.meta === 'object' && Object.values(SyncedBlocksSSRErrorCodeMap).includes(errorWrapper.meta.code); return Boolean(hasValidMeta); }; /** * Get the first SSR error for synced blocks from the window.__SSR_ERROR__ array. * * Expected structure of error objects stored in confluence window.__SSR_ERROR__ for synced blocks SSR errors: * * @example * { * error: { * message: "Synced blocks fetch operation timed out", * stack: "Error: Synced blocks fetch operation timed out\n at /tmp/script.js:xxx:xxx" * }, * meta: { * code: "SYNCED_BLOCKS_FETCH_TIMEOUT", * contentId: "XXXXXX", * cloudId: "XXXX-XXXX-XXXX-XXXX-XXXX", * isBlog: false, * identifiers: [ * { * resourceId: "confluence-page/XXXXXX/XXXX-XXXX-XXXX-XXXX-XXXX", * blockInstanceId: "XXXX-XXXX-XXXX-XXXX-XXXX" * } * ] * } * } * * @returns The first SSR error metadata, or undefined if no error found */ const getSyncedBlocksSSRError = () => { if (isSSR()) { return undefined; } const ssrErrors = window.__SSR_ERROR__; if (Array.isArray(ssrErrors)) { const syncedBlockErrors = ssrErrors.filter(isSyncedBlocksSSRErrorObj).map(errorWrapper => errorWrapper.meta); return syncedBlockErrors.length > 0 ? syncedBlockErrors[0] : undefined; } return undefined; }; /** * Fire analytics event for the first unprocessed SSR error that occurred during page rendering. * This function only runs ONCE per browser session to avoid duplicate analytics events. * * @param fireAnalyticsEvent - Function to fire analytics events */ export const handleSSRErrorsAnalytics = (() => { let called = false; // I want this fireAnalyticsEvent only takes in SyncedBlockSSRErrorAEP return fireAnalyticsEvent => { if (called) { return; } called = true; if (!fireAnalyticsEvent) { return; } const error = getSyncedBlocksSSRError(); if (error) { var _error$identifiers, _error$missingIdentif; fireAnalyticsEvent({ action: ACTION.ERROR, actionSubject: ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_SSR_ERROR, eventType: EVENT_TYPE.OPERATIONAL, attributes: { code: error.code, isBlog: error.isBlog, syncedBlocksCount: ((_error$identifiers = error.identifiers) === null || _error$identifiers === void 0 ? void 0 : _error$identifiers.length) || 0, missingSyncedBlocksCount: ((_error$missingIdentif = error.missingIdentifiers) === null || _error$missingIdentif === void 0 ? void 0 : _error$missingIdentif.length) || 0, errorMessage: error.errorMessage, errorName: error.errorName } }); } }; })();