@tracelog/lib 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -7
- package/dist/browser/tracelog.esm.js +669 -693
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js +2 -2
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/cjs/api.d.ts +2 -1
- package/dist/cjs/api.d.ts.map +1 -0
- package/dist/cjs/api.js +7 -6
- package/dist/cjs/api.js.map +1 -0
- package/dist/cjs/app.constants.d.ts +2 -0
- package/dist/cjs/app.constants.d.ts.map +1 -0
- package/dist/cjs/app.constants.js +17 -1
- package/dist/cjs/app.constants.js.map +1 -0
- package/dist/cjs/app.d.ts +2 -1
- package/dist/cjs/app.d.ts.map +1 -0
- package/dist/cjs/app.js +9 -9
- package/dist/cjs/app.js.map +1 -0
- package/dist/cjs/constants/config.constants.d.ts +8 -2
- package/dist/cjs/constants/config.constants.d.ts.map +1 -0
- package/dist/cjs/constants/config.constants.js +13 -6
- package/dist/cjs/constants/config.constants.js.map +1 -0
- package/dist/cjs/constants/error.constants.d.ts +1 -0
- package/dist/cjs/constants/error.constants.d.ts.map +1 -0
- package/dist/cjs/constants/error.constants.js +1 -0
- package/dist/cjs/constants/error.constants.js.map +1 -0
- package/dist/cjs/constants/index.d.ts +1 -0
- package/dist/cjs/constants/index.d.ts.map +1 -0
- package/dist/cjs/constants/index.js +1 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/cjs/constants/performance.constants.d.ts +1 -0
- package/dist/cjs/constants/performance.constants.d.ts.map +1 -0
- package/dist/cjs/constants/performance.constants.js +1 -0
- package/dist/cjs/constants/performance.constants.js.map +1 -0
- package/dist/cjs/constants/storage.constants.d.ts +1 -0
- package/dist/cjs/constants/storage.constants.d.ts.map +1 -0
- package/dist/cjs/constants/storage.constants.js +1 -0
- package/dist/cjs/constants/storage.constants.js.map +1 -0
- package/dist/cjs/handlers/click.handler.d.ts +1 -0
- package/dist/cjs/handlers/click.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/click.handler.js +1 -0
- package/dist/cjs/handlers/click.handler.js.map +1 -0
- package/dist/cjs/handlers/error.handler.d.ts +1 -0
- package/dist/cjs/handlers/error.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/error.handler.js +1 -0
- package/dist/cjs/handlers/error.handler.js.map +1 -0
- package/dist/cjs/handlers/page-view.handler.d.ts +1 -0
- package/dist/cjs/handlers/page-view.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/page-view.handler.js +2 -1
- package/dist/cjs/handlers/page-view.handler.js.map +1 -0
- package/dist/cjs/handlers/performance.handler.d.ts +1 -0
- package/dist/cjs/handlers/performance.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/performance.handler.js +1 -0
- package/dist/cjs/handlers/performance.handler.js.map +1 -0
- package/dist/cjs/handlers/scroll.handler.d.ts +1 -0
- package/dist/cjs/handlers/scroll.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/scroll.handler.js +4 -1
- package/dist/cjs/handlers/scroll.handler.js.map +1 -0
- package/dist/cjs/handlers/session.handler.d.ts +3 -2
- package/dist/cjs/handlers/session.handler.d.ts.map +1 -0
- package/dist/cjs/handlers/session.handler.js +7 -6
- package/dist/cjs/handlers/session.handler.js.map +1 -0
- package/dist/cjs/integrations/google-analytics.integration.d.ts +1 -0
- package/dist/cjs/integrations/google-analytics.integration.d.ts.map +1 -0
- package/dist/cjs/integrations/google-analytics.integration.js +7 -2
- package/dist/cjs/integrations/google-analytics.integration.js.map +1 -0
- package/dist/cjs/listeners/activity-listener-manager.d.ts +1 -0
- package/dist/cjs/listeners/activity-listener-manager.d.ts.map +1 -0
- package/dist/cjs/listeners/activity-listener-manager.js +1 -0
- package/dist/cjs/listeners/activity-listener-manager.js.map +1 -0
- package/dist/cjs/listeners/index.d.ts +1 -0
- package/dist/cjs/listeners/index.d.ts.map +1 -0
- package/dist/cjs/listeners/index.js +1 -0
- package/dist/cjs/listeners/index.js.map +1 -0
- package/dist/cjs/listeners/input-listener-managers.d.ts +1 -0
- package/dist/cjs/listeners/input-listener-managers.d.ts.map +1 -0
- package/dist/cjs/listeners/input-listener-managers.js +1 -0
- package/dist/cjs/listeners/input-listener-managers.js.map +1 -0
- package/dist/cjs/listeners/listeners.types.d.ts +1 -0
- package/dist/cjs/listeners/listeners.types.d.ts.map +1 -0
- package/dist/cjs/listeners/listeners.types.js +1 -0
- package/dist/cjs/listeners/listeners.types.js.map +1 -0
- package/dist/cjs/listeners/touch-listener-manager.d.ts +1 -0
- package/dist/cjs/listeners/touch-listener-manager.d.ts.map +1 -0
- package/dist/cjs/listeners/touch-listener-manager.js +1 -0
- package/dist/cjs/listeners/touch-listener-manager.js.map +1 -0
- package/dist/cjs/listeners/unload-listener-manager.d.ts +1 -0
- package/dist/cjs/listeners/unload-listener-manager.d.ts.map +1 -0
- package/dist/cjs/listeners/unload-listener-manager.js +1 -0
- package/dist/cjs/listeners/unload-listener-manager.js.map +1 -0
- package/dist/cjs/listeners/visibility-listener-manager.d.ts +1 -0
- package/dist/cjs/listeners/visibility-listener-manager.d.ts.map +1 -0
- package/dist/cjs/listeners/visibility-listener-manager.js +1 -0
- package/dist/cjs/listeners/visibility-listener-manager.js.map +1 -0
- package/dist/cjs/managers/event.manager.d.ts +1 -0
- package/dist/cjs/managers/event.manager.d.ts.map +1 -0
- package/dist/cjs/managers/event.manager.js +4 -3
- package/dist/cjs/managers/event.manager.js.map +1 -0
- package/dist/cjs/managers/sender.manager.d.ts +1 -8
- package/dist/cjs/managers/sender.manager.d.ts.map +1 -0
- package/dist/cjs/managers/sender.manager.js +32 -115
- package/dist/cjs/managers/sender.manager.js.map +1 -0
- package/dist/cjs/managers/session.manager.d.ts +3 -2
- package/dist/cjs/managers/session.manager.d.ts.map +1 -0
- package/dist/cjs/managers/session.manager.js +26 -27
- package/dist/cjs/managers/session.manager.js.map +1 -0
- package/dist/cjs/managers/state.manager.d.ts +1 -0
- package/dist/cjs/managers/state.manager.d.ts.map +1 -0
- package/dist/cjs/managers/state.manager.js +1 -0
- package/dist/cjs/managers/state.manager.js.map +1 -0
- package/dist/cjs/managers/storage.manager.d.ts +1 -0
- package/dist/cjs/managers/storage.manager.d.ts.map +1 -0
- package/dist/cjs/managers/storage.manager.js +4 -1
- package/dist/cjs/managers/storage.manager.js.map +1 -0
- package/dist/cjs/managers/user.manager.d.ts +1 -0
- package/dist/cjs/managers/user.manager.d.ts.map +1 -0
- package/dist/cjs/managers/user.manager.js +1 -0
- package/dist/cjs/managers/user.manager.js.map +1 -0
- package/dist/cjs/public-api.d.ts +2 -1
- package/dist/cjs/public-api.d.ts.map +1 -0
- package/dist/cjs/public-api.js +1 -0
- package/dist/cjs/public-api.js.map +1 -0
- package/dist/cjs/test-bridge.d.ts +2 -5
- package/dist/cjs/test-bridge.d.ts.map +1 -0
- package/dist/cjs/test-bridge.js +3 -10
- package/dist/cjs/test-bridge.js.map +1 -0
- package/dist/cjs/types/common.types.d.ts +6 -1
- package/dist/cjs/types/common.types.d.ts.map +1 -0
- package/dist/cjs/types/common.types.js +1 -0
- package/dist/cjs/types/common.types.js.map +1 -0
- package/dist/cjs/types/config.types.d.ts +1 -0
- package/dist/cjs/types/config.types.d.ts.map +1 -0
- package/dist/cjs/types/config.types.js +1 -0
- package/dist/cjs/types/config.types.js.map +1 -0
- package/dist/cjs/types/device.types.d.ts +1 -0
- package/dist/cjs/types/device.types.d.ts.map +1 -0
- package/dist/cjs/types/device.types.js +1 -0
- package/dist/cjs/types/device.types.js.map +1 -0
- package/dist/cjs/types/emitter.types.d.ts +1 -0
- package/dist/cjs/types/emitter.types.d.ts.map +1 -0
- package/dist/cjs/types/emitter.types.js +1 -0
- package/dist/cjs/types/emitter.types.js.map +1 -0
- package/dist/cjs/types/error.types.d.ts +1 -0
- package/dist/cjs/types/error.types.d.ts.map +1 -0
- package/dist/cjs/types/error.types.js +1 -0
- package/dist/cjs/types/error.types.js.map +1 -0
- package/dist/cjs/types/event.types.d.ts +1 -0
- package/dist/cjs/types/event.types.d.ts.map +1 -0
- package/dist/cjs/types/event.types.js +1 -0
- package/dist/cjs/types/event.types.js.map +1 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.d.ts.map +1 -0
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/log.types.d.ts +1 -0
- package/dist/cjs/types/log.types.d.ts.map +1 -0
- package/dist/cjs/types/log.types.js +1 -0
- package/dist/cjs/types/log.types.js.map +1 -0
- package/dist/cjs/types/mode.types.d.ts +1 -0
- package/dist/cjs/types/mode.types.d.ts.map +1 -0
- package/dist/cjs/types/mode.types.js +1 -0
- package/dist/cjs/types/mode.types.js.map +1 -0
- package/dist/cjs/types/queue.types.d.ts +1 -0
- package/dist/cjs/types/queue.types.d.ts.map +1 -0
- package/dist/cjs/types/queue.types.js +1 -0
- package/dist/cjs/types/queue.types.js.map +1 -0
- package/dist/cjs/types/session.types.d.ts +1 -0
- package/dist/cjs/types/session.types.d.ts.map +1 -0
- package/dist/cjs/types/session.types.js +1 -0
- package/dist/cjs/types/session.types.js.map +1 -0
- package/dist/cjs/types/state.types.d.ts +1 -0
- package/dist/cjs/types/state.types.d.ts.map +1 -0
- package/dist/cjs/types/state.types.js +1 -0
- package/dist/cjs/types/state.types.js.map +1 -0
- package/dist/cjs/types/test-bridge.types.d.ts +2 -1
- package/dist/cjs/types/test-bridge.types.d.ts.map +1 -0
- package/dist/cjs/types/test-bridge.types.js +1 -0
- package/dist/cjs/types/test-bridge.types.js.map +1 -0
- package/dist/cjs/types/validation-error.types.d.ts +1 -0
- package/dist/cjs/types/validation-error.types.d.ts.map +1 -0
- package/dist/cjs/types/validation-error.types.js +1 -0
- package/dist/cjs/types/validation-error.types.js.map +1 -0
- package/dist/cjs/types/window.types.d.ts +1 -0
- package/dist/cjs/types/window.types.d.ts.map +1 -0
- package/dist/cjs/types/window.types.js +1 -0
- package/dist/cjs/types/window.types.js.map +1 -0
- package/dist/cjs/utils/browser/device-detector.utils.d.ts +1 -0
- package/dist/cjs/utils/browser/device-detector.utils.d.ts.map +1 -0
- package/dist/cjs/utils/browser/device-detector.utils.js +1 -0
- package/dist/cjs/utils/browser/device-detector.utils.js.map +1 -0
- package/dist/cjs/utils/browser/index.d.ts +1 -0
- package/dist/cjs/utils/browser/index.d.ts.map +1 -0
- package/dist/cjs/utils/browser/index.js +1 -0
- package/dist/cjs/utils/browser/index.js.map +1 -0
- package/dist/cjs/utils/browser/qa-mode.utils.d.ts +1 -0
- package/dist/cjs/utils/browser/qa-mode.utils.d.ts.map +1 -0
- package/dist/cjs/utils/browser/qa-mode.utils.js +1 -0
- package/dist/cjs/utils/browser/qa-mode.utils.js.map +1 -0
- package/dist/cjs/utils/browser/utm-params.utils.d.ts +1 -0
- package/dist/cjs/utils/browser/utm-params.utils.d.ts.map +1 -0
- package/dist/cjs/utils/browser/utm-params.utils.js +1 -0
- package/dist/cjs/utils/browser/utm-params.utils.js.map +1 -0
- package/dist/cjs/utils/data/index.d.ts +1 -0
- package/dist/cjs/utils/data/index.d.ts.map +1 -0
- package/dist/cjs/utils/data/index.js +1 -0
- package/dist/cjs/utils/data/index.js.map +1 -0
- package/dist/cjs/utils/data/uuid.utils.d.ts +1 -0
- package/dist/cjs/utils/data/uuid.utils.d.ts.map +1 -0
- package/dist/cjs/utils/data/uuid.utils.js +1 -0
- package/dist/cjs/utils/data/uuid.utils.js.map +1 -0
- package/dist/cjs/utils/emitter.utils.d.ts +1 -0
- package/dist/cjs/utils/emitter.utils.d.ts.map +1 -0
- package/dist/cjs/utils/emitter.utils.js +4 -1
- package/dist/cjs/utils/emitter.utils.js.map +1 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts.map +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/logging.utils.d.ts +1 -0
- package/dist/cjs/utils/logging.utils.d.ts.map +1 -0
- package/dist/cjs/utils/logging.utils.js +1 -0
- package/dist/cjs/utils/logging.utils.js.map +1 -0
- package/dist/cjs/utils/network/index.d.ts +1 -0
- package/dist/cjs/utils/network/index.d.ts.map +1 -0
- package/dist/cjs/utils/network/index.js +1 -0
- package/dist/cjs/utils/network/index.js.map +1 -0
- package/dist/cjs/utils/network/url.utils.d.ts +1 -0
- package/dist/cjs/utils/network/url.utils.d.ts.map +1 -0
- package/dist/cjs/utils/network/url.utils.js +1 -0
- package/dist/cjs/utils/network/url.utils.js.map +1 -0
- package/dist/cjs/utils/security/index.d.ts +1 -0
- package/dist/cjs/utils/security/index.d.ts.map +1 -0
- package/dist/cjs/utils/security/index.js +1 -0
- package/dist/cjs/utils/security/index.js.map +1 -0
- package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -0
- package/dist/cjs/utils/security/sanitize.utils.d.ts.map +1 -0
- package/dist/cjs/utils/security/sanitize.utils.js +2 -1
- package/dist/cjs/utils/security/sanitize.utils.js.map +1 -0
- package/dist/cjs/utils/validations/config-validations.utils.d.ts +1 -0
- package/dist/cjs/utils/validations/config-validations.utils.d.ts.map +1 -0
- package/dist/cjs/utils/validations/config-validations.utils.js +1 -0
- package/dist/cjs/utils/validations/config-validations.utils.js.map +1 -0
- package/dist/cjs/utils/validations/event-validations.utils.d.ts +1 -0
- package/dist/cjs/utils/validations/event-validations.utils.d.ts.map +1 -0
- package/dist/cjs/utils/validations/event-validations.utils.js +1 -0
- package/dist/cjs/utils/validations/event-validations.utils.js.map +1 -0
- package/dist/cjs/utils/validations/index.d.ts +1 -0
- package/dist/cjs/utils/validations/index.d.ts.map +1 -0
- package/dist/cjs/utils/validations/index.js +1 -0
- package/dist/cjs/utils/validations/index.js.map +1 -0
- package/dist/cjs/utils/validations/metadata-validations.utils.d.ts +1 -0
- package/dist/cjs/utils/validations/metadata-validations.utils.d.ts.map +1 -0
- package/dist/cjs/utils/validations/metadata-validations.utils.js +3 -2
- package/dist/cjs/utils/validations/metadata-validations.utils.js.map +1 -0
- package/dist/cjs/utils/validations/type-guards.utils.d.ts +5 -2
- package/dist/cjs/utils/validations/type-guards.utils.d.ts.map +1 -0
- package/dist/cjs/utils/validations/type-guards.utils.js +15 -2
- package/dist/cjs/utils/validations/type-guards.utils.js.map +1 -0
- package/dist/esm/api.d.ts +2 -1
- package/dist/esm/api.d.ts.map +1 -0
- package/dist/esm/api.js +7 -6
- package/dist/esm/api.js.map +1 -0
- package/dist/esm/app.constants.d.ts +2 -0
- package/dist/esm/app.constants.d.ts.map +1 -0
- package/dist/esm/app.constants.js +2 -0
- package/dist/esm/app.constants.js.map +1 -0
- package/dist/esm/app.d.ts +2 -1
- package/dist/esm/app.d.ts.map +1 -0
- package/dist/esm/app.js +9 -9
- package/dist/esm/app.js.map +1 -0
- package/dist/esm/constants/config.constants.d.ts +8 -2
- package/dist/esm/constants/config.constants.d.ts.map +1 -0
- package/dist/esm/constants/config.constants.js +11 -4
- package/dist/esm/constants/config.constants.js.map +1 -0
- package/dist/esm/constants/error.constants.d.ts +1 -0
- package/dist/esm/constants/error.constants.d.ts.map +1 -0
- package/dist/esm/constants/error.constants.js +1 -0
- package/dist/esm/constants/error.constants.js.map +1 -0
- package/dist/esm/constants/index.d.ts +1 -0
- package/dist/esm/constants/index.d.ts.map +1 -0
- package/dist/esm/constants/index.js +1 -0
- package/dist/esm/constants/index.js.map +1 -0
- package/dist/esm/constants/performance.constants.d.ts +1 -0
- package/dist/esm/constants/performance.constants.d.ts.map +1 -0
- package/dist/esm/constants/performance.constants.js +1 -0
- package/dist/esm/constants/performance.constants.js.map +1 -0
- package/dist/esm/constants/storage.constants.d.ts +1 -0
- package/dist/esm/constants/storage.constants.d.ts.map +1 -0
- package/dist/esm/constants/storage.constants.js +1 -0
- package/dist/esm/constants/storage.constants.js.map +1 -0
- package/dist/esm/handlers/click.handler.d.ts +1 -0
- package/dist/esm/handlers/click.handler.d.ts.map +1 -0
- package/dist/esm/handlers/click.handler.js +1 -0
- package/dist/esm/handlers/click.handler.js.map +1 -0
- package/dist/esm/handlers/error.handler.d.ts +1 -0
- package/dist/esm/handlers/error.handler.d.ts.map +1 -0
- package/dist/esm/handlers/error.handler.js +1 -0
- package/dist/esm/handlers/error.handler.js.map +1 -0
- package/dist/esm/handlers/page-view.handler.d.ts +1 -0
- package/dist/esm/handlers/page-view.handler.d.ts.map +1 -0
- package/dist/esm/handlers/page-view.handler.js +2 -1
- package/dist/esm/handlers/page-view.handler.js.map +1 -0
- package/dist/esm/handlers/performance.handler.d.ts +1 -0
- package/dist/esm/handlers/performance.handler.d.ts.map +1 -0
- package/dist/esm/handlers/performance.handler.js +1 -0
- package/dist/esm/handlers/performance.handler.js.map +1 -0
- package/dist/esm/handlers/scroll.handler.d.ts +1 -0
- package/dist/esm/handlers/scroll.handler.d.ts.map +1 -0
- package/dist/esm/handlers/scroll.handler.js +4 -1
- package/dist/esm/handlers/scroll.handler.js.map +1 -0
- package/dist/esm/handlers/session.handler.d.ts +3 -2
- package/dist/esm/handlers/session.handler.d.ts.map +1 -0
- package/dist/esm/handlers/session.handler.js +7 -6
- package/dist/esm/handlers/session.handler.js.map +1 -0
- package/dist/esm/integrations/google-analytics.integration.d.ts +1 -0
- package/dist/esm/integrations/google-analytics.integration.d.ts.map +1 -0
- package/dist/esm/integrations/google-analytics.integration.js +7 -2
- package/dist/esm/integrations/google-analytics.integration.js.map +1 -0
- package/dist/esm/listeners/activity-listener-manager.d.ts +1 -0
- package/dist/esm/listeners/activity-listener-manager.d.ts.map +1 -0
- package/dist/esm/listeners/activity-listener-manager.js +1 -0
- package/dist/esm/listeners/activity-listener-manager.js.map +1 -0
- package/dist/esm/listeners/index.d.ts +1 -0
- package/dist/esm/listeners/index.d.ts.map +1 -0
- package/dist/esm/listeners/index.js +1 -0
- package/dist/esm/listeners/index.js.map +1 -0
- package/dist/esm/listeners/input-listener-managers.d.ts +1 -0
- package/dist/esm/listeners/input-listener-managers.d.ts.map +1 -0
- package/dist/esm/listeners/input-listener-managers.js +1 -0
- package/dist/esm/listeners/input-listener-managers.js.map +1 -0
- package/dist/esm/listeners/listeners.types.d.ts +1 -0
- package/dist/esm/listeners/listeners.types.d.ts.map +1 -0
- package/dist/esm/listeners/listeners.types.js +1 -0
- package/dist/esm/listeners/listeners.types.js.map +1 -0
- package/dist/esm/listeners/touch-listener-manager.d.ts +1 -0
- package/dist/esm/listeners/touch-listener-manager.d.ts.map +1 -0
- package/dist/esm/listeners/touch-listener-manager.js +1 -0
- package/dist/esm/listeners/touch-listener-manager.js.map +1 -0
- package/dist/esm/listeners/unload-listener-manager.d.ts +1 -0
- package/dist/esm/listeners/unload-listener-manager.d.ts.map +1 -0
- package/dist/esm/listeners/unload-listener-manager.js +1 -0
- package/dist/esm/listeners/unload-listener-manager.js.map +1 -0
- package/dist/esm/listeners/visibility-listener-manager.d.ts +1 -0
- package/dist/esm/listeners/visibility-listener-manager.d.ts.map +1 -0
- package/dist/esm/listeners/visibility-listener-manager.js +1 -0
- package/dist/esm/listeners/visibility-listener-manager.js.map +1 -0
- package/dist/esm/managers/event.manager.d.ts +1 -0
- package/dist/esm/managers/event.manager.d.ts.map +1 -0
- package/dist/esm/managers/event.manager.js +4 -3
- package/dist/esm/managers/event.manager.js.map +1 -0
- package/dist/esm/managers/sender.manager.d.ts +1 -8
- package/dist/esm/managers/sender.manager.d.ts.map +1 -0
- package/dist/esm/managers/sender.manager.js +33 -116
- package/dist/esm/managers/sender.manager.js.map +1 -0
- package/dist/esm/managers/session.manager.d.ts +3 -2
- package/dist/esm/managers/session.manager.d.ts.map +1 -0
- package/dist/esm/managers/session.manager.js +26 -27
- package/dist/esm/managers/session.manager.js.map +1 -0
- package/dist/esm/managers/state.manager.d.ts +1 -0
- package/dist/esm/managers/state.manager.d.ts.map +1 -0
- package/dist/esm/managers/state.manager.js +1 -0
- package/dist/esm/managers/state.manager.js.map +1 -0
- package/dist/esm/managers/storage.manager.d.ts +1 -0
- package/dist/esm/managers/storage.manager.d.ts.map +1 -0
- package/dist/esm/managers/storage.manager.js +4 -1
- package/dist/esm/managers/storage.manager.js.map +1 -0
- package/dist/esm/managers/user.manager.d.ts +1 -0
- package/dist/esm/managers/user.manager.d.ts.map +1 -0
- package/dist/esm/managers/user.manager.js +1 -0
- package/dist/esm/managers/user.manager.js.map +1 -0
- package/dist/esm/public-api.d.ts +2 -1
- package/dist/esm/public-api.d.ts.map +1 -0
- package/dist/esm/public-api.js +1 -0
- package/dist/esm/public-api.js.map +1 -0
- package/dist/esm/test-bridge.d.ts +2 -5
- package/dist/esm/test-bridge.d.ts.map +1 -0
- package/dist/esm/test-bridge.js +3 -10
- package/dist/esm/test-bridge.js.map +1 -0
- package/dist/esm/types/common.types.d.ts +6 -1
- package/dist/esm/types/common.types.d.ts.map +1 -0
- package/dist/esm/types/common.types.js +1 -0
- package/dist/esm/types/common.types.js.map +1 -0
- package/dist/esm/types/config.types.d.ts +1 -0
- package/dist/esm/types/config.types.d.ts.map +1 -0
- package/dist/esm/types/config.types.js +1 -0
- package/dist/esm/types/config.types.js.map +1 -0
- package/dist/esm/types/device.types.d.ts +1 -0
- package/dist/esm/types/device.types.d.ts.map +1 -0
- package/dist/esm/types/device.types.js +1 -0
- package/dist/esm/types/device.types.js.map +1 -0
- package/dist/esm/types/emitter.types.d.ts +1 -0
- package/dist/esm/types/emitter.types.d.ts.map +1 -0
- package/dist/esm/types/emitter.types.js +1 -0
- package/dist/esm/types/emitter.types.js.map +1 -0
- package/dist/esm/types/error.types.d.ts +1 -0
- package/dist/esm/types/error.types.d.ts.map +1 -0
- package/dist/esm/types/error.types.js +1 -0
- package/dist/esm/types/error.types.js.map +1 -0
- package/dist/esm/types/event.types.d.ts +1 -0
- package/dist/esm/types/event.types.d.ts.map +1 -0
- package/dist/esm/types/event.types.js +1 -0
- package/dist/esm/types/event.types.js.map +1 -0
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/log.types.d.ts +1 -0
- package/dist/esm/types/log.types.d.ts.map +1 -0
- package/dist/esm/types/log.types.js +1 -0
- package/dist/esm/types/log.types.js.map +1 -0
- package/dist/esm/types/mode.types.d.ts +1 -0
- package/dist/esm/types/mode.types.d.ts.map +1 -0
- package/dist/esm/types/mode.types.js +1 -0
- package/dist/esm/types/mode.types.js.map +1 -0
- package/dist/esm/types/queue.types.d.ts +1 -0
- package/dist/esm/types/queue.types.d.ts.map +1 -0
- package/dist/esm/types/queue.types.js +1 -0
- package/dist/esm/types/queue.types.js.map +1 -0
- package/dist/esm/types/session.types.d.ts +1 -0
- package/dist/esm/types/session.types.d.ts.map +1 -0
- package/dist/esm/types/session.types.js +1 -0
- package/dist/esm/types/session.types.js.map +1 -0
- package/dist/esm/types/state.types.d.ts +1 -0
- package/dist/esm/types/state.types.d.ts.map +1 -0
- package/dist/esm/types/state.types.js +1 -0
- package/dist/esm/types/state.types.js.map +1 -0
- package/dist/esm/types/test-bridge.types.d.ts +2 -1
- package/dist/esm/types/test-bridge.types.d.ts.map +1 -0
- package/dist/esm/types/test-bridge.types.js +1 -0
- package/dist/esm/types/test-bridge.types.js.map +1 -0
- package/dist/esm/types/validation-error.types.d.ts +1 -0
- package/dist/esm/types/validation-error.types.d.ts.map +1 -0
- package/dist/esm/types/validation-error.types.js +1 -0
- package/dist/esm/types/validation-error.types.js.map +1 -0
- package/dist/esm/types/window.types.d.ts +1 -0
- package/dist/esm/types/window.types.d.ts.map +1 -0
- package/dist/esm/types/window.types.js +1 -0
- package/dist/esm/types/window.types.js.map +1 -0
- package/dist/esm/utils/browser/device-detector.utils.d.ts +1 -0
- package/dist/esm/utils/browser/device-detector.utils.d.ts.map +1 -0
- package/dist/esm/utils/browser/device-detector.utils.js +1 -0
- package/dist/esm/utils/browser/device-detector.utils.js.map +1 -0
- package/dist/esm/utils/browser/index.d.ts +1 -0
- package/dist/esm/utils/browser/index.d.ts.map +1 -0
- package/dist/esm/utils/browser/index.js +1 -0
- package/dist/esm/utils/browser/index.js.map +1 -0
- package/dist/esm/utils/browser/qa-mode.utils.d.ts +1 -0
- package/dist/esm/utils/browser/qa-mode.utils.d.ts.map +1 -0
- package/dist/esm/utils/browser/qa-mode.utils.js +1 -0
- package/dist/esm/utils/browser/qa-mode.utils.js.map +1 -0
- package/dist/esm/utils/browser/utm-params.utils.d.ts +1 -0
- package/dist/esm/utils/browser/utm-params.utils.d.ts.map +1 -0
- package/dist/esm/utils/browser/utm-params.utils.js +1 -0
- package/dist/esm/utils/browser/utm-params.utils.js.map +1 -0
- package/dist/esm/utils/data/index.d.ts +1 -0
- package/dist/esm/utils/data/index.d.ts.map +1 -0
- package/dist/esm/utils/data/index.js +1 -0
- package/dist/esm/utils/data/index.js.map +1 -0
- package/dist/esm/utils/data/uuid.utils.d.ts +1 -0
- package/dist/esm/utils/data/uuid.utils.d.ts.map +1 -0
- package/dist/esm/utils/data/uuid.utils.js +1 -0
- package/dist/esm/utils/data/uuid.utils.js.map +1 -0
- package/dist/esm/utils/emitter.utils.d.ts +1 -0
- package/dist/esm/utils/emitter.utils.d.ts.map +1 -0
- package/dist/esm/utils/emitter.utils.js +4 -1
- package/dist/esm/utils/emitter.utils.js.map +1 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.d.ts.map +1 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/logging.utils.d.ts +1 -0
- package/dist/esm/utils/logging.utils.d.ts.map +1 -0
- package/dist/esm/utils/logging.utils.js +1 -0
- package/dist/esm/utils/logging.utils.js.map +1 -0
- package/dist/esm/utils/network/index.d.ts +1 -0
- package/dist/esm/utils/network/index.d.ts.map +1 -0
- package/dist/esm/utils/network/index.js +1 -0
- package/dist/esm/utils/network/index.js.map +1 -0
- package/dist/esm/utils/network/url.utils.d.ts +1 -0
- package/dist/esm/utils/network/url.utils.d.ts.map +1 -0
- package/dist/esm/utils/network/url.utils.js +1 -0
- package/dist/esm/utils/network/url.utils.js.map +1 -0
- package/dist/esm/utils/security/index.d.ts +1 -0
- package/dist/esm/utils/security/index.d.ts.map +1 -0
- package/dist/esm/utils/security/index.js +1 -0
- package/dist/esm/utils/security/index.js.map +1 -0
- package/dist/esm/utils/security/sanitize.utils.d.ts +1 -0
- package/dist/esm/utils/security/sanitize.utils.d.ts.map +1 -0
- package/dist/esm/utils/security/sanitize.utils.js +3 -2
- package/dist/esm/utils/security/sanitize.utils.js.map +1 -0
- package/dist/esm/utils/validations/config-validations.utils.d.ts +1 -0
- package/dist/esm/utils/validations/config-validations.utils.d.ts.map +1 -0
- package/dist/esm/utils/validations/config-validations.utils.js +1 -0
- package/dist/esm/utils/validations/config-validations.utils.js.map +1 -0
- package/dist/esm/utils/validations/event-validations.utils.d.ts +1 -0
- package/dist/esm/utils/validations/event-validations.utils.d.ts.map +1 -0
- package/dist/esm/utils/validations/event-validations.utils.js +1 -0
- package/dist/esm/utils/validations/event-validations.utils.js.map +1 -0
- package/dist/esm/utils/validations/index.d.ts +1 -0
- package/dist/esm/utils/validations/index.d.ts.map +1 -0
- package/dist/esm/utils/validations/index.js +1 -0
- package/dist/esm/utils/validations/index.js.map +1 -0
- package/dist/esm/utils/validations/metadata-validations.utils.d.ts +1 -0
- package/dist/esm/utils/validations/metadata-validations.utils.d.ts.map +1 -0
- package/dist/esm/utils/validations/metadata-validations.utils.js +4 -3
- package/dist/esm/utils/validations/metadata-validations.utils.js.map +1 -0
- package/dist/esm/utils/validations/type-guards.utils.d.ts +5 -2
- package/dist/esm/utils/validations/type-guards.utils.d.ts.map +1 -0
- package/dist/esm/utils/validations/type-guards.utils.js +16 -3
- package/dist/esm/utils/validations/type-guards.utils.js.map +1 -0
- package/package.json +2 -2
package/dist/browser/tracelog.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
(function(d){"use strict";const k="data-tlog",Oe=["button","a",'input[type="button"]','input[type="submit"]','input[type="reset"]','input[type="checkbox"]','input[type="radio"]',"select","textarea",'[role="button"]','[role="link"]','[role="tab"]','[role="menuitem"]','[role="option"]','[role="checkbox"]','[role="radio"]','[role="switch"]',"[routerLink]","[ng-click]","[data-action]","[data-click]","[data-navigate]","[data-toggle]","[onclick]",".btn",".button",".clickable",".nav-link",".menu-item","[data-testid]",'[tabindex="0"]'],be=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],p={INVALID_SESSION_TIMEOUT:"Session timeout must be between 30000ms (30 seconds) and 86400000ms (24 hours)",INVALID_SAMPLING_RATE:"Sampling rate must be between 0 and 1",INVALID_ERROR_SAMPLING_RATE:"Error sampling must be between 0 and 1",INVALID_TRACELOG_PROJECT_ID:"TraceLog project ID is required when integration is enabled",INVALID_CUSTOM_API_URL:"Custom API URL is required when integration is enabled",INVALID_GOOGLE_ANALYTICS_ID:"Google Analytics measurement ID is required when integration is enabled",INVALID_SCROLL_CONTAINER_SELECTORS:"Scroll container selectors must be valid CSS selectors",INVALID_GLOBAL_METADATA:"Global metadata must be an object",INVALID_SENSITIVE_QUERY_PARAMS:"Sensitive query params must be an array of strings"},Pe=[/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,/javascript:/gi,/on\w+\s*=/gi,/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,/<embed\b[^>]*>/gi,/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi];var U=(s=>(s.Localhost="localhost:8080",s.Fail="localhost:9999",s))(U||{}),T=(s=>(s.Mobile="mobile",s.Tablet="tablet",s.Desktop="desktop",s.Unknown="unknown",s))(T||{}),H=(s=>(s.EVENT="event",s.QUEUE="queue",s))(H||{});class _ extends Error{constructor(e,t){super(e),this.statusCode=t,this.name="PermanentError",Error.captureStackTrace&&Error.captureStackTrace(this,_)}}var h=(s=>(s.PAGE_VIEW="page_view",s.CLICK="click",s.SCROLL="scroll",s.SESSION_START="session_start",s.SESSION_END="session_end",s.CUSTOM="custom",s.WEB_VITALS="web_vitals",s.ERROR="error",s))(h||{}),b=(s=>(s.UP="up",s.DOWN="down",s))(b||{}),M=(s=>(s.JS_ERROR="js_error",s.PROMISE_REJECTION="promise_rejection",s))(M||{}),L=(s=>(s.QA="qa",s))(L||{});class N extends Error{constructor(e,t,r){super(e),this.errorCode=t,this.layer=r,this.name=this.constructor.name,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class A extends N{constructor(e,t="config"){super(e,"APP_CONFIG_INVALID",t)}}class le extends N{constructor(e,t="config"){super(e,"SESSION_TIMEOUT_INVALID",t)}}class j extends N{constructor(e,t="config"){super(e,"SAMPLING_RATE_INVALID",t)}}class v extends N{constructor(e,t="config"){super(e,"INTEGRATION_INVALID",t)}}class De extends N{constructor(e,t,r="runtime"){super(e,"INITIALIZATION_TIMEOUT",r),this.timeoutMs=t}}const ke=(s,e)=>{if(e){if(e instanceof Error){const t=e.message.replace(/\s+at\s+.*$/gm,"").replace(/\(.*?:\d+:\d+\)/g,"");return`[TraceLog] ${s}: ${t}`}return`[TraceLog] ${s}: ${e instanceof Error?e.message:"Unknown error"}`}return`[TraceLog] ${s}`},o=(s,e,t)=>{const{error:r,data:n,showToClient:i=!1}=t??{},a=r?ke(e,r):`[TraceLog] ${e}`,c=s==="error"?"error":s==="warn"?"warn":"log";if(!(s==="debug"||s==="info"&&!i))if(n!==void 0){const l=Ue(n);console[c](a,l)}else n!==void 0?console[c](a,n):console[c](a)},Ue=s=>{const e={},t=["token","password","secret","key","apikey","api_key","sessionid","session_id"];for(const[r,n]of Object.entries(s)){const i=r.toLowerCase();t.some(a=>i.includes(a))?e[r]="[REDACTED]":e[r]=n}return e};let X,ue;const He=()=>{typeof window<"u"&&!X&&(X=window.matchMedia("(pointer: coarse)"),ue=window.matchMedia("(hover: none)"))},Ve=()=>{try{const s=navigator;if(s.userAgentData&&typeof s.userAgentData.mobile=="boolean")return s.userAgentData.platform&&/ipad|tablet/i.test(s.userAgentData.platform)?T.Tablet:s.userAgentData.mobile?T.Mobile:T.Desktop;He();const e=window.innerWidth,t=X?.matches??!1,r=ue?.matches??!1,n="ontouchstart"in window||navigator.maxTouchPoints>0,i=navigator.userAgent.toLowerCase(),a=/mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i),c=/tablet|ipad|android(?!.*mobile)/.test(i);return e<=767||a&&n?T.Mobile:e>=768&&e<=1024||c||t&&r&&n?T.Tablet:T.Desktop}catch(s){return o("warn","Device detection failed, defaulting to desktop",{error:s}),T.Desktop}},I="tlog",de=`${I}:qa_mode`,Fe=`${I}:uid`,xe=s=>s?`${I}:${s}:queue`:`${I}:queue`,Ge=s=>s?`${I}:${s}:session`:`${I}:session`,ze=s=>s?`${I}:${s}:broadcast`:`${I}:broadcast`,he={LCP:4e3,FCP:1800,CLS:.25,INP:200,TTFB:800,LONG_TASK:50},$e=1e3,fe=[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/gi,/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,/\b[A-Z]{2}\d{2}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/gi,/\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\b/gi,/Bearer\s+[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)?(?:\.[A-Za-z0-9_-]+)?/gi,/:\/\/[^:/]+:([^@]+)@/gi],ge=500,Ee=5e3,V=50,Qe=V*2,Be=6e4,Se="tlog_mode",je="qa",Xe=()=>{if(sessionStorage.getItem(de)==="true")return!0;const e=new URLSearchParams(window.location.search),r=e.get(Se)===je;if(r){sessionStorage.setItem(de,"true"),e.delete(Se);const n=e.toString(),i=`${window.location.pathname}${n?"?"+n:""}${window.location.hash}`;try{window.history.replaceState({},"",i)}catch(a){o("warn","History API not available, cannot replace URL",{error:a})}console.log("%c[TraceLog] QA Mode ACTIVE","background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;")}return r},me=()=>{const s=new URLSearchParams(window.location.search),e={};return be.forEach(r=>{const n=s.get(r);if(n){const i=r.split("utm_")[1];e[i]=n}}),Object.keys(e).length?e:void 0},We=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,s=>{const e=Math.random()*16|0;return(s==="x"?e:e&3|8).toString(16)}),Ye=()=>{const s=Date.now();let e="";try{if(typeof crypto<"u"&&crypto.getRandomValues){const t=crypto.getRandomValues(new Uint8Array(4));t&&(e=Array.from(t,r=>r.toString(16).padStart(2,"0")).join(""))}}catch{}return e||(e=Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0")),`${s}-${e}`},pe=(s,e=!1)=>{try{const t=new URL(s),r=t.protocol==="https:",n=t.protocol==="http:";return r||e&&n}catch{return!1}},Ke=s=>{if(s.integrations?.tracelog?.projectId){const n=new URL(window.location.href).hostname.split(".");if(n.length===0)throw new Error("Invalid URL");const i=s.integrations.tracelog.projectId,a=n.slice(-2).join("."),c=`https://${i}.${a}/collect`;if(!pe(c))throw new Error("Invalid URL");return c}const e=s.integrations?.custom?.collectApiUrl;if(e){const t=s.integrations?.custom?.allowHttp??!1;if(!pe(e,t))throw new Error("Invalid URL");return e}return""},W=(s,e=[])=>{try{const t=new URL(s),r=t.searchParams;let n=!1;const i=[];return e.forEach(c=>{r.has(c)&&(r.delete(c),n=!0,i.push(c))}),!n&&s.includes("?")?s:(t.search=r.toString(),t.toString())}catch(t){return o("warn","URL normalization failed, returning original",{error:t,data:{url:s.slice(0,100)}}),s}},Te=s=>{if(!s||typeof s!="string"||s.trim().length===0)return"";let e=s;s.length>1e3&&(e=s.slice(0,Math.max(0,1e3)));let t=0;for(const n of Pe){const i=e;e=e.replace(n,""),i!==e&&t++}return t>0&&o("warn","XSS patterns detected and removed",{data:{patternMatches:t,originalValue:s.slice(0,100)}}),e=e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'").replaceAll("/","/"),e.trim()},Y=(s,e=0)=>{if(e>3||s==null)return null;if(typeof s=="string")return Te(s);if(typeof s=="number")return!Number.isFinite(s)||s<-Number.MAX_SAFE_INTEGER||s>Number.MAX_SAFE_INTEGER?0:s;if(typeof s=="boolean")return s;if(Array.isArray(s))return s.slice(0,100).map(n=>Y(n,e+1)).filter(n=>n!==null);if(typeof s=="object"){const t={},n=Object.entries(s).slice(0,20);for(const[i,a]of n){const c=Te(i);if(c){const l=Y(a,e+1);l!==null&&(t[c]=l)}}return t}return null},qe=s=>{if(typeof s!="object"||s===null)return{};try{const e=Y(s);return typeof e=="object"&&e!==null?e:{}}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`[TraceLog] Metadata sanitization failed: ${t}`)}},Ze=s=>{if(s!==void 0&&(s===null||typeof s!="object"))throw new A("Configuration must be an object","config");if(s){if(s.sessionTimeout!==void 0&&(typeof s.sessionTimeout!="number"||s.sessionTimeout<3e4||s.sessionTimeout>864e5))throw new le(p.INVALID_SESSION_TIMEOUT,"config");if(s.globalMetadata!==void 0&&(typeof s.globalMetadata!="object"||s.globalMetadata===null))throw new A(p.INVALID_GLOBAL_METADATA,"config");if(s.scrollContainerSelectors!==void 0&&et(s.scrollContainerSelectors),s.integrations&&tt(s.integrations),s.sensitiveQueryParams!==void 0){if(!Array.isArray(s.sensitiveQueryParams))throw new A(p.INVALID_SENSITIVE_QUERY_PARAMS,"config");for(const e of s.sensitiveQueryParams)if(typeof e!="string")throw new A("All sensitive query params must be strings","config")}if(s.errorSampling!==void 0&&(typeof s.errorSampling!="number"||s.errorSampling<0||s.errorSampling>1))throw new j(p.INVALID_ERROR_SAMPLING_RATE,"config");if(s.samplingRate!==void 0&&(typeof s.samplingRate!="number"||s.samplingRate<0||s.samplingRate>1))throw new j(p.INVALID_SAMPLING_RATE,"config")}},Je=s=>{if(s.includes("<")||s.includes(">")||/on\w+\s*=/i.test(s)||!/^[a-zA-Z0-9\-_#.[\]="':, >+~*()]+$/.test(s))return!1;let t=0;for(const n of s)if(n==="("&&t++,n===")"&&t--,t<0)return!1;if(t!==0)return!1;let r=0;for(const n of s)if(n==="["&&r++,n==="]"&&r--,r<0)return!1;return r===0},et=s=>{const e=Array.isArray(s)?s:[s];for(const t of e){if(typeof t!="string"||t.trim()==="")throw o("error","Invalid scroll container selector",{showToClient:!0,data:{selector:t,type:typeof t,isEmpty:t===""||typeof t=="string"&&t.trim()===""}}),new A(p.INVALID_SCROLL_CONTAINER_SELECTORS,"config");if(!Je(t))throw o("error","Invalid or potentially unsafe CSS selector",{showToClient:!0,data:{selector:t,reason:"Failed security validation"}}),new A("Invalid or potentially unsafe CSS selector","config")}},tt=s=>{if(s){if(s.tracelog&&(!s.tracelog.projectId||typeof s.tracelog.projectId!="string"||s.tracelog.projectId.trim()===""))throw new v(p.INVALID_TRACELOG_PROJECT_ID,"config");if(s.custom){if(!s.custom.collectApiUrl||typeof s.custom.collectApiUrl!="string"||s.custom.collectApiUrl.trim()==="")throw new v(p.INVALID_CUSTOM_API_URL,"config");if(s.custom.allowHttp!==void 0&&typeof s.custom.allowHttp!="boolean")throw new v("allowHttp must be a boolean","config");const e=s.custom.collectApiUrl.trim();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new v('Custom API URL must start with "http://" or "https://"',"config");if(!(s.custom.allowHttp??!1)&&e.startsWith("http://"))throw new v("Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)","config")}if(s.googleAnalytics){if(!s.googleAnalytics.measurementId||typeof s.googleAnalytics.measurementId!="string"||s.googleAnalytics.measurementId.trim()==="")throw new v(p.INVALID_GOOGLE_ANALYTICS_ID,"config");if(!s.googleAnalytics.measurementId.trim().match(/^(G-|UA-)/))throw new v('Google Analytics measurement ID must start with "G-" or "UA-"',"config")}}},rt=s=>{Ze(s);const e={...s??{},sessionTimeout:s?.sessionTimeout??9e5,globalMetadata:s?.globalMetadata??{},sensitiveQueryParams:s?.sensitiveQueryParams??[],errorSampling:s?.errorSampling??1,samplingRate:s?.samplingRate??1};return e.integrations?.custom&&(e.integrations.custom={...e.integrations.custom,allowHttp:e.integrations.custom.allowHttp??!1}),e},st=s=>{if(typeof s=="string")return!0;if(typeof s=="object"&&s!==null&&!Array.isArray(s)){const e=Object.entries(s);if(e.length>20)return!1;for(const[,t]of e){if(t==null)continue;const r=typeof t;if(r!=="string"&&r!=="number"&&r!=="boolean")return!1}return!0}return!1},nt=s=>{if(typeof s!="object"||s===null)return!1;for(const e of Object.values(s)){if(e==null)continue;const t=typeof e;if(!(t==="string"||t==="number"||t==="boolean")){if(Array.isArray(e)){if(e.length===0)continue;if(typeof e[0]=="string"){if(!e.every(i=>typeof i=="string"))return!1}else if(!e.every(i=>st(i)))return!1;continue}return!1}}return!0},it=s=>typeof s!="string"?{valid:!1,error:"Event name must be a string"}:s.length===0?{valid:!1,error:"Event name cannot be empty"}:s.length>120?{valid:!1,error:"Event name is too long (max 120 characters)"}:s.includes("<")||s.includes(">")||s.includes("&")?{valid:!1,error:"Event name contains invalid characters"}:["constructor","prototype","__proto__","eval","function","var","let","const"].includes(s.toLowerCase())?{valid:!1,error:"Event name cannot be a reserved word"}:{valid:!0},_e=(s,e,t)=>{const r=qe(e),n=`${t} "${s}" metadata error`;if(!nt(r))return{valid:!1,error:`${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`};let i;try{i=JSON.stringify(r)}catch{return{valid:!1,error:`${n}: object contains circular references or cannot be serialized.`}}if(i.length>8192)return{valid:!1,error:`${n}: object is too large (max ${8192/1024} KB).`};if(Object.keys(r).length>10)return{valid:!1,error:`${n}: object has too many keys (max 10 keys).`};for(const[c,l]of Object.entries(r)){if(Array.isArray(l)){if(l.length>10)return{valid:!1,error:`${n}: array property "${c}" is too large (max 10 items).`};for(const u of l)if(typeof u=="string"&&u.length>500)return{valid:!1,error:`${n}: array property "${c}" contains strings that are too long (max 500 characters).`}}if(typeof l=="string"&&l.length>1e3)return{valid:!1,error:`${n}: property "${c}" is too long (max 1000 characters).`}}return{valid:!0,sanitizedMetadata:r}},at=(s,e,t)=>{if(Array.isArray(e)){const r=[],n=`${t} "${s}" metadata error`;for(let i=0;i<e.length;i++){const a=e[i];if(typeof a!="object"||a===null||Array.isArray(a))return{valid:!1,error:`${n}: array item at index ${i} must be an object.`};const c=_e(s,a,t);if(!c.valid)return{valid:!1,error:`${n}: array item at index ${i} is invalid: ${c.error}`};c.sanitizedMetadata&&r.push(c.sanitizedMetadata)}return{valid:!0,sanitizedMetadata:r}}return _e(s,e,t)},ot=(s,e)=>{const t=it(s);if(!t.valid)return o("error","Event name validation failed",{showToClient:!0,data:{eventName:s,error:t.error}}),t;if(!e)return{valid:!0};const r=at(s,e,"customEvent");return r.valid||o("error","Event metadata validation failed",{showToClient:!0,data:{eventName:s,error:r.error}}),r};class ct{listeners=new Map;on(e,t){this.listeners.has(e)||this.listeners.set(e,[]),this.listeners.get(e).push(t)}off(e,t){const r=this.listeners.get(e);if(r){const n=r.indexOf(t);n>-1&&r.splice(n,1)}}emit(e,t){const r=this.listeners.get(e);r&&r.forEach(n=>n(t))}removeAllListeners(){this.listeners.clear()}}const K={};class g{get(e){return K[e]}set(e,t){K[e]=t}getState(){return{...K}}}class lt extends g{storeManager;retryTimeoutId=null;retryCount=0;isRetrying=!1;lastPermanentErrorLog=null;constructor(e){super(),this.storeManager=e}getQueueStorageKey(){const e=this.get("userId")||"anonymous";return xe(e)}sendEventsQueueSync(e){if(this.shouldSkipSend())return this.resetRetryState(),!0;if(this.get("config")?.integrations?.custom?.collectApiUrl===U.Fail)return o("warn","Fail mode: simulating network failure (sync)",{data:{events:e.events.length}}),!1;const r=this.sendQueueSyncInternal(e);return r&&this.resetRetryState(),r}async sendEventsQueue(e,t){this.shouldSkipSend()||this.persistEvents(e)||o("warn","Failed to persist events, attempting immediate send");try{const r=await this.send(e);return r?(this.clearPersistedEvents(),this.resetRetryState(),t?.onSuccess?.(e.events.length,e.events,e)):(this.scheduleRetry(e,t),t?.onFailure?.()),r}catch(r){if(r instanceof _)return this.logPermanentError("Permanent error, not retrying",r),this.clearPersistedEvents(),this.resetRetryState(),t?.onFailure?.(),!1;throw r}}async recoverPersistedEvents(e){try{const t=this.getPersistedData();if(!t||!this.isDataRecent(t)||t.events.length===0){this.clearPersistedEvents();return}const r=this.createRecoveryBody(t);await this.send(r)?(this.clearPersistedEvents(),this.resetRetryState(),e?.onSuccess?.(t.events.length,t.events,r)):(this.scheduleRetry(r,e),e?.onFailure?.())}catch(t){if(t instanceof _){this.logPermanentError("Permanent error during recovery, clearing persisted events",t),this.clearPersistedEvents(),this.resetRetryState(),e?.onFailure?.();return}o("error","Failed to recover persisted events",{error:t}),this.clearPersistedEvents()}}persistEventsForRecovery(e){return this.persistEvents(e)}async sendEventsQueueAsync(e){return this.sendEventsQueue(e)}stop(){this.clearRetryTimeout(),this.resetRetryState()}async send(e){if(this.shouldSkipSend())return this.simulateSuccessfulSend();if(this.get("config")?.integrations?.custom?.collectApiUrl===U.Fail)return o("warn","Fail mode: simulating network failure",{data:{events:e.events.length}}),!1;const{url:r,payload:n}=this.prepareRequest(e);try{return(await this.sendWithTimeout(r,n)).ok}catch(i){if(i instanceof _)throw i;return o("error","Send request failed",{error:i,data:{events:e.events.length,url:r.replace(/\/\/[^/]+/,"//[DOMAIN]")}}),!1}}async sendWithTimeout(e,t){const r=new AbortController,n=setTimeout(()=>r.abort(),1e4);try{const i=await fetch(e,{method:"POST",body:t,keepalive:!0,credentials:"include",signal:r.signal,headers:{"Content-Type":"application/json"}});if(!i.ok)throw i.status>=400&&i.status<500?new _(`HTTP ${i.status}: ${i.statusText}`,i.status):new Error(`HTTP ${i.status}: ${i.statusText}`);return i}finally{clearTimeout(n)}}sendQueueSyncInternal(e){const{url:t,payload:r}=this.prepareRequest(e),n=new Blob([r],{type:"application/json"});if(this.isSendBeaconAvailable()){if(navigator.sendBeacon(t,n))return!0;o("warn","sendBeacon failed, persisting events for recovery")}else o("warn","sendBeacon not available, persisting events for recovery");return this.persistEventsForRecovery(e),!1}prepareRequest(e){const t={...e,_metadata:{referer:typeof window<"u"?window.location.href:void 0,timestamp:Date.now()}};return{url:this.get("collectApiUrl"),payload:JSON.stringify(t)}}getPersistedData(){try{const e=this.getQueueStorageKey(),t=this.storeManager.getItem(e);if(t)return JSON.parse(t)}catch(e){o("warn","Failed to parse persisted data",{error:e}),this.clearPersistedEvents()}return null}isDataRecent(e){return!e.timestamp||typeof e.timestamp!="number"?!1:(Date.now()-e.timestamp)/(1e3*60*60)<2}createRecoveryBody(e){return{user_id:e.userId,session_id:e.sessionId,device:e.device,events:e.events,...e.global_metadata&&{global_metadata:e.global_metadata}}}persistEvents(e){try{const t={userId:e.user_id,sessionId:e.session_id,device:e.device,events:e.events,timestamp:Date.now(),...e.global_metadata&&{global_metadata:e.global_metadata}},r=this.getQueueStorageKey();return this.storeManager.setItem(r,JSON.stringify(t)),!!this.storeManager.getItem(r)}catch(t){return o("warn","Failed to persist events",{error:t}),!1}}clearPersistedEvents(){try{const e=this.getQueueStorageKey();this.storeManager.removeItem(e)}catch(e){o("warn","Failed to clear persisted events",{error:e})}}resetRetryState(){this.retryCount=0,this.isRetrying=!1,this.clearRetryTimeout()}scheduleRetry(e,t){if(this.retryTimeoutId!==null||this.isRetrying)return;if(this.retryCount>=3){o("warn","Max retries reached, giving up",{data:{retryCount:this.retryCount}}),this.clearPersistedEvents(),this.resetRetryState(),t?.onFailure?.();return}const r=5e3*Math.pow(2,this.retryCount);this.isRetrying=!0,this.retryTimeoutId=window.setTimeout(async()=>{this.retryTimeoutId=null,this.retryCount++;try{await this.send(e)?(this.clearPersistedEvents(),this.resetRetryState(),t?.onSuccess?.(e.events.length)):this.retryCount>=3?(this.clearPersistedEvents(),this.resetRetryState(),t?.onFailure?.()):this.scheduleRetry(e,t)}catch(n){if(n instanceof _){this.logPermanentError("Permanent error detected during retry, giving up",n),this.clearPersistedEvents(),this.resetRetryState(),t?.onFailure?.();return}this.retryCount>=3?(this.clearPersistedEvents(),this.resetRetryState(),t?.onFailure?.()):this.scheduleRetry(e,t)}finally{this.isRetrying=!1}},r)}shouldSkipSend(){return!this.get("collectApiUrl")}async simulateSuccessfulSend(){const e=Math.random()*400+100;return await new Promise(t=>setTimeout(t,e)),!0}isSendBeaconAvailable(){return typeof navigator<"u"&&typeof navigator.sendBeacon=="function"}clearRetryTimeout(){this.retryTimeoutId!==null&&(clearTimeout(this.retryTimeoutId),this.retryTimeoutId=null)}logPermanentError(e,t){const r=Date.now();(!this.lastPermanentErrorLog||this.lastPermanentErrorLog.statusCode!==t.statusCode||r-this.lastPermanentErrorLog.timestamp>=Be)&&(o("error",e,{data:{status:t.statusCode,message:t.message}}),this.lastPermanentErrorLog={statusCode:t.statusCode,timestamp:r})}}class ut extends g{googleAnalytics;dataSender;emitter;eventsQueue=[];pendingEventsBuffer=[];lastEventFingerprint=null;lastEventTime=0;sendIntervalId=null;rateLimitCounter=0;rateLimitWindowStart=0;constructor(e,t=null,r=null){super(),this.googleAnalytics=t,this.dataSender=new lt(e),this.emitter=r}async recoverPersistedEvents(){await this.dataSender.recoverPersistedEvents({onSuccess:(e,t,r)=>{if(t&&t.length>0){const n=t.map(i=>i.id);this.removeProcessedEvents(n),r&&this.emitEventsQueue(r)}},onFailure:async()=>{o("warn","Failed to recover persisted events")}})}track({type:e,page_url:t,from_page_url:r,scroll_data:n,click_data:i,custom_event:a,web_vitals:c,error_data:l,session_end_reason:u}){if(!e){o("error","Event type is required - event will be ignored");return}if(!this.get("sessionId")){this.pendingEventsBuffer.length>=100&&(this.pendingEventsBuffer.shift(),o("warn","Pending events buffer full - dropping oldest event",{data:{maxBufferSize:100}})),this.pendingEventsBuffer.push({type:e,page_url:t,from_page_url:r,scroll_data:n,click_data:i,custom_event:a,web_vitals:c,error_data:l,session_end_reason:u});return}const y=e===h.SESSION_START||e===h.SESSION_END;if(!y&&!this.checkRateLimit())return;const D=e,Jt=D===h.SESSION_START,er=t||this.get("pageUrl"),ce=this.buildEventPayload({type:D,page_url:er,from_page_url:r,scroll_data:n,click_data:i,custom_event:a,web_vitals:c,error_data:l,session_end_reason:u});if(!(!y&&!this.shouldSample())){if(Jt){const Ce=this.get("sessionId");if(!Ce){o("error","Session start event requires sessionId - event will be ignored");return}if(this.get("hasStartSession")){o("warn","Duplicate session_start detected",{data:{sessionId:Ce}});return}this.set("hasStartSession",!0)}if(!this.isDuplicateEvent(ce)){if(this.get("mode")===L.QA&&D===h.CUSTOM&&a){console.log("[TraceLog] Event",{name:a.name,...a.metadata&&{metadata:a.metadata}}),this.emitEvent(ce);return}this.addToQueue(ce)}}}stop(){this.sendIntervalId&&(clearInterval(this.sendIntervalId),this.sendIntervalId=null),this.eventsQueue=[],this.pendingEventsBuffer=[],this.lastEventFingerprint=null,this.lastEventTime=0,this.rateLimitCounter=0,this.rateLimitWindowStart=0,this.dataSender.stop()}async flushImmediately(){return this.flushEvents(!1)}flushImmediatelySync(){return this.flushEvents(!0)}getQueueLength(){return this.eventsQueue.length}flushPendingEvents(){if(this.pendingEventsBuffer.length===0)return;if(!this.get("sessionId")){o("warn","Cannot flush pending events: session not initialized - keeping in buffer",{data:{bufferedEventCount:this.pendingEventsBuffer.length}});return}const t=[...this.pendingEventsBuffer];this.pendingEventsBuffer=[],t.forEach(r=>{this.track(r)})}clearSendInterval(){this.sendIntervalId&&(clearInterval(this.sendIntervalId),this.sendIntervalId=null)}flushEvents(e){if(this.eventsQueue.length===0)return e?!0:Promise.resolve(!0);const t=this.buildEventsPayload(),r=[...this.eventsQueue],n=r.map(i=>i.id);if(e){const i=this.dataSender.sendEventsQueueSync(t);return i&&(this.removeProcessedEvents(n),this.clearSendInterval(),this.emitEventsQueue(t)),i}else return this.dataSender.sendEventsQueue(t,{onSuccess:()=>{this.removeProcessedEvents(n),this.clearSendInterval(),this.emitEventsQueue(t)},onFailure:()=>{o("warn","Async flush failed",{data:{eventCount:r.length}})}})}async sendEventsQueue(){if(!this.get("sessionId")||this.eventsQueue.length===0)return;const e=this.buildEventsPayload(),t=[...this.eventsQueue],r=t.map(n=>n.id);await this.dataSender.sendEventsQueue(e,{onSuccess:()=>{this.removeProcessedEvents(r),this.emitEventsQueue(e)},onFailure:async()=>{o("warn","Events send failed, keeping in queue",{data:{eventCount:t.length}})}})}buildEventsPayload(){const e=new Map,t=[];for(const n of this.eventsQueue){const i=this.createEventSignature(n);e.has(i)||t.push(i),e.set(i,n)}const r=t.map(n=>e.get(n)).filter(n=>!!n).sort((n,i)=>n.timestamp-i.timestamp);return{user_id:this.get("userId"),session_id:this.get("sessionId"),device:this.get("device"),events:r,...this.get("config")?.globalMetadata&&{global_metadata:this.get("config")?.globalMetadata}}}buildEventPayload(e){const t=e.type===h.SESSION_START,r=e.page_url??this.get("pageUrl");return{id:Ye(),type:e.type,page_url:r,timestamp:Date.now(),...t&&{referrer:document.referrer||"Direct"},...e.from_page_url&&{from_page_url:e.from_page_url},...e.scroll_data&&{scroll_data:e.scroll_data},...e.click_data&&{click_data:e.click_data},...e.custom_event&&{custom_event:e.custom_event},...e.web_vitals&&{web_vitals:e.web_vitals},...e.error_data&&{error_data:e.error_data},...e.session_end_reason&&{session_end_reason:e.session_end_reason},...t&&me()&&{utm:me()}}}isDuplicateEvent(e){const t=Date.now(),r=this.createEventFingerprint(e);return this.lastEventFingerprint===r&&t-this.lastEventTime<500?!0:(this.lastEventFingerprint=r,this.lastEventTime=t,!1)}createEventFingerprint(e){let t=`${e.type}_${e.page_url}`;if(e.click_data){const r=Math.round((e.click_data.x||0)/10)*10,n=Math.round((e.click_data.y||0)/10)*10;t+=`_click_${r}_${n}`}return e.scroll_data&&(t+=`_scroll_${e.scroll_data.depth}_${e.scroll_data.direction}`),e.custom_event&&(t+=`_custom_${e.custom_event.name}`),e.web_vitals&&(t+=`_vitals_${e.web_vitals.type}`),e.error_data&&(t+=`_error_${e.error_data.type}_${e.error_data.message}`),t}createEventSignature(e){return this.createEventFingerprint(e)}addToQueue(e){if(this.eventsQueue.push(e),this.emitEvent(e),this.eventsQueue.length>100){const t=this.eventsQueue.findIndex(n=>n.type!==h.SESSION_START&&n.type!==h.SESSION_END),r=t>=0?this.eventsQueue.splice(t,1)[0]:this.eventsQueue.shift();o("warn","Event queue overflow, oldest non-critical event removed",{data:{maxLength:100,currentLength:this.eventsQueue.length,removedEventType:r?.type,wasCritical:r?.type===h.SESSION_START||r?.type===h.SESSION_END}})}this.sendIntervalId||this.startSendInterval(),this.handleGoogleAnalyticsIntegration(e)}startSendInterval(){this.sendIntervalId=window.setInterval(()=>{this.eventsQueue.length>0&&this.sendEventsQueue()},1e4)}handleGoogleAnalyticsIntegration(e){if(this.googleAnalytics&&e.type===h.CUSTOM&&e.custom_event){if(this.get("mode")===L.QA)return;this.googleAnalytics.trackEvent(e.custom_event.name,e.custom_event.metadata??{})}}shouldSample(){const e=this.get("config")?.samplingRate??1;return Math.random()<e}checkRateLimit(){const e=Date.now();return e-this.rateLimitWindowStart>1e3&&(this.rateLimitCounter=0,this.rateLimitWindowStart=e),this.rateLimitCounter>=200?!1:(this.rateLimitCounter++,!0)}removeProcessedEvents(e){const t=new Set(e);this.eventsQueue=this.eventsQueue.filter(r=>!t.has(r.id))}emitEvent(e){this.emitter&&this.emitter.emit(H.EVENT,e)}emitEventsQueue(e){this.emitter&&this.emitter.emit(H.QUEUE,e)}}class dt{static getId(e){const t=Fe,r=e.getItem(t);if(r)return r;const n=We();return e.setItem(t,n),n}}class ht extends g{storageManager;eventManager;projectId;sessionTimeoutId=null;broadcastChannel=null;activityHandler=null;visibilityChangeHandler=null;beforeUnloadHandler=null;isTracking=!1;constructor(e,t,r){super(),this.storageManager=e,this.eventManager=t,this.projectId=r}initCrossTabSync(){if(typeof BroadcastChannel>"u"){o("warn","BroadcastChannel not supported");return}const e=this.getProjectId();this.broadcastChannel=new BroadcastChannel(ze(e)),this.broadcastChannel.onmessage=t=>{const{action:r,sessionId:n,timestamp:i,projectId:a}=t.data??{};if(a===e){if(r==="session_end"){this.resetSessionState();return}n&&typeof i=="number"&&i>Date.now()-5e3&&(this.set("sessionId",n),this.set("hasStartSession",!0),this.persistSession(n,i),this.isTracking&&this.setupSessionTimeout())}}}shareSession(e){this.broadcastChannel&&typeof this.broadcastChannel.postMessage=="function"&&this.broadcastChannel.postMessage({action:"session_start",projectId:this.getProjectId(),sessionId:e,timestamp:Date.now()})}broadcastSessionEnd(e,t){e&&this.broadcastChannel&&typeof this.broadcastChannel.postMessage=="function"&&this.broadcastChannel.postMessage({action:"session_end",projectId:this.getProjectId(),sessionId:e,reason:t,timestamp:Date.now()})}cleanupCrossTabSync(){this.broadcastChannel&&(typeof this.broadcastChannel.close=="function"&&this.broadcastChannel.close(),this.broadcastChannel=null)}recoverSession(){const e=this.loadStoredSession();if(!e)return null;const t=this.get("config")?.sessionTimeout??9e5;return Date.now()-e.lastActivity>t?(this.clearStoredSession(),null):e.id}persistSession(e,t=Date.now()){this.saveStoredSession({id:e,lastActivity:t})}clearStoredSession(){const e=this.getSessionStorageKey();this.storageManager.removeItem(e)}loadStoredSession(){const e=this.getSessionStorageKey(),t=this.storageManager.getItem(e);if(!t)return null;try{const r=JSON.parse(t);return!r.id||typeof r.lastActivity!="number"?null:r}catch{return this.storageManager.removeItem(e),null}}saveStoredSession(e){const t=this.getSessionStorageKey();this.storageManager.setItem(t,JSON.stringify(e))}getSessionStorageKey(){return Ge(this.getProjectId())}getProjectId(){return this.projectId}async startTracking(){if(this.isTracking){o("warn","Session tracking already active");return}const e=this.recoverSession(),t=e??this.generateSessionId(),r=!!e;this.isTracking=!0;try{this.set("sessionId",t),this.persistSession(t),r||this.eventManager.track({type:h.SESSION_START}),this.initCrossTabSync(),this.shareSession(t),this.setupSessionTimeout(),this.setupActivityListeners(),this.setupLifecycleListeners()}catch(n){throw this.isTracking=!1,this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupLifecycleListeners(),this.cleanupCrossTabSync(),this.set("sessionId",null),n}}generateSessionId(){return`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}setupSessionTimeout(){this.clearSessionTimeout();const e=this.get("config")?.sessionTimeout??9e5;this.sessionTimeoutId=setTimeout(()=>{this.endSession("inactivity")},e)}resetSessionTimeout(){this.setupSessionTimeout();const e=this.get("sessionId");e&&this.persistSession(e)}clearSessionTimeout(){this.sessionTimeoutId&&(clearTimeout(this.sessionTimeoutId),this.sessionTimeoutId=null)}setupActivityListeners(){this.activityHandler=()=>this.resetSessionTimeout(),document.addEventListener("click",this.activityHandler,{passive:!0}),document.addEventListener("keydown",this.activityHandler,{passive:!0}),document.addEventListener("scroll",this.activityHandler,{passive:!0})}cleanupActivityListeners(){this.activityHandler&&(document.removeEventListener("click",this.activityHandler),document.removeEventListener("keydown",this.activityHandler),document.removeEventListener("scroll",this.activityHandler),this.activityHandler=null)}setupLifecycleListeners(){this.visibilityChangeHandler||this.beforeUnloadHandler||(this.visibilityChangeHandler=()=>{document.hidden?this.clearSessionTimeout():this.get("sessionId")&&this.setupSessionTimeout()},this.beforeUnloadHandler=()=>{this.endSession("page_unload")},document.addEventListener("visibilitychange",this.visibilityChangeHandler),window.addEventListener("beforeunload",this.beforeUnloadHandler))}cleanupLifecycleListeners(){this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null)}async endSession(e){const t=this.get("sessionId");if(!t){o("warn","endSession called without active session",{data:{reason:e}}),this.resetSessionState(e);return}this.eventManager.track({type:h.SESSION_END,session_end_reason:e});const r=()=>{this.broadcastSessionEnd(t,e),this.resetSessionState(e)};if(this.eventManager.flushImmediatelySync()){r();return}try{await this.eventManager.flushImmediately(),r()}catch(i){o("warn","Async flush failed during session end",{error:i}),r()}}resetSessionState(e){this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupLifecycleListeners(),this.cleanupCrossTabSync(),e!=="page_unload"&&this.clearStoredSession(),this.set("sessionId",null),this.set("hasStartSession",!1),this.isTracking=!1}async stopTracking(){await this.endSession("manual_stop")}destroy(){this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupCrossTabSync(),this.cleanupLifecycleListeners(),this.isTracking=!1,this.set("hasStartSession",!1)}}class ft extends g{eventManager;storageManager;sessionManager=null;destroyed=!1;constructor(e,t){super(),this.eventManager=t,this.storageManager=e}async startTracking(){if(this.isActive())return;if(this.destroyed){o("warn","Cannot start tracking on destroyed handler");return}const e=this.get("config"),t=e?.integrations?.tracelog?.projectId??e?.integrations?.custom?.collectApiUrl??"default";if(!t)throw new Error("Cannot start session tracking: config not available");try{this.sessionManager=new ht(this.storageManager,this.eventManager,t),await this.sessionManager.startTracking(),this.eventManager.flushPendingEvents()}catch(r){if(this.sessionManager){try{this.sessionManager.destroy()}catch{}this.sessionManager=null}throw o("error","Failed to start session tracking",{error:r}),r}}isActive(){return this.sessionManager!==null&&!this.destroyed}async cleanupSessionManager(){this.sessionManager&&(await this.sessionManager.stopTracking(),this.sessionManager.destroy(),this.sessionManager=null)}async stopTracking(){await this.cleanupSessionManager()}destroy(){this.destroyed||(this.sessionManager&&(this.sessionManager.destroy(),this.sessionManager=null),this.destroyed=!0,this.set("hasStartSession",!1))}}class gt extends g{eventManager;onTrack;originalPushState;originalReplaceState;constructor(e,t){super(),this.eventManager=e,this.onTrack=t}startTracking(){this.trackInitialPageView(),window.addEventListener("popstate",this.trackCurrentPage,!0),window.addEventListener("hashchange",this.trackCurrentPage,!0),this.patchHistory("pushState"),this.patchHistory("replaceState")}stopTracking(){window.removeEventListener("popstate",this.trackCurrentPage,!0),window.removeEventListener("hashchange",this.trackCurrentPage,!0),this.originalPushState&&(window.history.pushState=this.originalPushState),this.originalReplaceState&&(window.history.replaceState=this.originalReplaceState)}patchHistory(e){const t=window.history[e];e==="pushState"&&!this.originalPushState?this.originalPushState=t:e==="replaceState"&&!this.originalReplaceState&&(this.originalReplaceState=t),window.history[e]=(...r)=>{t.apply(window.history,r),this.trackCurrentPage()}}trackCurrentPage=async()=>{const e=window.location.href,t=W(e,this.get("config").sensitiveQueryParams);if(this.get("pageUrl")===t)return;this.onTrack();const r=this.get("pageUrl");this.set("pageUrl",t);const n=this.extractPageViewData();this.eventManager.track({type:h.PAGE_VIEW,page_url:this.get("pageUrl"),from_page_url:r,...n&&{page_view:n}})};trackInitialPageView(){const e=W(window.location.href,this.get("config").sensitiveQueryParams),t=this.extractPageViewData();this.eventManager.track({type:h.PAGE_VIEW,page_url:e,...t&&{page_view:t}}),this.onTrack()}extractPageViewData(){const{pathname:e,search:t,hash:r}=window.location,{referrer:n}=document,{title:i}=document;return!n&&!i&&!e&&!t&&!r?void 0:{...n&&{referrer:n},...i&&{title:i},...e&&{pathname:e},...t&&{search:t},...r&&{hash:r}}}}class Et extends g{eventManager;clickHandler;constructor(e){super(),this.eventManager=e}startTracking(){this.clickHandler||(this.clickHandler=e=>{const t=e,r=t.target,n=typeof HTMLElement<"u"&&r instanceof HTMLElement?r:typeof HTMLElement<"u"&&r instanceof Node&&r.parentElement instanceof HTMLElement?r.parentElement:null;if(!n){o("warn","Click target not found or not an element");return}const i=this.findTrackingElement(n),a=this.getRelevantClickElement(n),c=this.calculateClickCoordinates(t,n);if(i){const u=this.extractTrackingData(i);if(u){const y=this.createCustomEventData(u);this.eventManager.track({type:h.CUSTOM,custom_event:{name:y.name,...y.value&&{metadata:{value:y.value}}}})}}const l=this.generateClickData(n,a,c);this.eventManager.track({type:h.CLICK,click_data:l})},window.addEventListener("click",this.clickHandler,!0))}stopTracking(){this.clickHandler&&(window.removeEventListener("click",this.clickHandler,!0),this.clickHandler=void 0)}findTrackingElement(e){return e.hasAttribute(`${k}-name`)?e:e.closest(`[${k}-name]`)||void 0}getRelevantClickElement(e){for(const t of Oe)try{if(e.matches(t))return e;const r=e.closest(t);if(r)return r}catch(r){o("warn","Invalid selector in element search",{error:r,data:{selector:t}});continue}return e}clamp(e){return Math.max(0,Math.min(1,Number(e.toFixed(3))))}calculateClickCoordinates(e,t){const r=t.getBoundingClientRect(),n=e.clientX,i=e.clientY,a=r.width>0?this.clamp((n-r.left)/r.width):0,c=r.height>0?this.clamp((i-r.top)/r.height):0;return{x:n,y:i,relativeX:a,relativeY:c}}extractTrackingData(e){const t=e.getAttribute(`${k}-name`),r=e.getAttribute(`${k}-value`);if(t)return{element:e,name:t,...r&&{value:r}}}generateClickData(e,t,r){const{x:n,y:i,relativeX:a,relativeY:c}=r,l=this.getRelevantText(e,t),u=this.extractElementAttributes(t);return{x:n,y:i,relativeX:a,relativeY:c,tag:t.tagName.toLowerCase(),...t.id&&{id:t.id},...t.className&&{class:t.className},...l&&{text:l},...u.href&&{href:u.href},...u.title&&{title:u.title},...u.alt&&{alt:u.alt},...u.role&&{role:u.role},...u["aria-label"]&&{ariaLabel:u["aria-label"]},...Object.keys(u).length>0&&{dataAttributes:u}}}getRelevantText(e,t){const r=e.textContent?.trim()??"",n=t.textContent?.trim()??"";return!r&&!n?"":r&&r.length<=255?r:n.length<=255?n:n.slice(0,252)+"..."}extractElementAttributes(e){const t=["id","class","data-testid","aria-label","title","href","type","name","alt","role"],r={};for(const n of t){const i=e.getAttribute(n);i&&(r[n]=i)}return r}createCustomEventData(e){return{name:e.name,...e.value&&{value:e.value}}}}class St extends g{eventManager;containers=[];limitWarningLogged=!1;minDepthChange=5;minIntervalMs=500;maxEventsPerSession=120;constructor(e){super(),this.eventManager=e}startTracking(){this.limitWarningLogged=!1,this.applyConfigOverrides(),this.set("scrollEventCount",0);const e=this.get("config").scrollContainerSelectors,t=Array.isArray(e)?e:typeof e=="string"?[e]:[];t.length===0?this.setupScrollContainer(window):this.trySetupContainers(t,0)}stopTracking(){for(const e of this.containers)this.clearContainerTimer(e),e.element instanceof Window?window.removeEventListener("scroll",e.listener):e.element.removeEventListener("scroll",e.listener);this.containers.length=0,this.set("scrollEventCount",0),this.limitWarningLogged=!1}trySetupContainers(e,t){const r=e.map(n=>this.safeQuerySelector(n)).filter(n=>n!=null&&typeof HTMLElement<"u"&&n instanceof HTMLElement);if(r.length>0){for(const n of r)this.containers.some(a=>a.element===n)||this.setupScrollContainer(n);return}if(t<5){setTimeout(()=>this.trySetupContainers(e,t+1),200);return}this.containers.length===0&&this.setupScrollContainer(window)}setupScrollContainer(e){if(e!==window&&!this.isElementScrollable(e))return;const t=()=>{this.get("suppressNextScroll")||(this.clearContainerTimer(n),n.debounceTimer=window.setTimeout(()=>{const i=this.calculateScrollData(n);if(i){const a=Date.now();this.processScrollEvent(n,i,a)}n.debounceTimer=null},250))},r=this.getScrollTop(e),n={element:e,lastScrollPos:r,lastDepth:this.calculateScrollDepth(r,this.getScrollHeight(e),this.getViewportHeight(e)),lastDirection:b.DOWN,lastEventTime:0,debounceTimer:null,listener:t};this.containers.push(n),e instanceof Window?window.addEventListener("scroll",t,{passive:!0}):e.addEventListener("scroll",t,{passive:!0})}processScrollEvent(e,t,r){if(!this.shouldEmitScrollEvent(e,t,r))return;e.lastEventTime=r,e.lastDepth=t.depth,e.lastDirection=t.direction;const n=this.get("scrollEventCount")??0;this.set("scrollEventCount",n+1),this.eventManager.track({type:h.SCROLL,scroll_data:t})}shouldEmitScrollEvent(e,t,r){return this.hasReachedSessionLimit()?(this.logLimitOnce(),!1):!(!this.hasElapsedMinimumInterval(e,r)||!this.hasSignificantDepthChange(e,t.depth))}hasReachedSessionLimit(){return(this.get("scrollEventCount")??0)>=this.maxEventsPerSession}hasElapsedMinimumInterval(e,t){return e.lastEventTime===0?!0:t-e.lastEventTime>=this.minIntervalMs}hasSignificantDepthChange(e,t){return Math.abs(t-e.lastDepth)>=this.minDepthChange}logLimitOnce(){this.limitWarningLogged||(this.limitWarningLogged=!0,o("warn","Max scroll events per session reached",{data:{limit:this.maxEventsPerSession}}))}applyConfigOverrides(){this.minDepthChange=5,this.minIntervalMs=500,this.maxEventsPerSession=120}isWindowScrollable(){return document.documentElement.scrollHeight>window.innerHeight}clearContainerTimer(e){e.debounceTimer!==null&&(clearTimeout(e.debounceTimer),e.debounceTimer=null)}getScrollDirection(e,t){return e>t?b.DOWN:b.UP}calculateScrollDepth(e,t,r){if(t<=r)return 0;const n=t-r;return Math.min(100,Math.max(0,Math.floor(e/n*100)))}calculateScrollData(e){const{element:t,lastScrollPos:r}=e,n=this.getScrollTop(t);if(Math.abs(n-r)<10||t===window&&!this.isWindowScrollable())return null;const a=this.getViewportHeight(t),c=this.getScrollHeight(t),l=this.getScrollDirection(n,r),u=this.calculateScrollDepth(n,c,a);return e.lastScrollPos=n,{depth:u,direction:l}}getScrollTop(e){return e instanceof Window?window.scrollY:e.scrollTop}getViewportHeight(e){return e instanceof Window?window.innerHeight:e.clientHeight}getScrollHeight(e){return e instanceof Window?document.documentElement.scrollHeight:e.scrollHeight}isElementScrollable(e){const t=getComputedStyle(e),r=t.overflowY==="auto"||t.overflowY==="scroll"||t.overflowX==="auto"||t.overflowX==="scroll"||t.overflow==="auto"||t.overflow==="scroll",n=e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;return r&&n}safeQuerySelector(e){try{return document.querySelector(e)}catch(t){return o("warn","Invalid CSS selector",{error:t,data:{selector:e},showToClient:!0}),null}}}class mt extends g{isInitialized=!1;async initialize(){if(this.isInitialized)return;const e=this.get("config").integrations?.googleAnalytics?.measurementId,t=this.get("userId");if(!(!e?.trim()||!t?.trim()))try{if(this.isScriptAlreadyLoaded()){this.isInitialized=!0;return}await this.loadScript(e),this.configureGtag(e,t),this.isInitialized=!0}catch(r){o("error","Google Analytics initialization failed",{error:r})}}trackEvent(e,t){if(!(!e?.trim()||!this.isInitialized||typeof window.gtag!="function"))try{const r=Array.isArray(t)?{items:t}:t;window.gtag("event",e,r)}catch(r){o("error","Google Analytics event tracking failed",{error:r})}}cleanup(){this.isInitialized=!1;const e=document.getElementById("tracelog-ga-script");e&&e.remove()}isScriptAlreadyLoaded(){return document.getElementById("tracelog-ga-script")?!0:!!document.querySelector('script[src*="googletagmanager.com/gtag/js"]')}async loadScript(e){return new Promise((t,r)=>{const n=document.createElement("script");n.id="tracelog-ga-script",n.async=!0,n.src=`https://www.googletagmanager.com/gtag/js?id=${e}`,n.onload=()=>t(),n.onerror=()=>r(new Error("Failed to load Google Analytics script")),document.head.appendChild(n)})}configureGtag(e,t){const r=document.createElement("script");r.innerHTML=`
|
|
1
|
+
(function(u){"use strict";const U="data-tlog",be=["button","a",'input[type="button"]','input[type="submit"]','input[type="reset"]','input[type="checkbox"]','input[type="radio"]',"select","textarea",'[role="button"]','[role="link"]','[role="tab"]','[role="menuitem"]','[role="option"]','[role="checkbox"]','[role="radio"]','[role="switch"]',"[routerLink]","[ng-click]","[data-action]","[data-click]","[data-navigate]","[data-toggle]","[onclick]",".btn",".button",".clickable",".nav-link",".menu-item","[data-testid]",'[tabindex="0"]'],De=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],T={INVALID_SESSION_TIMEOUT:"Session timeout must be between 30000ms (30 seconds) and 86400000ms (24 hours)",INVALID_SAMPLING_RATE:"Sampling rate must be between 0 and 1",INVALID_ERROR_SAMPLING_RATE:"Error sampling must be between 0 and 1",INVALID_TRACELOG_PROJECT_ID:"TraceLog project ID is required when integration is enabled",INVALID_CUSTOM_API_URL:"Custom API URL is required when integration is enabled",INVALID_GOOGLE_ANALYTICS_ID:"Google Analytics measurement ID is required when integration is enabled",INVALID_SCROLL_CONTAINER_SELECTORS:"Scroll container selectors must be valid CSS selectors",INVALID_GLOBAL_METADATA:"Global metadata must be an object",INVALID_SENSITIVE_QUERY_PARAMS:"Sensitive query params must be an array of strings"},Pe=[/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,/javascript:/gi,/on\w+\s*=/gi,/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,/<embed\b[^>]*>/gi,/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi];var k=(r=>(r.Localhost="localhost:8080",r.Fail="localhost:9999",r))(k||{}),m=(r=>(r.Mobile="mobile",r.Tablet="tablet",r.Desktop="desktop",r.Unknown="unknown",r))(m||{}),H=(r=>(r.EVENT="event",r.QUEUE="queue",r))(H||{});class A extends Error{constructor(e,t){super(e),this.statusCode=t,this.name="PermanentError",Error.captureStackTrace&&Error.captureStackTrace(this,A)}}var h=(r=>(r.PAGE_VIEW="page_view",r.CLICK="click",r.SCROLL="scroll",r.SESSION_START="session_start",r.SESSION_END="session_end",r.CUSTOM="custom",r.WEB_VITALS="web_vitals",r.ERROR="error",r))(h||{}),b=(r=>(r.UP="up",r.DOWN="down",r))(b||{}),M=(r=>(r.JS_ERROR="js_error",r.PROMISE_REJECTION="promise_rejection",r))(M||{}),w=(r=>(r.QA="qa",r))(w||{});class L extends Error{constructor(e,t,s){super(e),this.errorCode=t,this.layer=s,this.name=this.constructor.name,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class y extends L{constructor(e,t="config"){super(e,"APP_CONFIG_INVALID",t)}}class ce extends L{constructor(e,t="config"){super(e,"SESSION_TIMEOUT_INVALID",t)}}class Y extends L{constructor(e,t="config"){super(e,"SAMPLING_RATE_INVALID",t)}}class p extends L{constructor(e,t="config"){super(e,"INTEGRATION_INVALID",t)}}class Ue extends L{constructor(e,t,s="runtime"){super(e,"INITIALIZATION_TIMEOUT",s),this.timeoutMs=t}}const ke=(r,e)=>{if(e){if(e instanceof Error){const t=e.message.replace(/\s+at\s+.*$/gm,"").replace(/\(.*?:\d+:\d+\)/g,"");return`[TraceLog] ${r}: ${t}`}return`[TraceLog] ${r}: ${e instanceof Error?e.message:"Unknown error"}`}return`[TraceLog] ${r}`},o=(r,e,t)=>{const{error:s,data:n,showToClient:i=!1}=t??{},a=s?ke(e,s):`[TraceLog] ${e}`,l=r==="error"?"error":r==="warn"?"warn":"log";if(!(r==="debug"||r==="info"&&!i))if(n!==void 0){const c=He(n);console[l](a,c)}else n!==void 0?console[l](a,n):console[l](a)},He=r=>{const e={},t=["token","password","secret","key","apikey","api_key","sessionid","session_id"];for(const[s,n]of Object.entries(r)){const i=s.toLowerCase();t.some(a=>i.includes(a))?e[s]="[REDACTED]":e[s]=n}return e};let Q,ue;const Ve=()=>{typeof window<"u"&&!Q&&(Q=window.matchMedia("(pointer: coarse)"),ue=window.matchMedia("(hover: none)"))},Ge=()=>{try{const r=navigator;if(r.userAgentData&&typeof r.userAgentData.mobile=="boolean")return r.userAgentData.platform&&/ipad|tablet/i.test(r.userAgentData.platform)?m.Tablet:r.userAgentData.mobile?m.Mobile:m.Desktop;Ve();const e=window.innerWidth,t=Q?.matches??!1,s=ue?.matches??!1,n="ontouchstart"in window||navigator.maxTouchPoints>0,i=navigator.userAgent.toLowerCase(),a=/mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i),l=/tablet|ipad|android(?!.*mobile)/.test(i);return e<=767||a&&n?m.Mobile:e>=768&&e<=1024||l||t&&s&&n?m.Tablet:m.Desktop}catch(r){return o("warn","Device detection failed, defaulting to desktop",{error:r}),m.Desktop}},I="tlog",de=`${I}:qa_mode`,Fe=`${I}:uid`,xe=r=>r?`${I}:${r}:queue`:`${I}:queue`,Xe=r=>r?`${I}:${r}:session`:`${I}:session`,Be=r=>r?`${I}:${r}:broadcast`:`${I}:broadcast`,he={LCP:4e3,FCP:1800,CLS:.25,INP:200,TTFB:800,LONG_TASK:50},$e=1e3,fe=[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/gi,/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,/\b[A-Z]{2}\d{2}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/gi,/\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\b/gi,/Bearer\s+[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)?(?:\.[A-Za-z0-9_-]+)?/gi,/:\/\/[^:/]+:([^@]+)@/gi],ge=500,Ee=5e3,V=50,ze=V*2,Ye=6e4,Se="tlog_mode",Qe="qa",je=()=>{if(sessionStorage.getItem(de)==="true")return!0;const e=new URLSearchParams(window.location.search),s=e.get(Se)===Qe;if(s){sessionStorage.setItem(de,"true"),e.delete(Se);const n=e.toString(),i=`${window.location.pathname}${n?"?"+n:""}${window.location.hash}`;try{window.history.replaceState({},"",i)}catch(a){o("warn","History API not available, cannot replace URL",{error:a})}console.log("%c[TraceLog] QA Mode ACTIVE","background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;")}return s},_e=()=>{const r=new URLSearchParams(window.location.search),e={};return De.forEach(s=>{const n=r.get(s);if(n){const i=s.split("utm_")[1];e[i]=n}}),Object.keys(e).length?e:void 0},Ke=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{const e=Math.random()*16|0;return(r==="x"?e:e&3|8).toString(16)}),We=()=>{const r=Date.now();let e="";try{if(typeof crypto<"u"&&crypto.getRandomValues){const t=crypto.getRandomValues(new Uint8Array(4));t&&(e=Array.from(t,s=>s.toString(16).padStart(2,"0")).join(""))}}catch{}return e||(e=Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0")),`${r}-${e}`},Te=(r,e=!1)=>{try{const t=new URL(r),s=t.protocol==="https:",n=t.protocol==="http:";return s||e&&n}catch{return!1}},Ze=r=>{if(r.integrations?.tracelog?.projectId){const n=new URL(window.location.href).hostname.split(".");if(n.length===0)throw new Error("Invalid URL");const i=r.integrations.tracelog.projectId,a=n.slice(-2).join("."),l=`https://${i}.${a}/collect`;if(!Te(l))throw new Error("Invalid URL");return l}const e=r.integrations?.custom?.collectApiUrl;if(e){const t=r.integrations?.custom?.allowHttp??!1;if(!Te(e,t))throw new Error("Invalid URL");return e}return""},j=(r,e=[])=>{try{const t=new URL(r),s=t.searchParams;let n=!1;const i=[];return e.forEach(l=>{s.has(l)&&(s.delete(l),n=!0,i.push(l))}),!n&&r.includes("?")?r:(t.search=s.toString(),t.toString())}catch(t){return o("warn","URL normalization failed, returning original",{error:t,data:{url:r.slice(0,100)}}),r}},me=r=>{if(!r||typeof r!="string"||r.trim().length===0)return"";let e=r;r.length>1e3&&(e=r.slice(0,Math.max(0,1e3)));let t=0;for(const n of Pe){const i=e;e=e.replace(n,""),i!==e&&t++}return t>0&&o("warn","XSS patterns detected and removed",{data:{patternMatches:t,originalValue:r.slice(0,100)}}),e=e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'").replaceAll("/","/"),e.trim()},K=(r,e=0)=>{if(e>3||r==null)return null;if(typeof r=="string")return me(r);if(typeof r=="number")return!Number.isFinite(r)||r<-Number.MAX_SAFE_INTEGER||r>Number.MAX_SAFE_INTEGER?0:r;if(typeof r=="boolean")return r;if(Array.isArray(r))return r.slice(0,100).map(n=>K(n,e+1)).filter(n=>n!==null);if(typeof r=="object"){const t={},n=Object.entries(r).slice(0,20);for(const[i,a]of n){const l=me(i);if(l){const c=K(a,e+1);c!==null&&(t[l]=c)}}return t}return null},qe=r=>{if(typeof r!="object"||r===null)return{};try{const e=K(r);return typeof e=="object"&&e!==null?e:{}}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`[TraceLog] Metadata sanitization failed: ${t}`)}},Je=r=>{if(r!==void 0&&(r===null||typeof r!="object"))throw new y("Configuration must be an object","config");if(r){if(r.sessionTimeout!==void 0&&(typeof r.sessionTimeout!="number"||r.sessionTimeout<3e4||r.sessionTimeout>864e5))throw new ce(T.INVALID_SESSION_TIMEOUT,"config");if(r.globalMetadata!==void 0&&(typeof r.globalMetadata!="object"||r.globalMetadata===null))throw new y(T.INVALID_GLOBAL_METADATA,"config");if(r.scrollContainerSelectors!==void 0&&tt(r.scrollContainerSelectors),r.integrations&&rt(r.integrations),r.sensitiveQueryParams!==void 0){if(!Array.isArray(r.sensitiveQueryParams))throw new y(T.INVALID_SENSITIVE_QUERY_PARAMS,"config");for(const e of r.sensitiveQueryParams)if(typeof e!="string")throw new y("All sensitive query params must be strings","config")}if(r.errorSampling!==void 0&&(typeof r.errorSampling!="number"||r.errorSampling<0||r.errorSampling>1))throw new Y(T.INVALID_ERROR_SAMPLING_RATE,"config");if(r.samplingRate!==void 0&&(typeof r.samplingRate!="number"||r.samplingRate<0||r.samplingRate>1))throw new Y(T.INVALID_SAMPLING_RATE,"config")}},et=r=>{if(r.includes("<")||r.includes(">")||/on\w+\s*=/i.test(r)||!/^[a-zA-Z0-9\-_#.[\]="':, >+~*()]+$/.test(r))return!1;let t=0;for(const n of r)if(n==="("&&t++,n===")"&&t--,t<0)return!1;if(t!==0)return!1;let s=0;for(const n of r)if(n==="["&&s++,n==="]"&&s--,s<0)return!1;return s===0},tt=r=>{const e=Array.isArray(r)?r:[r];for(const t of e){if(typeof t!="string"||t.trim()==="")throw o("error","Invalid scroll container selector",{showToClient:!0,data:{selector:t,type:typeof t,isEmpty:t===""||typeof t=="string"&&t.trim()===""}}),new y(T.INVALID_SCROLL_CONTAINER_SELECTORS,"config");if(!et(t))throw o("error","Invalid or potentially unsafe CSS selector",{showToClient:!0,data:{selector:t,reason:"Failed security validation"}}),new y("Invalid or potentially unsafe CSS selector","config")}},rt=r=>{if(r){if(r.tracelog&&(!r.tracelog.projectId||typeof r.tracelog.projectId!="string"||r.tracelog.projectId.trim()===""))throw new p(T.INVALID_TRACELOG_PROJECT_ID,"config");if(r.custom){if(!r.custom.collectApiUrl||typeof r.custom.collectApiUrl!="string"||r.custom.collectApiUrl.trim()==="")throw new p(T.INVALID_CUSTOM_API_URL,"config");if(r.custom.allowHttp!==void 0&&typeof r.custom.allowHttp!="boolean")throw new p("allowHttp must be a boolean","config");const e=r.custom.collectApiUrl.trim();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new p('Custom API URL must start with "http://" or "https://"',"config");if(!(r.custom.allowHttp??!1)&&e.startsWith("http://"))throw new p("Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)","config")}if(r.googleAnalytics){if(!r.googleAnalytics.measurementId||typeof r.googleAnalytics.measurementId!="string"||r.googleAnalytics.measurementId.trim()==="")throw new p(T.INVALID_GOOGLE_ANALYTICS_ID,"config");if(!r.googleAnalytics.measurementId.trim().match(/^(G-|UA-)/))throw new p('Google Analytics measurement ID must start with "G-" or "UA-"',"config")}}},st=r=>{Je(r);const e={...r??{},sessionTimeout:r?.sessionTimeout??9e5,globalMetadata:r?.globalMetadata??{},sensitiveQueryParams:r?.sensitiveQueryParams??[],errorSampling:r?.errorSampling??1,samplingRate:r?.samplingRate??1};return e.integrations?.custom&&(e.integrations.custom={...e.integrations.custom,allowHttp:e.integrations.custom.allowHttp??!1}),e},nt=r=>{if(typeof r=="string")return!0;if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const e=Object.entries(r);if(e.length>20)return!1;for(const[,t]of e){if(t==null)continue;const s=typeof t;if(s!=="string"&&s!=="number"&&s!=="boolean")return!1}return!0}return!1},pe=(r,e=0)=>{if(typeof r!="object"||r===null||e>1)return!1;for(const t of Object.values(r)){if(t==null)continue;const s=typeof t;if(!(s==="string"||s==="number"||s==="boolean")){if(Array.isArray(t)){if(t.length===0)continue;if(typeof t[0]=="string"){if(!t.every(a=>typeof a=="string"))return!1}else if(!t.every(a=>nt(a)))return!1;continue}if(s==="object"&&e===0){if(!pe(t,e+1))return!1;continue}return!1}}return!0},it=r=>typeof r!="string"?{valid:!1,error:"Event name must be a string"}:r.length===0?{valid:!1,error:"Event name cannot be empty"}:r.length>120?{valid:!1,error:"Event name is too long (max 120 characters)"}:r.includes("<")||r.includes(">")||r.includes("&")?{valid:!1,error:"Event name contains invalid characters"}:["constructor","prototype","__proto__","eval","function","var","let","const"].includes(r.toLowerCase())?{valid:!1,error:"Event name cannot be a reserved word"}:{valid:!0},Ie=(r,e,t)=>{const s=qe(e),n=`${t} "${r}" metadata error`;if(!pe(s))return{valid:!1,error:`${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`};let i;try{i=JSON.stringify(s)}catch{return{valid:!1,error:`${n}: object contains circular references or cannot be serialized.`}}if(i.length>8192)return{valid:!1,error:`${n}: object is too large (max ${8192/1024} KB).`};if(Object.keys(s).length>10)return{valid:!1,error:`${n}: object has too many keys (max 10 keys).`};for(const[l,c]of Object.entries(s)){if(Array.isArray(c)){if(c.length>10)return{valid:!1,error:`${n}: array property "${l}" is too large (max 10 items).`};for(const d of c)if(typeof d=="string"&&d.length>500)return{valid:!1,error:`${n}: array property "${l}" contains strings that are too long (max 500 characters).`}}if(typeof c=="string"&&c.length>1e3)return{valid:!1,error:`${n}: property "${l}" is too long (max 1000 characters).`}}return{valid:!0,sanitizedMetadata:s}},at=(r,e,t)=>{if(Array.isArray(e)){const s=[],n=`${t} "${r}" metadata error`;for(let i=0;i<e.length;i++){const a=e[i];if(typeof a!="object"||a===null||Array.isArray(a))return{valid:!1,error:`${n}: array item at index ${i} must be an object.`};const l=Ie(r,a,t);if(!l.valid)return{valid:!1,error:`${n}: array item at index ${i} is invalid: ${l.error}`};l.sanitizedMetadata&&s.push(l.sanitizedMetadata)}return{valid:!0,sanitizedMetadata:s}}return Ie(r,e,t)},ot=(r,e)=>{const t=it(r);if(!t.valid)return o("error","Event name validation failed",{showToClient:!0,data:{eventName:r,error:t.error}}),t;if(!e)return{valid:!0};const s=at(r,e,"customEvent");return s.valid||o("error","Event metadata validation failed",{showToClient:!0,data:{eventName:r,error:s.error}}),s};class lt{listeners=new Map;on(e,t){this.listeners.has(e)||this.listeners.set(e,[]),this.listeners.get(e).push(t)}off(e,t){const s=this.listeners.get(e);if(s){const n=s.indexOf(t);n>-1&&s.splice(n,1)}}emit(e,t){const s=this.listeners.get(e);s&&s.forEach(n=>{n(t)})}removeAllListeners(){this.listeners.clear()}}const W={};class g{get(e){return W[e]}set(e,t){W[e]=t}getState(){return{...W}}}class ct extends g{storeManager;lastPermanentErrorLog=null;constructor(e){super(),this.storeManager=e}getQueueStorageKey(){const e=this.get("userId")||"anonymous";return xe(e)}sendEventsQueueSync(e){return this.shouldSkipSend()?!0:this.get("config")?.integrations?.custom?.collectApiUrl===k.Fail?(o("warn","Fail mode: simulating network failure (sync)",{data:{events:e.events.length}}),!1):this.sendQueueSyncInternal(e)}async sendEventsQueue(e,t){try{const s=await this.send(e);return s?(this.clearPersistedEvents(),t?.onSuccess?.(e.events.length,e.events,e)):(this.persistEvents(e),t?.onFailure?.()),s}catch(s){return s instanceof A?(this.logPermanentError("Permanent error, not retrying",s),this.clearPersistedEvents(),t?.onFailure?.(),!1):(this.persistEvents(e),t?.onFailure?.(),!1)}}async recoverPersistedEvents(e){try{const t=this.getPersistedData();if(!t||!this.isDataRecent(t)||t.events.length===0){this.clearPersistedEvents();return}const s=this.createRecoveryBody(t);await this.send(s)?(this.clearPersistedEvents(),e?.onSuccess?.(t.events.length,t.events,s)):e?.onFailure?.()}catch(t){if(t instanceof A){this.logPermanentError("Permanent error during recovery, clearing persisted events",t),this.clearPersistedEvents(),e?.onFailure?.();return}o("error","Failed to recover persisted events",{error:t})}}stop(){}async send(e){if(this.shouldSkipSend())return this.simulateSuccessfulSend();if(this.get("config")?.integrations?.custom?.collectApiUrl===k.Fail)return o("warn","Fail mode: simulating network failure",{data:{events:e.events.length}}),!1;const{url:s,payload:n}=this.prepareRequest(e);try{return(await this.sendWithTimeout(s,n)).ok}catch(i){if(i instanceof A)throw i;return o("error","Send request failed",{error:i,data:{events:e.events.length,url:s.replace(/\/\/[^/]+/,"//[DOMAIN]")}}),!1}}async sendWithTimeout(e,t){const s=new AbortController,n=setTimeout(()=>{s.abort()},1e4);try{const i=await fetch(e,{method:"POST",body:t,keepalive:!0,credentials:"include",signal:s.signal,headers:{"Content-Type":"application/json"}});if(!i.ok)throw i.status>=400&&i.status<500?new A(`HTTP ${i.status}: ${i.statusText}`,i.status):new Error(`HTTP ${i.status}: ${i.statusText}`);return i}finally{clearTimeout(n)}}sendQueueSyncInternal(e){const{url:t,payload:s}=this.prepareRequest(e),n=new Blob([s],{type:"application/json"});if(!this.isSendBeaconAvailable())return o("warn","sendBeacon not available, persisting events for recovery"),this.persistEvents(e),!1;const i=navigator.sendBeacon(t,n);return i||(o("warn","sendBeacon rejected request, persisting events for recovery"),this.persistEvents(e)),i}prepareRequest(e){const t={...e,_metadata:{referer:typeof window<"u"?window.location.href:void 0,timestamp:Date.now()}};return{url:this.get("collectApiUrl"),payload:JSON.stringify(t)}}getPersistedData(){try{const e=this.getQueueStorageKey(),t=this.storeManager.getItem(e);if(t)return JSON.parse(t)}catch(e){o("warn","Failed to parse persisted data",{error:e}),this.clearPersistedEvents()}return null}isDataRecent(e){return!e.timestamp||typeof e.timestamp!="number"?!1:(Date.now()-e.timestamp)/(1e3*60*60)<2}createRecoveryBody(e){return{user_id:e.userId,session_id:e.sessionId,device:e.device,events:e.events,...e.global_metadata&&{global_metadata:e.global_metadata}}}persistEvents(e){try{const t={userId:e.user_id,sessionId:e.session_id,device:e.device,events:e.events,timestamp:Date.now(),...e.global_metadata&&{global_metadata:e.global_metadata}},s=this.getQueueStorageKey();return this.storeManager.setItem(s,JSON.stringify(t)),!!this.storeManager.getItem(s)}catch(t){return o("warn","Failed to persist events",{error:t}),!1}}clearPersistedEvents(){try{const e=this.getQueueStorageKey();this.storeManager.removeItem(e)}catch(e){o("warn","Failed to clear persisted events",{error:e})}}shouldSkipSend(){return!this.get("collectApiUrl")}async simulateSuccessfulSend(){const e=Math.random()*400+100;return await new Promise(t=>setTimeout(t,e)),!0}isSendBeaconAvailable(){return typeof navigator<"u"&&typeof navigator.sendBeacon=="function"}logPermanentError(e,t){const s=Date.now();(!this.lastPermanentErrorLog||this.lastPermanentErrorLog.statusCode!==t.statusCode||s-this.lastPermanentErrorLog.timestamp>=Ye)&&(o("error",e,{data:{status:t.statusCode,message:t.message}}),this.lastPermanentErrorLog={statusCode:t.statusCode,timestamp:s})}}class ut extends g{googleAnalytics;dataSender;emitter;eventsQueue=[];pendingEventsBuffer=[];lastEventFingerprint=null;lastEventTime=0;sendIntervalId=null;rateLimitCounter=0;rateLimitWindowStart=0;constructor(e,t=null,s=null){super(),this.googleAnalytics=t,this.dataSender=new ct(e),this.emitter=s}async recoverPersistedEvents(){await this.dataSender.recoverPersistedEvents({onSuccess:(e,t,s)=>{if(t&&t.length>0){const n=t.map(i=>i.id);this.removeProcessedEvents(n),s&&this.emitEventsQueue(s)}},onFailure:()=>{o("warn","Failed to recover persisted events")}})}track({type:e,page_url:t,from_page_url:s,scroll_data:n,click_data:i,custom_event:a,web_vitals:l,error_data:c,session_end_reason:d}){if(!e){o("error","Event type is required - event will be ignored");return}if(!this.get("sessionId")){this.pendingEventsBuffer.length>=100&&(this.pendingEventsBuffer.shift(),o("warn","Pending events buffer full - dropping oldest event",{data:{maxBufferSize:100}})),this.pendingEventsBuffer.push({type:e,page_url:t,from_page_url:s,scroll_data:n,click_data:i,custom_event:a,web_vitals:l,error_data:c,session_end_reason:d});return}const v=e===h.SESSION_START||e===h.SESSION_END;if(!v&&!this.checkRateLimit())return;const P=e,Jt=P===h.SESSION_START,er=t||this.get("pageUrl"),le=this.buildEventPayload({type:P,page_url:er,from_page_url:s,scroll_data:n,click_data:i,custom_event:a,web_vitals:l,error_data:c,session_end_reason:d});if(!(!v&&!this.shouldSample())){if(Jt){const Oe=this.get("sessionId");if(!Oe){o("error","Session start event requires sessionId - event will be ignored");return}if(this.get("hasStartSession")){o("warn","Duplicate session_start detected",{data:{sessionId:Oe}});return}this.set("hasStartSession",!0)}if(!this.isDuplicateEvent(le)){if(this.get("mode")===w.QA&&P===h.CUSTOM&&a){console.log("[TraceLog] Event",{name:a.name,...a.metadata&&{metadata:a.metadata}}),this.emitEvent(le);return}this.addToQueue(le)}}}stop(){this.sendIntervalId&&(clearInterval(this.sendIntervalId),this.sendIntervalId=null),this.eventsQueue=[],this.pendingEventsBuffer=[],this.lastEventFingerprint=null,this.lastEventTime=0,this.rateLimitCounter=0,this.rateLimitWindowStart=0,this.dataSender.stop()}async flushImmediately(){return this.flushEvents(!1)}flushImmediatelySync(){return this.flushEvents(!0)}getQueueLength(){return this.eventsQueue.length}flushPendingEvents(){if(this.pendingEventsBuffer.length===0)return;if(!this.get("sessionId")){o("warn","Cannot flush pending events: session not initialized - keeping in buffer",{data:{bufferedEventCount:this.pendingEventsBuffer.length}});return}const t=[...this.pendingEventsBuffer];this.pendingEventsBuffer=[],t.forEach(s=>{this.track(s)})}clearSendInterval(){this.sendIntervalId&&(clearInterval(this.sendIntervalId),this.sendIntervalId=null)}flushEvents(e){if(this.eventsQueue.length===0)return e?!0:Promise.resolve(!0);const t=this.buildEventsPayload(),s=[...this.eventsQueue],n=s.map(i=>i.id);if(e){const i=this.dataSender.sendEventsQueueSync(t);return i&&(this.removeProcessedEvents(n),this.clearSendInterval(),this.emitEventsQueue(t)),i}else return this.dataSender.sendEventsQueue(t,{onSuccess:()=>{this.removeProcessedEvents(n),this.clearSendInterval(),this.emitEventsQueue(t)},onFailure:()=>{o("warn","Async flush failed",{data:{eventCount:s.length}})}})}async sendEventsQueue(){if(!this.get("sessionId")||this.eventsQueue.length===0)return;const e=this.buildEventsPayload(),t=[...this.eventsQueue],s=t.map(n=>n.id);await this.dataSender.sendEventsQueue(e,{onSuccess:()=>{this.removeProcessedEvents(s),this.emitEventsQueue(e)},onFailure:()=>{o("warn","Events send failed, keeping in queue",{data:{eventCount:t.length}})}})}buildEventsPayload(){const e=new Map,t=[];for(const n of this.eventsQueue){const i=this.createEventSignature(n);e.has(i)||t.push(i),e.set(i,n)}const s=t.map(n=>e.get(n)).filter(n=>!!n).sort((n,i)=>n.timestamp-i.timestamp);return{user_id:this.get("userId"),session_id:this.get("sessionId"),device:this.get("device"),events:s,...this.get("config")?.globalMetadata&&{global_metadata:this.get("config")?.globalMetadata}}}buildEventPayload(e){const t=e.type===h.SESSION_START,s=e.page_url??this.get("pageUrl");return{id:We(),type:e.type,page_url:s,timestamp:Date.now(),...t&&{referrer:document.referrer||"Direct"},...e.from_page_url&&{from_page_url:e.from_page_url},...e.scroll_data&&{scroll_data:e.scroll_data},...e.click_data&&{click_data:e.click_data},...e.custom_event&&{custom_event:e.custom_event},...e.web_vitals&&{web_vitals:e.web_vitals},...e.error_data&&{error_data:e.error_data},...e.session_end_reason&&{session_end_reason:e.session_end_reason},...t&&_e()&&{utm:_e()}}}isDuplicateEvent(e){const t=Date.now(),s=this.createEventFingerprint(e);return this.lastEventFingerprint===s&&t-this.lastEventTime<500?!0:(this.lastEventFingerprint=s,this.lastEventTime=t,!1)}createEventFingerprint(e){let t=`${e.type}_${e.page_url}`;if(e.click_data){const s=Math.round((e.click_data.x||0)/10)*10,n=Math.round((e.click_data.y||0)/10)*10;t+=`_click_${s}_${n}`}return e.scroll_data&&(t+=`_scroll_${e.scroll_data.depth}_${e.scroll_data.direction}`),e.custom_event&&(t+=`_custom_${e.custom_event.name}`),e.web_vitals&&(t+=`_vitals_${e.web_vitals.type}`),e.error_data&&(t+=`_error_${e.error_data.type}_${e.error_data.message}`),t}createEventSignature(e){return this.createEventFingerprint(e)}addToQueue(e){if(this.eventsQueue.push(e),this.emitEvent(e),this.eventsQueue.length>100){const t=this.eventsQueue.findIndex(n=>n.type!==h.SESSION_START&&n.type!==h.SESSION_END),s=t>=0?this.eventsQueue.splice(t,1)[0]:this.eventsQueue.shift();o("warn","Event queue overflow, oldest non-critical event removed",{data:{maxLength:100,currentLength:this.eventsQueue.length,removedEventType:s?.type,wasCritical:s?.type===h.SESSION_START||s?.type===h.SESSION_END}})}this.sendIntervalId||this.startSendInterval(),this.handleGoogleAnalyticsIntegration(e)}startSendInterval(){this.sendIntervalId=window.setInterval(()=>{this.eventsQueue.length>0&&this.sendEventsQueue()},1e4)}handleGoogleAnalyticsIntegration(e){if(this.googleAnalytics&&e.type===h.CUSTOM&&e.custom_event){if(this.get("mode")===w.QA)return;this.googleAnalytics.trackEvent(e.custom_event.name,e.custom_event.metadata??{})}}shouldSample(){const e=this.get("config")?.samplingRate??1;return Math.random()<e}checkRateLimit(){const e=Date.now();return e-this.rateLimitWindowStart>1e3&&(this.rateLimitCounter=0,this.rateLimitWindowStart=e),this.rateLimitCounter>=200?!1:(this.rateLimitCounter++,!0)}removeProcessedEvents(e){const t=new Set(e);this.eventsQueue=this.eventsQueue.filter(s=>!t.has(s.id))}emitEvent(e){this.emitter&&this.emitter.emit(H.EVENT,e)}emitEventsQueue(e){this.emitter&&this.emitter.emit(H.QUEUE,e)}}class dt{static getId(e){const t=Fe,s=e.getItem(t);if(s)return s;const n=Ke();return e.setItem(t,n),n}}class ht extends g{storageManager;eventManager;projectId;sessionTimeoutId=null;broadcastChannel=null;activityHandler=null;visibilityChangeHandler=null;beforeUnloadHandler=null;isTracking=!1;constructor(e,t,s){super(),this.storageManager=e,this.eventManager=t,this.projectId=s}initCrossTabSync(){if(typeof BroadcastChannel>"u"){o("warn","BroadcastChannel not supported");return}const e=this.getProjectId();this.broadcastChannel=new BroadcastChannel(Be(e)),this.broadcastChannel.onmessage=t=>{const{action:s,sessionId:n,timestamp:i,projectId:a}=t.data??{};if(a===e){if(s==="session_end"){this.resetSessionState();return}n&&typeof i=="number"&&i>Date.now()-5e3&&(this.set("sessionId",n),this.set("hasStartSession",!0),this.persistSession(n,i),this.isTracking&&this.setupSessionTimeout())}}}shareSession(e){this.broadcastChannel&&typeof this.broadcastChannel.postMessage=="function"&&this.broadcastChannel.postMessage({action:"session_start",projectId:this.getProjectId(),sessionId:e,timestamp:Date.now()})}broadcastSessionEnd(e,t){if(e&&this.broadcastChannel&&typeof this.broadcastChannel.postMessage=="function")try{this.broadcastChannel.postMessage({action:"session_end",projectId:this.getProjectId(),sessionId:e,reason:t,timestamp:Date.now()})}catch(s){o("warn","Failed to broadcast session end",{error:s,data:{sessionId:e,reason:t}})}}cleanupCrossTabSync(){this.broadcastChannel&&(typeof this.broadcastChannel.close=="function"&&this.broadcastChannel.close(),this.broadcastChannel=null)}recoverSession(){const e=this.loadStoredSession();if(!e)return null;const t=this.get("config")?.sessionTimeout??9e5;return Date.now()-e.lastActivity>t?(this.clearStoredSession(),null):e.id}persistSession(e,t=Date.now()){this.saveStoredSession({id:e,lastActivity:t})}clearStoredSession(){const e=this.getSessionStorageKey();this.storageManager.removeItem(e)}loadStoredSession(){const e=this.getSessionStorageKey(),t=this.storageManager.getItem(e);if(!t)return null;try{const s=JSON.parse(t);return!s.id||typeof s.lastActivity!="number"?null:s}catch{return this.storageManager.removeItem(e),null}}saveStoredSession(e){const t=this.getSessionStorageKey();this.storageManager.setItem(t,JSON.stringify(e))}getSessionStorageKey(){return Xe(this.getProjectId())}getProjectId(){return this.projectId}startTracking(){if(this.isTracking){o("warn","Session tracking already active");return}const e=this.recoverSession(),t=e??this.generateSessionId(),s=!!e;this.isTracking=!0;try{this.set("sessionId",t),this.persistSession(t),s||this.eventManager.track({type:h.SESSION_START}),this.initCrossTabSync(),this.shareSession(t),this.setupSessionTimeout(),this.setupActivityListeners(),this.setupLifecycleListeners()}catch(n){throw this.isTracking=!1,this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupLifecycleListeners(),this.cleanupCrossTabSync(),this.set("sessionId",null),n}}generateSessionId(){return`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}setupSessionTimeout(){this.clearSessionTimeout();const e=this.get("config")?.sessionTimeout??9e5;this.sessionTimeoutId=setTimeout(()=>{this.endSession("inactivity")},e)}resetSessionTimeout(){this.setupSessionTimeout();const e=this.get("sessionId");e&&this.persistSession(e)}clearSessionTimeout(){this.sessionTimeoutId&&(clearTimeout(this.sessionTimeoutId),this.sessionTimeoutId=null)}setupActivityListeners(){this.activityHandler=()=>{this.resetSessionTimeout()},document.addEventListener("click",this.activityHandler,{passive:!0}),document.addEventListener("keydown",this.activityHandler,{passive:!0}),document.addEventListener("scroll",this.activityHandler,{passive:!0})}cleanupActivityListeners(){this.activityHandler&&(document.removeEventListener("click",this.activityHandler),document.removeEventListener("keydown",this.activityHandler),document.removeEventListener("scroll",this.activityHandler),this.activityHandler=null)}setupLifecycleListeners(){this.visibilityChangeHandler||this.beforeUnloadHandler||(this.visibilityChangeHandler=()=>{document.hidden?this.clearSessionTimeout():this.get("sessionId")&&this.setupSessionTimeout()},this.beforeUnloadHandler=()=>{this.endSession("page_unload")},document.addEventListener("visibilitychange",this.visibilityChangeHandler),window.addEventListener("beforeunload",this.beforeUnloadHandler))}cleanupLifecycleListeners(){this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null)}endSession(e){const t=this.get("sessionId");if(!t){o("warn","endSession called without active session",{data:{reason:e}}),this.resetSessionState(e);return}this.eventManager.track({type:h.SESSION_END,session_end_reason:e}),this.eventManager.flushImmediatelySync()||o("warn","Sync flush failed during session end, events persisted for recovery",{data:{reason:e,sessionId:t}}),this.broadcastSessionEnd(t,e),this.resetSessionState(e)}resetSessionState(e){this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupLifecycleListeners(),this.cleanupCrossTabSync(),e!=="page_unload"&&this.clearStoredSession(),this.set("sessionId",null),this.set("hasStartSession",!1),this.isTracking=!1}stopTracking(){this.endSession("manual_stop")}destroy(){this.clearSessionTimeout(),this.cleanupActivityListeners(),this.cleanupCrossTabSync(),this.cleanupLifecycleListeners(),this.isTracking=!1,this.set("hasStartSession",!1)}}class ft extends g{eventManager;storageManager;sessionManager=null;destroyed=!1;constructor(e,t){super(),this.eventManager=t,this.storageManager=e}startTracking(){if(this.isActive())return;if(this.destroyed){o("warn","Cannot start tracking on destroyed handler");return}const e=this.get("config"),t=e?.integrations?.tracelog?.projectId??e?.integrations?.custom?.collectApiUrl??"default";if(!t)throw new Error("Cannot start session tracking: config not available");try{this.sessionManager=new ht(this.storageManager,this.eventManager,t),this.sessionManager.startTracking(),this.eventManager.flushPendingEvents()}catch(s){if(this.sessionManager){try{this.sessionManager.destroy()}catch{}this.sessionManager=null}throw o("error","Failed to start session tracking",{error:s}),s}}isActive(){return this.sessionManager!==null&&!this.destroyed}cleanupSessionManager(){this.sessionManager&&(this.sessionManager.stopTracking(),this.sessionManager.destroy(),this.sessionManager=null)}stopTracking(){this.cleanupSessionManager()}destroy(){this.destroyed||(this.sessionManager&&(this.sessionManager.destroy(),this.sessionManager=null),this.destroyed=!0,this.set("hasStartSession",!1))}}class gt extends g{eventManager;onTrack;originalPushState;originalReplaceState;constructor(e,t){super(),this.eventManager=e,this.onTrack=t}startTracking(){this.trackInitialPageView(),window.addEventListener("popstate",this.trackCurrentPage,!0),window.addEventListener("hashchange",this.trackCurrentPage,!0),this.patchHistory("pushState"),this.patchHistory("replaceState")}stopTracking(){window.removeEventListener("popstate",this.trackCurrentPage,!0),window.removeEventListener("hashchange",this.trackCurrentPage,!0),this.originalPushState&&(window.history.pushState=this.originalPushState),this.originalReplaceState&&(window.history.replaceState=this.originalReplaceState)}patchHistory(e){const t=window.history[e];e==="pushState"&&!this.originalPushState?this.originalPushState=t:e==="replaceState"&&!this.originalReplaceState&&(this.originalReplaceState=t),window.history[e]=(...s)=>{t.apply(window.history,s),this.trackCurrentPage()}}trackCurrentPage=()=>{const e=window.location.href,t=j(e,this.get("config").sensitiveQueryParams);if(this.get("pageUrl")===t)return;this.onTrack();const s=this.get("pageUrl");this.set("pageUrl",t);const n=this.extractPageViewData();this.eventManager.track({type:h.PAGE_VIEW,page_url:this.get("pageUrl"),from_page_url:s,...n&&{page_view:n}})};trackInitialPageView(){const e=j(window.location.href,this.get("config").sensitiveQueryParams),t=this.extractPageViewData();this.eventManager.track({type:h.PAGE_VIEW,page_url:e,...t&&{page_view:t}}),this.onTrack()}extractPageViewData(){const{pathname:e,search:t,hash:s}=window.location,{referrer:n}=document,{title:i}=document;return!n&&!i&&!e&&!t&&!s?void 0:{...n&&{referrer:n},...i&&{title:i},...e&&{pathname:e},...t&&{search:t},...s&&{hash:s}}}}class Et extends g{eventManager;clickHandler;constructor(e){super(),this.eventManager=e}startTracking(){this.clickHandler||(this.clickHandler=e=>{const t=e,s=t.target,n=typeof HTMLElement<"u"&&s instanceof HTMLElement?s:typeof HTMLElement<"u"&&s instanceof Node&&s.parentElement instanceof HTMLElement?s.parentElement:null;if(!n){o("warn","Click target not found or not an element");return}const i=this.findTrackingElement(n),a=this.getRelevantClickElement(n),l=this.calculateClickCoordinates(t,n);if(i){const d=this.extractTrackingData(i);if(d){const v=this.createCustomEventData(d);this.eventManager.track({type:h.CUSTOM,custom_event:{name:v.name,...v.value&&{metadata:{value:v.value}}}})}}const c=this.generateClickData(n,a,l);this.eventManager.track({type:h.CLICK,click_data:c})},window.addEventListener("click",this.clickHandler,!0))}stopTracking(){this.clickHandler&&(window.removeEventListener("click",this.clickHandler,!0),this.clickHandler=void 0)}findTrackingElement(e){return e.hasAttribute(`${U}-name`)?e:e.closest(`[${U}-name]`)||void 0}getRelevantClickElement(e){for(const t of be)try{if(e.matches(t))return e;const s=e.closest(t);if(s)return s}catch(s){o("warn","Invalid selector in element search",{error:s,data:{selector:t}});continue}return e}clamp(e){return Math.max(0,Math.min(1,Number(e.toFixed(3))))}calculateClickCoordinates(e,t){const s=t.getBoundingClientRect(),n=e.clientX,i=e.clientY,a=s.width>0?this.clamp((n-s.left)/s.width):0,l=s.height>0?this.clamp((i-s.top)/s.height):0;return{x:n,y:i,relativeX:a,relativeY:l}}extractTrackingData(e){const t=e.getAttribute(`${U}-name`),s=e.getAttribute(`${U}-value`);if(t)return{element:e,name:t,...s&&{value:s}}}generateClickData(e,t,s){const{x:n,y:i,relativeX:a,relativeY:l}=s,c=this.getRelevantText(e,t),d=this.extractElementAttributes(t);return{x:n,y:i,relativeX:a,relativeY:l,tag:t.tagName.toLowerCase(),...t.id&&{id:t.id},...t.className&&{class:t.className},...c&&{text:c},...d.href&&{href:d.href},...d.title&&{title:d.title},...d.alt&&{alt:d.alt},...d.role&&{role:d.role},...d["aria-label"]&&{ariaLabel:d["aria-label"]},...Object.keys(d).length>0&&{dataAttributes:d}}}getRelevantText(e,t){const s=e.textContent?.trim()??"",n=t.textContent?.trim()??"";return!s&&!n?"":s&&s.length<=255?s:n.length<=255?n:n.slice(0,252)+"..."}extractElementAttributes(e){const t=["id","class","data-testid","aria-label","title","href","type","name","alt","role"],s={};for(const n of t){const i=e.getAttribute(n);i&&(s[n]=i)}return s}createCustomEventData(e){return{name:e.name,...e.value&&{value:e.value}}}}class St extends g{eventManager;containers=[];limitWarningLogged=!1;minDepthChange=5;minIntervalMs=500;maxEventsPerSession=120;constructor(e){super(),this.eventManager=e}startTracking(){this.limitWarningLogged=!1,this.applyConfigOverrides(),this.set("scrollEventCount",0);const e=this.get("config").scrollContainerSelectors,t=Array.isArray(e)?e:typeof e=="string"?[e]:[];t.length===0?this.setupScrollContainer(window):this.trySetupContainers(t,0)}stopTracking(){for(const e of this.containers)this.clearContainerTimer(e),e.element instanceof Window?window.removeEventListener("scroll",e.listener):e.element.removeEventListener("scroll",e.listener);this.containers.length=0,this.set("scrollEventCount",0),this.limitWarningLogged=!1}trySetupContainers(e,t){const s=e.map(n=>this.safeQuerySelector(n)).filter(n=>n!=null&&typeof HTMLElement<"u"&&n instanceof HTMLElement);if(s.length>0){for(const n of s)this.containers.some(a=>a.element===n)||this.setupScrollContainer(n);return}if(t<5){setTimeout(()=>{this.trySetupContainers(e,t+1)},200);return}this.containers.length===0&&this.setupScrollContainer(window)}setupScrollContainer(e){if(e!==window&&!this.isElementScrollable(e))return;const t=()=>{this.get("suppressNextScroll")||(this.clearContainerTimer(n),n.debounceTimer=window.setTimeout(()=>{const i=this.calculateScrollData(n);if(i){const a=Date.now();this.processScrollEvent(n,i,a)}n.debounceTimer=null},250))},s=this.getScrollTop(e),n={element:e,lastScrollPos:s,lastDepth:this.calculateScrollDepth(s,this.getScrollHeight(e),this.getViewportHeight(e)),lastDirection:b.DOWN,lastEventTime:0,debounceTimer:null,listener:t};this.containers.push(n),e instanceof Window?window.addEventListener("scroll",t,{passive:!0}):e.addEventListener("scroll",t,{passive:!0})}processScrollEvent(e,t,s){if(!this.shouldEmitScrollEvent(e,t,s))return;e.lastEventTime=s,e.lastDepth=t.depth,e.lastDirection=t.direction;const n=this.get("scrollEventCount")??0;this.set("scrollEventCount",n+1),this.eventManager.track({type:h.SCROLL,scroll_data:t})}shouldEmitScrollEvent(e,t,s){return this.hasReachedSessionLimit()?(this.logLimitOnce(),!1):!(!this.hasElapsedMinimumInterval(e,s)||!this.hasSignificantDepthChange(e,t.depth))}hasReachedSessionLimit(){return(this.get("scrollEventCount")??0)>=this.maxEventsPerSession}hasElapsedMinimumInterval(e,t){return e.lastEventTime===0?!0:t-e.lastEventTime>=this.minIntervalMs}hasSignificantDepthChange(e,t){return Math.abs(t-e.lastDepth)>=this.minDepthChange}logLimitOnce(){this.limitWarningLogged||(this.limitWarningLogged=!0,o("warn","Max scroll events per session reached",{data:{limit:this.maxEventsPerSession}}))}applyConfigOverrides(){this.minDepthChange=5,this.minIntervalMs=500,this.maxEventsPerSession=120}isWindowScrollable(){return document.documentElement.scrollHeight>window.innerHeight}clearContainerTimer(e){e.debounceTimer!==null&&(clearTimeout(e.debounceTimer),e.debounceTimer=null)}getScrollDirection(e,t){return e>t?b.DOWN:b.UP}calculateScrollDepth(e,t,s){if(t<=s)return 0;const n=t-s;return Math.min(100,Math.max(0,Math.floor(e/n*100)))}calculateScrollData(e){const{element:t,lastScrollPos:s}=e,n=this.getScrollTop(t);if(Math.abs(n-s)<10||t===window&&!this.isWindowScrollable())return null;const a=this.getViewportHeight(t),l=this.getScrollHeight(t),c=this.getScrollDirection(n,s),d=this.calculateScrollDepth(n,l,a);return e.lastScrollPos=n,{depth:d,direction:c}}getScrollTop(e){return e instanceof Window?window.scrollY:e.scrollTop}getViewportHeight(e){return e instanceof Window?window.innerHeight:e.clientHeight}getScrollHeight(e){return e instanceof Window?document.documentElement.scrollHeight:e.scrollHeight}isElementScrollable(e){const t=getComputedStyle(e),s=t.overflowY==="auto"||t.overflowY==="scroll"||t.overflowX==="auto"||t.overflowX==="scroll"||t.overflow==="auto"||t.overflow==="scroll",n=e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;return s&&n}safeQuerySelector(e){try{return document.querySelector(e)}catch(t){return o("warn","Invalid CSS selector",{error:t,data:{selector:e},showToClient:!0}),null}}}class _t extends g{isInitialized=!1;async initialize(){if(this.isInitialized)return;const e=this.get("config").integrations?.googleAnalytics?.measurementId,t=this.get("userId");if(!(!e?.trim()||!t?.trim()))try{if(this.isScriptAlreadyLoaded()){this.isInitialized=!0;return}await this.loadScript(e),this.configureGtag(e,t),this.isInitialized=!0}catch(s){o("error","Google Analytics initialization failed",{error:s})}}trackEvent(e,t){if(!(!e?.trim()||!this.isInitialized||typeof window.gtag!="function"))try{const s=Array.isArray(t)?{items:t}:t;window.gtag("event",e,s)}catch(s){o("error","Google Analytics event tracking failed",{error:s})}}cleanup(){this.isInitialized=!1;const e=document.getElementById("tracelog-ga-script");e&&e.remove()}isScriptAlreadyLoaded(){return document.getElementById("tracelog-ga-script")?!0:!!document.querySelector('script[src*="googletagmanager.com/gtag/js"]')}async loadScript(e){return new Promise((t,s)=>{const n=document.createElement("script");n.id="tracelog-ga-script",n.async=!0,n.src=`https://www.googletagmanager.com/gtag/js?id=${e}`,n.onload=()=>{t()},n.onerror=()=>{s(new Error("Failed to load Google Analytics script"))},document.head.appendChild(n)})}configureGtag(e,t){const s=document.createElement("script");s.innerHTML=`
|
|
2
2
|
window.dataLayer = window.dataLayer || [];
|
|
3
3
|
function gtag(){dataLayer.push(arguments);}
|
|
4
4
|
gtag('js', new Date());
|
|
5
5
|
gtag('config', '${e}', {
|
|
6
6
|
'user_id': '${t}'
|
|
7
7
|
});
|
|
8
|
-
`,document.head.appendChild(r)}}class pt{storage;sessionStorageRef;fallbackStorage=new Map;fallbackSessionStorage=new Map;hasQuotaExceededError=!1;constructor(){this.storage=this.initializeStorage("localStorage"),this.sessionStorageRef=this.initializeStorage("sessionStorage"),this.storage||o("warn","localStorage not available, using memory fallback"),this.sessionStorageRef||o("warn","sessionStorage not available, using memory fallback")}getItem(e){try{return this.storage?this.storage.getItem(e):this.fallbackStorage.get(e)??null}catch{return this.fallbackStorage.get(e)??null}}setItem(e,t){this.fallbackStorage.set(e,t);try{if(this.storage){this.storage.setItem(e,t);return}}catch(r){if(r instanceof DOMException&&r.name==="QuotaExceededError")if(this.hasQuotaExceededError=!0,o("warn","localStorage quota exceeded, attempting cleanup",{data:{key:e,valueSize:t.length}}),this.cleanupOldData())try{if(this.storage){this.storage.setItem(e,t);return}}catch(i){o("error","localStorage quota exceeded even after cleanup - data will not persist",{error:i,data:{key:e,valueSize:t.length}})}else o("error","localStorage quota exceeded and no data to cleanup - data will not persist",{error:r,data:{key:e,valueSize:t.length}})}}removeItem(e){try{this.storage&&this.storage.removeItem(e)}catch{}this.fallbackStorage.delete(e)}clear(){if(!this.storage){this.fallbackStorage.clear();return}try{const e=[];for(let t=0;t<this.storage.length;t++){const r=this.storage.key(t);r?.startsWith("tracelog_")&&e.push(r)}e.forEach(t=>this.storage.removeItem(t)),this.fallbackStorage.clear()}catch(e){o("error","Failed to clear storage",{error:e}),this.fallbackStorage.clear()}}isAvailable(){return this.storage!==null}hasQuotaError(){return this.hasQuotaExceededError}cleanupOldData(){if(!this.storage)return!1;try{const e=[],t=[];for(let i=0;i<this.storage.length;i++){const a=this.storage.key(i);a?.startsWith("tracelog_")&&(e.push(a),a.startsWith("tracelog_persisted_events_")&&t.push(a))}if(t.length>0)return t.forEach(i=>{try{this.storage.removeItem(i)}catch{}}),!0;const r=["tracelog_session_","tracelog_user_id","tracelog_device_id","tracelog_config"],n=e.filter(i=>!r.some(a=>i.startsWith(a)));return n.length>0?(n.slice(0,5).forEach(a=>{try{this.storage.removeItem(a)}catch{}}),!0):!1}catch(e){return o("error","Failed to cleanup old data",{error:e}),!1}}initializeStorage(e){if(typeof window>"u")return null;try{const t=e==="localStorage"?window.localStorage:window.sessionStorage,r="__tracelog_test__";return t.setItem(r,"test"),t.removeItem(r),t}catch{return null}}getSessionItem(e){try{return this.sessionStorageRef?this.sessionStorageRef.getItem(e):this.fallbackSessionStorage.get(e)??null}catch{return this.fallbackSessionStorage.get(e)??null}}setSessionItem(e,t){this.fallbackSessionStorage.set(e,t);try{if(this.sessionStorageRef){this.sessionStorageRef.setItem(e,t);return}}catch(r){r instanceof DOMException&&r.name==="QuotaExceededError"&&o("error","sessionStorage quota exceeded - data will not persist",{error:r,data:{key:e,valueSize:t.length}})}}removeSessionItem(e){try{this.sessionStorageRef&&this.sessionStorageRef.removeItem(e)}catch{}this.fallbackSessionStorage.delete(e)}}class Tt extends g{eventManager;reportedByNav=new Map;observers=[];lastLongTaskSentAt=0;vitalThresholds=he;constructor(e){super(),this.eventManager=e}async startTracking(){await this.initWebVitals(),this.observeLongTasks()}stopTracking(){this.observers.forEach((e,t)=>{try{e.disconnect()}catch(r){o("warn","Failed to disconnect performance observer",{error:r,data:{observerIndex:t}})}}),this.observers.length=0,this.reportedByNav.clear()}observeWebVitalsFallback(){this.reportTTFB(),this.safeObserve("largest-contentful-paint",r=>{const n=r.getEntries(),i=n[n.length-1];i&&this.sendVital({type:"LCP",value:Number(i.startTime.toFixed(2))})},{type:"largest-contentful-paint",buffered:!0},!0);let e=0,t=this.getNavigationId();this.safeObserve("layout-shift",r=>{const n=this.getNavigationId();n!==t&&(e=0,t=n);const i=r.getEntries();for(const a of i){if(a.hadRecentInput===!0)continue;const c=typeof a.value=="number"?a.value:0;e+=c}this.sendVital({type:"CLS",value:Number(e.toFixed(2))})},{type:"layout-shift",buffered:!0}),this.safeObserve("paint",r=>{for(const n of r.getEntries())n.name==="first-contentful-paint"&&this.sendVital({type:"FCP",value:Number(n.startTime.toFixed(2))})},{type:"paint",buffered:!0},!0),this.safeObserve("event",r=>{let n=0;const i=r.getEntries();for(const a of i){const c=(a.processingEnd??0)-(a.startTime??0);n=Math.max(n,c)}n>0&&this.sendVital({type:"INP",value:Number(n.toFixed(2))})},{type:"event",buffered:!0})}async initWebVitals(){try{const{onLCP:e,onCLS:t,onFCP:r,onTTFB:n,onINP:i}=await Promise.resolve().then(()=>Zt),a=c=>l=>{const u=Number(l.value.toFixed(2));this.sendVital({type:c,value:u})};e(a("LCP")),t(a("CLS")),r(a("FCP")),n(a("TTFB")),i(a("INP"))}catch(e){o("warn","Failed to load web-vitals library, using fallback",{error:e}),this.observeWebVitalsFallback()}}reportTTFB(){try{const e=performance.getEntriesByType("navigation")[0];if(!e)return;const t=e.responseStart;typeof t=="number"&&Number.isFinite(t)&&this.sendVital({type:"TTFB",value:Number(t.toFixed(2))})}catch(e){o("warn","Failed to report TTFB",{error:e})}}observeLongTasks(){this.safeObserve("longtask",e=>{const t=e.getEntries();for(const r of t){const n=Number(r.duration.toFixed(2)),i=Date.now();i-this.lastLongTaskSentAt>=$e&&(this.shouldSendVital("LONG_TASK",n)&&this.trackWebVital("LONG_TASK",n),this.lastLongTaskSentAt=i)}},{type:"longtask",buffered:!0})}sendVital(e){if(!this.shouldSendVital(e.type,e.value))return;const t=this.getNavigationId();if(t){const r=this.reportedByNav.get(t);if(r?.has(e.type))return;r?r.add(e.type):this.reportedByNav.set(t,new Set([e.type]))}this.trackWebVital(e.type,e.value)}trackWebVital(e,t){if(!Number.isFinite(t)){o("warn","Invalid web vital value",{data:{type:e,value:t}});return}this.eventManager.track({type:h.WEB_VITALS,web_vitals:{type:e,value:t}})}getNavigationId(){try{const e=performance.getEntriesByType("navigation")[0];if(!e)return null;const t=e.startTime||performance.now(),r=Math.random().toString(36).substr(2,5);return`${t.toFixed(2)}_${window.location.pathname}_${r}`}catch(e){return o("warn","Failed to get navigation ID",{error:e}),null}}isObserverSupported(e){if(typeof PerformanceObserver>"u")return!1;const t=PerformanceObserver.supportedEntryTypes;return!t||t.includes(e)}safeObserve(e,t,r,n=!1){try{if(!this.isObserverSupported(e))return!1;const i=new PerformanceObserver((a,c)=>{try{t(a,c)}catch(l){o("warn","Observer callback failed",{error:l,data:{type:e}})}if(n)try{c.disconnect()}catch{}});return i.observe(r??{type:e,buffered:!0}),n||this.observers.push(i),!0}catch(i){return o("warn","Failed to create performance observer",{error:i,data:{type:e}}),!1}}shouldSendVital(e,t){if(typeof t!="number"||!Number.isFinite(t))return o("warn","Invalid web vital value",{data:{type:e,value:t}}),!1;const r=this.vitalThresholds[e];return!(typeof r=="number"&&t<=r)}}class _t extends g{eventManager;recentErrors=new Map;constructor(e){super(),this.eventManager=e}startTracking(){window.addEventListener("error",this.handleError),window.addEventListener("unhandledrejection",this.handleRejection)}stopTracking(){window.removeEventListener("error",this.handleError),window.removeEventListener("unhandledrejection",this.handleRejection),this.recentErrors.clear()}shouldSample(){const t=this.get("config")?.errorSampling??.1;return Math.random()<t}handleError=e=>{if(!this.shouldSample())return;const t=this.sanitize(e.message||"Unknown error");this.shouldSuppressError(M.JS_ERROR,t)||this.eventManager.track({type:h.ERROR,error_data:{type:M.JS_ERROR,message:t,...e.filename&&{filename:e.filename},...e.lineno&&{line:e.lineno},...e.colno&&{column:e.colno}}})};handleRejection=e=>{if(!this.shouldSample())return;const t=this.extractRejectionMessage(e.reason),r=this.sanitize(t);this.shouldSuppressError(M.PROMISE_REJECTION,r)||this.eventManager.track({type:h.ERROR,error_data:{type:M.PROMISE_REJECTION,message:r}})};extractRejectionMessage(e){if(!e)return"Unknown rejection";if(typeof e=="string")return e;if(e instanceof Error)return e.stack??e.message??e.toString();if(typeof e=="object"&&"message"in e)return String(e.message);try{return JSON.stringify(e)}catch{return String(e)}}sanitize(e){let t=e.length>ge?e.slice(0,ge)+"...":e;for(const r of fe){const n=new RegExp(r.source,r.flags);t=t.replace(n,"[REDACTED]")}return t}shouldSuppressError(e,t){const r=Date.now(),n=`${e}:${t}`,i=this.recentErrors.get(n);return i&&r-i<Ee?(this.recentErrors.set(n,r),!0):(this.recentErrors.set(n,r),this.recentErrors.size>Qe?(this.recentErrors.clear(),this.recentErrors.set(n,r),!1):(this.recentErrors.size>V&&this.pruneOldErrors(),!1))}pruneOldErrors(){const e=Date.now();for(const[n,i]of this.recentErrors.entries())e-i>Ee&&this.recentErrors.delete(n);if(this.recentErrors.size<=V)return;const t=Array.from(this.recentErrors.entries()).sort((n,i)=>n[1]-i[1]),r=this.recentErrors.size-V;for(let n=0;n<r;n+=1){const i=t[n];i&&this.recentErrors.delete(i[0])}}}class vt extends g{isInitialized=!1;suppressNextScrollTimer=null;emitter=new ct;managers={};handlers={};integrations={};get initialized(){return this.isInitialized}async init(e={}){if(!this.isInitialized){this.managers.storage=new pt;try{this.setupState(e),await this.setupIntegrations(),this.managers.event=new ut(this.managers.storage,this.integrations.googleAnalytics,this.emitter),await this.initializeHandlers(),await this.managers.event.recoverPersistedEvents().catch(t=>{o("warn","Failed to recover persisted events",{error:t})}),this.isInitialized=!0}catch(t){await this.destroy(!0);const r=t instanceof Error?t.message:String(t);throw new Error(`[TraceLog] TraceLog initialization failed: ${r}`)}}}sendCustomEvent(e,t){if(!this.managers.event)return;const{valid:r,error:n,sanitizedMetadata:i}=ot(e,t);if(!r){if(this.get("mode")===L.QA)throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${n}`);return}this.managers.event.track({type:h.CUSTOM,custom_event:{name:e,...i&&{metadata:i}}})}on(e,t){this.emitter.on(e,t)}off(e,t){this.emitter.off(e,t)}async destroy(e=!1){if(!this.isInitialized&&!e)return;this.integrations.googleAnalytics?.cleanup();const t=Object.values(this.handlers).filter(Boolean).map(async r=>{try{await r.stopTracking()}catch(n){o("warn","Failed to stop tracking",{error:n})}});await Promise.allSettled(t),this.suppressNextScrollTimer&&(clearTimeout(this.suppressNextScrollTimer),this.suppressNextScrollTimer=null),this.managers.event?.flushImmediatelySync(),this.managers.event?.stop(),this.emitter.removeAllListeners(),this.set("hasStartSession",!1),this.set("suppressNextScroll",!1),this.set("sessionId",null),this.isInitialized=!1,this.handlers={}}setupState(e={}){this.set("config",e);const t=dt.getId(this.managers.storage);this.set("userId",t);const r=Ke(e);this.set("collectApiUrl",r);const n=Ve();this.set("device",n);const i=W(window.location.href,e.sensitiveQueryParams);this.set("pageUrl",i);const a=Xe()?L.QA:void 0;a&&this.set("mode",a)}async setupIntegrations(){if(this.get("config").integrations?.googleAnalytics?.measurementId?.trim())try{this.integrations.googleAnalytics=new mt,await this.integrations.googleAnalytics.initialize()}catch{this.integrations.googleAnalytics=void 0}}async initializeHandlers(){this.handlers.session=new ft(this.managers.storage,this.managers.event),await this.handlers.session.startTracking();const e=()=>{this.set("suppressNextScroll",!0),this.suppressNextScrollTimer&&clearTimeout(this.suppressNextScrollTimer),this.suppressNextScrollTimer=window.setTimeout(()=>{this.set("suppressNextScroll",!1)},250*2)};this.handlers.pageView=new gt(this.managers.event,e),this.handlers.pageView.startTracking(),this.handlers.click=new Et(this.managers.event),this.handlers.click.startTracking(),this.handlers.scroll=new St(this.managers.event),this.handlers.scroll.startTracking(),this.handlers.performance=new Tt(this.managers.event),this.handlers.performance.startTracking().catch(t=>{o("warn","Failed to start performance tracking",{error:t})}),this.handlers.error=new _t(this.managers.event),this.handlers.error.startTracking()}}const w=[];let f=null,R=!1,F=!1;const It=async s=>{if(typeof window>"u"||typeof document>"u")throw new Error("[TraceLog] This library can only be used in a browser environment");if(!window.__traceLogDisabled&&!f&&!R){R=!0;try{const e=rt(s??{}),t=new vt;try{w.forEach(({event:i,callback:a})=>{t.on(i,a)}),w.length=0;const r=t.init(e),n=new Promise((i,a)=>{setTimeout(()=>{a(new Error("[TraceLog] Initialization timeout after 10000ms"))},1e4)});await Promise.race([r,n]),f=t}catch(r){try{await t.destroy(!0)}catch(n){o("error","Failed to cleanup partially initialized app",{error:n})}throw r}}catch(e){throw f=null,e}finally{R=!1}}},yt=(s,e)=>{if(!f)throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");if(F)throw new Error("[TraceLog] Cannot send events while TraceLog is being destroyed");f.sendCustomEvent(s,e)},At=(s,e)=>{if(!f||R){w.push({event:s,callback:e});return}f.on(s,e)},wt=(s,e)=>{if(!f){const t=w.findIndex(r=>r.event===s&&r.callback===e);t!==-1&&w.splice(t,1);return}f.off(s,e)},Mt=()=>f!==null,Lt=async()=>{if(!f)throw new Error("[TraceLog] App not initialized");if(F)throw new Error("[TraceLog] Destroy operation already in progress");F=!0;try{await f.destroy(),f=null,R=!1,w.length=0}catch(s){f=null,R=!1,w.length=0,o("warn","Error during destroy, forced cleanup completed",{error:s})}finally{F=!1}},Nt={WEB_VITALS_THRESHOLDS:he},Rt={PII_PATTERNS:fe},Ct={LOW_ACTIVITY_EVENT_COUNT:50,HIGH_ACTIVITY_EVENT_COUNT:1e3,MIN_EVENTS_FOR_DYNAMIC_CALCULATION:100,MIN_EVENTS_FOR_TREND_ANALYSIS:30,BOUNCE_RATE_SESSION_THRESHOLD:1,MIN_ENGAGED_SESSION_DURATION_MS:30*1e3,MIN_SCROLL_DEPTH_ENGAGEMENT:25},Ot={INACTIVITY_TIMEOUT_MS:30*60*1e3,SHORT_SESSION_THRESHOLD_MS:30*1e3,MEDIUM_SESSION_THRESHOLD_MS:5*60*1e3,LONG_SESSION_THRESHOLD_MS:30*60*1e3,MAX_REALISTIC_SESSION_DURATION_MS:8*60*60*1e3},bt={MOBILE_MAX_WIDTH:768,TABLET_MAX_WIDTH:1024,MOBILE_PERFORMANCE_FACTOR:1.5,TABLET_PERFORMANCE_FACTOR:1.2},Pt={MIN_TEXT_LENGTH_FOR_ANALYSIS:10,MIN_CLICKS_FOR_HOT_ELEMENT:10,MIN_SCROLL_COMPLETION_PERCENT:80,MIN_TIME_ON_PAGE_FOR_READ_MS:15*1e3},Dt={SIGNIFICANT_CHANGE_PERCENT:20,MAJOR_CHANGE_PERCENT:50,MIN_EVENTS_FOR_INSIGHT:100,MIN_SESSIONS_FOR_INSIGHT:10,MIN_CORRELATION_STRENGTH:.7,LOW_ERROR_RATE_PERCENT:1,HIGH_ERROR_RATE_PERCENT:5,CRITICAL_ERROR_RATE_PERCENT:10},kt={SHORT_TERM_TREND_HOURS:24,MEDIUM_TERM_TREND_DAYS:7,LONG_TERM_TREND_DAYS:30,MIN_DATA_POINTS_FOR_TREND:5,WEEKLY_PATTERN_MIN_WEEKS:4,DAILY_PATTERN_MIN_DAYS:14},Ut={MIN_SEGMENT_SIZE:10,MIN_COHORT_SIZE:5,COHORT_ANALYSIS_DAYS:[1,3,7,14,30],MIN_FUNNEL_EVENTS:20},Ht={DEFAULT_EVENTS_LIMIT:5,DEFAULT_SESSIONS_LIMIT:5,DEFAULT_PAGES_LIMIT:5,MAX_EVENTS_FOR_DEEP_ANALYSIS:1e4,MAX_TIME_RANGE_DAYS:365,ANALYTICS_BATCH_SIZE:1e3},Vt={ANOMALY_THRESHOLD_SIGMA:2.5,STRONG_ANOMALY_THRESHOLD_SIGMA:3,TRAFFIC_DROP_ALERT_PERCENT:-30,TRAFFIC_SPIKE_ALERT_PERCENT:200,MIN_BASELINE_DAYS:7,MIN_EVENTS_FOR_ANOMALY_DETECTION:50},Ft={PAGE_URL_EXCLUDED:"excluded",PAGE_URL_UNKNOWN:"unknown"},xt={init:It,event:yt,on:At,off:wt,isInitialized:Mt,destroy:Lt};var q,ve=-1,C=function(s){addEventListener("pageshow",function(e){e.persisted&&(ve=e.timeStamp,s(e))},!0)},Z=function(){var s=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(s&&s.responseStart>0&&s.responseStart<performance.now())return s},x=function(){var s=Z();return s&&s.activationStart||0},E=function(s,e){var t=Z(),r="navigate";return ve>=0?r="back-forward-cache":t&&(document.prerendering||x()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-"))),{name:s,value:e===void 0?-1:e,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},P=function(s,e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(s)){var r=new PerformanceObserver(function(n){Promise.resolve().then(function(){e(n.getEntries())})});return r.observe(Object.assign({type:s,buffered:!0},t||{})),r}}catch{}},S=function(s,e,t,r){var n,i;return function(a){e.value>=0&&(a||r)&&((i=e.value-(n||0))||n===void 0)&&(n=e.value,e.delta=i,e.rating=function(c,l){return c>l[1]?"poor":c>l[0]?"needs-improvement":"good"}(e.value,t),s(e))}},J=function(s){requestAnimationFrame(function(){return requestAnimationFrame(function(){return s()})})},G=function(s){document.addEventListener("visibilitychange",function(){document.visibilityState==="hidden"&&s()})},ee=function(s){var e=!1;return function(){e||(s(),e=!0)}},O=-1,Ie=function(){return document.visibilityState!=="hidden"||document.prerendering?1/0:0},z=function(s){document.visibilityState==="hidden"&&O>-1&&(O=s.type==="visibilitychange"?s.timeStamp:0,Gt())},ye=function(){addEventListener("visibilitychange",z,!0),addEventListener("prerenderingchange",z,!0)},Gt=function(){removeEventListener("visibilitychange",z,!0),removeEventListener("prerenderingchange",z,!0)},Ae=function(){return O<0&&(O=Ie(),ye(),C(function(){setTimeout(function(){O=Ie(),ye()},0)})),{get firstHiddenTime(){return O}}},$=function(s){document.prerendering?addEventListener("prerenderingchange",function(){return s()},!0):s()},te=[1800,3e3],we=function(s,e){e=e||{},$(function(){var t,r=Ae(),n=E("FCP"),i=P("paint",function(a){a.forEach(function(c){c.name==="first-contentful-paint"&&(i.disconnect(),c.startTime<r.firstHiddenTime&&(n.value=Math.max(c.startTime-x(),0),n.entries.push(c),t(!0)))})});i&&(t=S(s,n,te,e.reportAllChanges),C(function(a){n=E("FCP"),t=S(s,n,te,e.reportAllChanges),J(function(){n.value=performance.now()-a.timeStamp,t(!0)})}))})},re=[.1,.25],zt=function(s,e){e=e||{},we(ee(function(){var t,r=E("CLS",0),n=0,i=[],a=function(l){l.forEach(function(u){if(!u.hadRecentInput){var y=i[0],D=i[i.length-1];n&&u.startTime-D.startTime<1e3&&u.startTime-y.startTime<5e3?(n+=u.value,i.push(u)):(n=u.value,i=[u])}}),n>r.value&&(r.value=n,r.entries=i,t())},c=P("layout-shift",a);c&&(t=S(s,r,re,e.reportAllChanges),G(function(){a(c.takeRecords()),t(!0)}),C(function(){n=0,r=E("CLS",0),t=S(s,r,re,e.reportAllChanges),J(function(){return t()})}),setTimeout(t,0))}))},Me=0,se=1/0,Q=0,$t=function(s){s.forEach(function(e){e.interactionId&&(se=Math.min(se,e.interactionId),Q=Math.max(Q,e.interactionId),Me=Q?(Q-se)/7+1:0)})},Le=function(){return q?Me:performance.interactionCount||0},Qt=function(){"interactionCount"in performance||q||(q=P("event",$t,{type:"event",buffered:!0,durationThreshold:0}))},m=[],B=new Map,Ne=0,Bt=function(){var s=Math.min(m.length-1,Math.floor((Le()-Ne)/50));return m[s]},jt=[],Xt=function(s){if(jt.forEach(function(n){return n(s)}),s.interactionId||s.entryType==="first-input"){var e=m[m.length-1],t=B.get(s.interactionId);if(t||m.length<10||s.duration>e.latency){if(t)s.duration>t.latency?(t.entries=[s],t.latency=s.duration):s.duration===t.latency&&s.startTime===t.entries[0].startTime&&t.entries.push(s);else{var r={id:s.interactionId,latency:s.duration,entries:[s]};B.set(r.id,r),m.push(r)}m.sort(function(n,i){return i.latency-n.latency}),m.length>10&&m.splice(10).forEach(function(n){return B.delete(n.id)})}}},Re=function(s){var e=self.requestIdleCallback||self.setTimeout,t=-1;return s=ee(s),document.visibilityState==="hidden"?s():(t=e(s),G(s)),t},ne=[200,500],Wt=function(s,e){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(e=e||{},$(function(){var t;Qt();var r,n=E("INP"),i=function(c){Re(function(){c.forEach(Xt);var l=Bt();l&&l.latency!==n.value&&(n.value=l.latency,n.entries=l.entries,r())})},a=P("event",i,{durationThreshold:(t=e.durationThreshold)!==null&&t!==void 0?t:40});r=S(s,n,ne,e.reportAllChanges),a&&(a.observe({type:"first-input",buffered:!0}),G(function(){i(a.takeRecords()),r(!0)}),C(function(){Ne=Le(),m.length=0,B.clear(),n=E("INP"),r=S(s,n,ne,e.reportAllChanges)}))}))},ie=[2500,4e3],ae={},Yt=function(s,e){e=e||{},$(function(){var t,r=Ae(),n=E("LCP"),i=function(l){e.reportAllChanges||(l=l.slice(-1)),l.forEach(function(u){u.startTime<r.firstHiddenTime&&(n.value=Math.max(u.startTime-x(),0),n.entries=[u],t())})},a=P("largest-contentful-paint",i);if(a){t=S(s,n,ie,e.reportAllChanges);var c=ee(function(){ae[n.id]||(i(a.takeRecords()),a.disconnect(),ae[n.id]=!0,t(!0))});["keydown","click"].forEach(function(l){addEventListener(l,function(){return Re(c)},{once:!0,capture:!0})}),G(c),C(function(l){n=E("LCP"),t=S(s,n,ie,e.reportAllChanges),J(function(){n.value=performance.now()-l.timeStamp,ae[n.id]=!0,t(!0)})})}})},oe=[800,1800],Kt=function s(e){document.prerendering?$(function(){return s(e)}):document.readyState!=="complete"?addEventListener("load",function(){return s(e)},!0):setTimeout(e,0)},qt=function(s,e){e=e||{};var t=E("TTFB"),r=S(s,t,oe,e.reportAllChanges);Kt(function(){var n=Z();n&&(t.value=Math.max(n.responseStart-x(),0),t.entries=[n],r(!0),C(function(){t=E("TTFB",0),(r=S(s,t,oe,e.reportAllChanges))(!0)}))})};const Zt=Object.freeze(Object.defineProperty({__proto__:null,CLSThresholds:re,FCPThresholds:te,INPThresholds:ne,LCPThresholds:ie,TTFBThresholds:oe,onCLS:zt,onFCP:we,onINP:Wt,onLCP:Yt,onTTFB:qt},Symbol.toStringTag,{value:"Module"}));d.ANALYTICS_QUERY_LIMITS=Ht,d.ANOMALY_DETECTION=Vt,d.AppConfigValidationError=A,d.CONTENT_ANALYTICS=Pt,d.DATA_PROTECTION=Rt,d.DEVICE_ANALYTICS=bt,d.DeviceType=T,d.ENGAGEMENT_THRESHOLDS=Ct,d.EmitterEvent=H,d.ErrorType=M,d.EventType=h,d.INSIGHT_THRESHOLDS=Dt,d.InitializationTimeoutError=De,d.IntegrationValidationError=v,d.Mode=L,d.PERFORMANCE_CONFIG=Nt,d.PermanentError=_,d.SEGMENTATION_ANALYTICS=Ut,d.SESSION_ANALYTICS=Ot,d.SPECIAL_PAGE_URLS=Ft,d.SamplingRateValidationError=j,d.ScrollDirection=b,d.SessionTimeoutValidationError=le,d.SpecialApiUrl=U,d.TEMPORAL_ANALYSIS=kt,d.TraceLogValidationError=N,d.tracelog=xt,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})})(this.TraceLog=this.TraceLog||{});typeof window<"u"&&window.TraceLog?.tracelog&&(window.tracelog=window.TraceLog.tracelog);
|
|
8
|
+
`,document.head.appendChild(s)}}class Tt{storage;sessionStorageRef;fallbackStorage=new Map;fallbackSessionStorage=new Map;hasQuotaExceededError=!1;constructor(){this.storage=this.initializeStorage("localStorage"),this.sessionStorageRef=this.initializeStorage("sessionStorage"),this.storage||o("warn","localStorage not available, using memory fallback"),this.sessionStorageRef||o("warn","sessionStorage not available, using memory fallback")}getItem(e){try{return this.storage?this.storage.getItem(e):this.fallbackStorage.get(e)??null}catch{return this.fallbackStorage.get(e)??null}}setItem(e,t){this.fallbackStorage.set(e,t);try{if(this.storage){this.storage.setItem(e,t);return}}catch(s){if(s instanceof DOMException&&s.name==="QuotaExceededError")if(this.hasQuotaExceededError=!0,o("warn","localStorage quota exceeded, attempting cleanup",{data:{key:e,valueSize:t.length}}),this.cleanupOldData())try{if(this.storage){this.storage.setItem(e,t);return}}catch(i){o("error","localStorage quota exceeded even after cleanup - data will not persist",{error:i,data:{key:e,valueSize:t.length}})}else o("error","localStorage quota exceeded and no data to cleanup - data will not persist",{error:s,data:{key:e,valueSize:t.length}})}}removeItem(e){try{this.storage&&this.storage.removeItem(e)}catch{}this.fallbackStorage.delete(e)}clear(){if(!this.storage){this.fallbackStorage.clear();return}try{const e=[];for(let t=0;t<this.storage.length;t++){const s=this.storage.key(t);s?.startsWith("tracelog_")&&e.push(s)}e.forEach(t=>{this.storage.removeItem(t)}),this.fallbackStorage.clear()}catch(e){o("error","Failed to clear storage",{error:e}),this.fallbackStorage.clear()}}isAvailable(){return this.storage!==null}hasQuotaError(){return this.hasQuotaExceededError}cleanupOldData(){if(!this.storage)return!1;try{const e=[],t=[];for(let i=0;i<this.storage.length;i++){const a=this.storage.key(i);a?.startsWith("tracelog_")&&(e.push(a),a.startsWith("tracelog_persisted_events_")&&t.push(a))}if(t.length>0)return t.forEach(i=>{try{this.storage.removeItem(i)}catch{}}),!0;const s=["tracelog_session_","tracelog_user_id","tracelog_device_id","tracelog_config"],n=e.filter(i=>!s.some(a=>i.startsWith(a)));return n.length>0?(n.slice(0,5).forEach(a=>{try{this.storage.removeItem(a)}catch{}}),!0):!1}catch(e){return o("error","Failed to cleanup old data",{error:e}),!1}}initializeStorage(e){if(typeof window>"u")return null;try{const t=e==="localStorage"?window.localStorage:window.sessionStorage,s="__tracelog_test__";return t.setItem(s,"test"),t.removeItem(s),t}catch{return null}}getSessionItem(e){try{return this.sessionStorageRef?this.sessionStorageRef.getItem(e):this.fallbackSessionStorage.get(e)??null}catch{return this.fallbackSessionStorage.get(e)??null}}setSessionItem(e,t){this.fallbackSessionStorage.set(e,t);try{if(this.sessionStorageRef){this.sessionStorageRef.setItem(e,t);return}}catch(s){s instanceof DOMException&&s.name==="QuotaExceededError"&&o("error","sessionStorage quota exceeded - data will not persist",{error:s,data:{key:e,valueSize:t.length}})}}removeSessionItem(e){try{this.sessionStorageRef&&this.sessionStorageRef.removeItem(e)}catch{}this.fallbackSessionStorage.delete(e)}}class mt extends g{eventManager;reportedByNav=new Map;observers=[];lastLongTaskSentAt=0;vitalThresholds=he;constructor(e){super(),this.eventManager=e}async startTracking(){await this.initWebVitals(),this.observeLongTasks()}stopTracking(){this.observers.forEach((e,t)=>{try{e.disconnect()}catch(s){o("warn","Failed to disconnect performance observer",{error:s,data:{observerIndex:t}})}}),this.observers.length=0,this.reportedByNav.clear()}observeWebVitalsFallback(){this.reportTTFB(),this.safeObserve("largest-contentful-paint",s=>{const n=s.getEntries(),i=n[n.length-1];i&&this.sendVital({type:"LCP",value:Number(i.startTime.toFixed(2))})},{type:"largest-contentful-paint",buffered:!0},!0);let e=0,t=this.getNavigationId();this.safeObserve("layout-shift",s=>{const n=this.getNavigationId();n!==t&&(e=0,t=n);const i=s.getEntries();for(const a of i){if(a.hadRecentInput===!0)continue;const l=typeof a.value=="number"?a.value:0;e+=l}this.sendVital({type:"CLS",value:Number(e.toFixed(2))})},{type:"layout-shift",buffered:!0}),this.safeObserve("paint",s=>{for(const n of s.getEntries())n.name==="first-contentful-paint"&&this.sendVital({type:"FCP",value:Number(n.startTime.toFixed(2))})},{type:"paint",buffered:!0},!0),this.safeObserve("event",s=>{let n=0;const i=s.getEntries();for(const a of i){const l=(a.processingEnd??0)-(a.startTime??0);n=Math.max(n,l)}n>0&&this.sendVital({type:"INP",value:Number(n.toFixed(2))})},{type:"event",buffered:!0})}async initWebVitals(){try{const{onLCP:e,onCLS:t,onFCP:s,onTTFB:n,onINP:i}=await Promise.resolve().then(()=>qt),a=l=>c=>{const d=Number(c.value.toFixed(2));this.sendVital({type:l,value:d})};e(a("LCP")),t(a("CLS")),s(a("FCP")),n(a("TTFB")),i(a("INP"))}catch(e){o("warn","Failed to load web-vitals library, using fallback",{error:e}),this.observeWebVitalsFallback()}}reportTTFB(){try{const e=performance.getEntriesByType("navigation")[0];if(!e)return;const t=e.responseStart;typeof t=="number"&&Number.isFinite(t)&&this.sendVital({type:"TTFB",value:Number(t.toFixed(2))})}catch(e){o("warn","Failed to report TTFB",{error:e})}}observeLongTasks(){this.safeObserve("longtask",e=>{const t=e.getEntries();for(const s of t){const n=Number(s.duration.toFixed(2)),i=Date.now();i-this.lastLongTaskSentAt>=$e&&(this.shouldSendVital("LONG_TASK",n)&&this.trackWebVital("LONG_TASK",n),this.lastLongTaskSentAt=i)}},{type:"longtask",buffered:!0})}sendVital(e){if(!this.shouldSendVital(e.type,e.value))return;const t=this.getNavigationId();if(t){const s=this.reportedByNav.get(t);if(s?.has(e.type))return;s?s.add(e.type):this.reportedByNav.set(t,new Set([e.type]))}this.trackWebVital(e.type,e.value)}trackWebVital(e,t){if(!Number.isFinite(t)){o("warn","Invalid web vital value",{data:{type:e,value:t}});return}this.eventManager.track({type:h.WEB_VITALS,web_vitals:{type:e,value:t}})}getNavigationId(){try{const e=performance.getEntriesByType("navigation")[0];if(!e)return null;const t=e.startTime||performance.now(),s=Math.random().toString(36).substr(2,5);return`${t.toFixed(2)}_${window.location.pathname}_${s}`}catch(e){return o("warn","Failed to get navigation ID",{error:e}),null}}isObserverSupported(e){if(typeof PerformanceObserver>"u")return!1;const t=PerformanceObserver.supportedEntryTypes;return!t||t.includes(e)}safeObserve(e,t,s,n=!1){try{if(!this.isObserverSupported(e))return!1;const i=new PerformanceObserver((a,l)=>{try{t(a,l)}catch(c){o("warn","Observer callback failed",{error:c,data:{type:e}})}if(n)try{l.disconnect()}catch{}});return i.observe(s??{type:e,buffered:!0}),n||this.observers.push(i),!0}catch(i){return o("warn","Failed to create performance observer",{error:i,data:{type:e}}),!1}}shouldSendVital(e,t){if(typeof t!="number"||!Number.isFinite(t))return o("warn","Invalid web vital value",{data:{type:e,value:t}}),!1;const s=this.vitalThresholds[e];return!(typeof s=="number"&&t<=s)}}class pt extends g{eventManager;recentErrors=new Map;constructor(e){super(),this.eventManager=e}startTracking(){window.addEventListener("error",this.handleError),window.addEventListener("unhandledrejection",this.handleRejection)}stopTracking(){window.removeEventListener("error",this.handleError),window.removeEventListener("unhandledrejection",this.handleRejection),this.recentErrors.clear()}shouldSample(){const t=this.get("config")?.errorSampling??.1;return Math.random()<t}handleError=e=>{if(!this.shouldSample())return;const t=this.sanitize(e.message||"Unknown error");this.shouldSuppressError(M.JS_ERROR,t)||this.eventManager.track({type:h.ERROR,error_data:{type:M.JS_ERROR,message:t,...e.filename&&{filename:e.filename},...e.lineno&&{line:e.lineno},...e.colno&&{column:e.colno}}})};handleRejection=e=>{if(!this.shouldSample())return;const t=this.extractRejectionMessage(e.reason),s=this.sanitize(t);this.shouldSuppressError(M.PROMISE_REJECTION,s)||this.eventManager.track({type:h.ERROR,error_data:{type:M.PROMISE_REJECTION,message:s}})};extractRejectionMessage(e){if(!e)return"Unknown rejection";if(typeof e=="string")return e;if(e instanceof Error)return e.stack??e.message??e.toString();if(typeof e=="object"&&"message"in e)return String(e.message);try{return JSON.stringify(e)}catch{return String(e)}}sanitize(e){let t=e.length>ge?e.slice(0,ge)+"...":e;for(const s of fe){const n=new RegExp(s.source,s.flags);t=t.replace(n,"[REDACTED]")}return t}shouldSuppressError(e,t){const s=Date.now(),n=`${e}:${t}`,i=this.recentErrors.get(n);return i&&s-i<Ee?(this.recentErrors.set(n,s),!0):(this.recentErrors.set(n,s),this.recentErrors.size>ze?(this.recentErrors.clear(),this.recentErrors.set(n,s),!1):(this.recentErrors.size>V&&this.pruneOldErrors(),!1))}pruneOldErrors(){const e=Date.now();for(const[n,i]of this.recentErrors.entries())e-i>Ee&&this.recentErrors.delete(n);if(this.recentErrors.size<=V)return;const t=Array.from(this.recentErrors.entries()).sort((n,i)=>n[1]-i[1]),s=this.recentErrors.size-V;for(let n=0;n<s;n+=1){const i=t[n];i&&this.recentErrors.delete(i[0])}}}class It extends g{isInitialized=!1;suppressNextScrollTimer=null;emitter=new lt;managers={};handlers={};integrations={};get initialized(){return this.isInitialized}async init(e={}){if(!this.isInitialized){this.managers.storage=new Tt;try{this.setupState(e),await this.setupIntegrations(),this.managers.event=new ut(this.managers.storage,this.integrations.googleAnalytics,this.emitter),this.initializeHandlers(),await this.managers.event.recoverPersistedEvents().catch(t=>{o("warn","Failed to recover persisted events",{error:t})}),this.isInitialized=!0}catch(t){this.destroy(!0);const s=t instanceof Error?t.message:String(t);throw new Error(`[TraceLog] TraceLog initialization failed: ${s}`)}}}sendCustomEvent(e,t){if(!this.managers.event)return;const{valid:s,error:n,sanitizedMetadata:i}=ot(e,t);if(!s){if(this.get("mode")===w.QA)throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${n}`);return}this.managers.event.track({type:h.CUSTOM,custom_event:{name:e,...i&&{metadata:i}}})}on(e,t){this.emitter.on(e,t)}off(e,t){this.emitter.off(e,t)}destroy(e=!1){!this.isInitialized&&!e||(this.integrations.googleAnalytics?.cleanup(),Object.values(this.handlers).filter(Boolean).forEach(t=>{try{t.stopTracking()}catch(s){o("warn","Failed to stop tracking",{error:s})}}),this.suppressNextScrollTimer&&(clearTimeout(this.suppressNextScrollTimer),this.suppressNextScrollTimer=null),this.managers.event?.flushImmediatelySync(),this.managers.event?.stop(),this.emitter.removeAllListeners(),this.set("hasStartSession",!1),this.set("suppressNextScroll",!1),this.set("sessionId",null),this.isInitialized=!1,this.handlers={})}setupState(e={}){this.set("config",e);const t=dt.getId(this.managers.storage);this.set("userId",t);const s=Ze(e);this.set("collectApiUrl",s);const n=Ge();this.set("device",n);const i=j(window.location.href,e.sensitiveQueryParams);this.set("pageUrl",i);const a=je()?w.QA:void 0;a&&this.set("mode",a)}async setupIntegrations(){if(this.get("config").integrations?.googleAnalytics?.measurementId?.trim())try{this.integrations.googleAnalytics=new _t,await this.integrations.googleAnalytics.initialize()}catch{this.integrations.googleAnalytics=void 0}}initializeHandlers(){this.handlers.session=new ft(this.managers.storage,this.managers.event),this.handlers.session.startTracking();const e=()=>{this.set("suppressNextScroll",!0),this.suppressNextScrollTimer&&clearTimeout(this.suppressNextScrollTimer),this.suppressNextScrollTimer=window.setTimeout(()=>{this.set("suppressNextScroll",!1)},250*2)};this.handlers.pageView=new gt(this.managers.event,e),this.handlers.pageView.startTracking(),this.handlers.click=new Et(this.managers.event),this.handlers.click.startTracking(),this.handlers.scroll=new St(this.managers.event),this.handlers.scroll.startTracking(),this.handlers.performance=new mt(this.managers.event),this.handlers.performance.startTracking().catch(t=>{o("warn","Failed to start performance tracking",{error:t})}),this.handlers.error=new pt(this.managers.event),this.handlers.error.startTracking()}}const N=[];let f=null,C=!1,G=!1;const vt=async r=>{if(typeof window>"u"||typeof document>"u")throw new Error("[TraceLog] This library can only be used in a browser environment");if(!window.__traceLogDisabled&&!f&&!C){C=!0;try{const e=st(r??{}),t=new It;try{N.forEach(({event:i,callback:a})=>{t.on(i,a)}),N.length=0;const s=t.init(e),n=new Promise((i,a)=>{setTimeout(()=>{a(new Error("[TraceLog] Initialization timeout after 10000ms"))},1e4)});await Promise.race([s,n]),f=t}catch(s){try{t.destroy(!0)}catch(n){o("error","Failed to cleanup partially initialized app",{error:n})}throw s}}catch(e){throw f=null,e}finally{C=!1}}},At=(r,e)=>{if(!f)throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");if(G)throw new Error("[TraceLog] Cannot send events while TraceLog is being destroyed");f.sendCustomEvent(r,e)},yt=(r,e)=>{if(!f||C){N.push({event:r,callback:e});return}f.on(r,e)},Nt=(r,e)=>{if(!f){const t=N.findIndex(s=>s.event===r&&s.callback===e);t!==-1&&N.splice(t,1);return}f.off(r,e)},Mt=()=>f!==null,wt=()=>{if(G)throw new Error("[TraceLog] Destroy operation already in progress");if(!f)throw new Error("[TraceLog] App not initialized");G=!0;try{f.destroy(),f=null,C=!1,N.length=0}catch(r){f=null,C=!1,N.length=0,o("warn","Error during destroy, forced cleanup completed",{error:r})}finally{G=!1}},Lt={WEB_VITALS_THRESHOLDS:he},Ct={PII_PATTERNS:fe},Rt={LOW_ACTIVITY_EVENT_COUNT:50,HIGH_ACTIVITY_EVENT_COUNT:1e3,MIN_EVENTS_FOR_DYNAMIC_CALCULATION:100,MIN_EVENTS_FOR_TREND_ANALYSIS:30,BOUNCE_RATE_SESSION_THRESHOLD:1,MIN_ENGAGED_SESSION_DURATION_MS:30*1e3,MIN_SCROLL_DEPTH_ENGAGEMENT:25},Ot={INACTIVITY_TIMEOUT_MS:30*60*1e3,SHORT_SESSION_THRESHOLD_MS:30*1e3,MEDIUM_SESSION_THRESHOLD_MS:5*60*1e3,LONG_SESSION_THRESHOLD_MS:30*60*1e3,MAX_REALISTIC_SESSION_DURATION_MS:8*60*60*1e3},bt={MOBILE_MAX_WIDTH:768,TABLET_MAX_WIDTH:1024,MOBILE_PERFORMANCE_FACTOR:1.5,TABLET_PERFORMANCE_FACTOR:1.2},Dt={MIN_TEXT_LENGTH_FOR_ANALYSIS:10,MIN_CLICKS_FOR_HOT_ELEMENT:10,MIN_SCROLL_COMPLETION_PERCENT:80,MIN_TIME_ON_PAGE_FOR_READ_MS:15*1e3},Pt={SIGNIFICANT_CHANGE_PERCENT:20,MAJOR_CHANGE_PERCENT:50,MIN_EVENTS_FOR_INSIGHT:100,MIN_SESSIONS_FOR_INSIGHT:10,MIN_CORRELATION_STRENGTH:.7,LOW_ERROR_RATE_PERCENT:1,HIGH_ERROR_RATE_PERCENT:5,CRITICAL_ERROR_RATE_PERCENT:10},Ut={SHORT_TERM_TREND_HOURS:24,MEDIUM_TERM_TREND_DAYS:7,LONG_TERM_TREND_DAYS:30,MIN_DATA_POINTS_FOR_TREND:5,WEEKLY_PATTERN_MIN_WEEKS:4,DAILY_PATTERN_MIN_DAYS:14},kt={MIN_SEGMENT_SIZE:10,MIN_COHORT_SIZE:5,COHORT_ANALYSIS_DAYS:[1,3,7,14,30],MIN_FUNNEL_EVENTS:20},Ht={DEFAULT_EVENTS_LIMIT:5,DEFAULT_SESSIONS_LIMIT:5,DEFAULT_PAGES_LIMIT:5,MAX_EVENTS_FOR_DEEP_ANALYSIS:1e4,MAX_TIME_RANGE_DAYS:365,ANALYTICS_BATCH_SIZE:1e3},Vt={ANOMALY_THRESHOLD_SIGMA:2.5,STRONG_ANOMALY_THRESHOLD_SIGMA:3,TRAFFIC_DROP_ALERT_PERCENT:-30,TRAFFIC_SPIKE_ALERT_PERCENT:200,MIN_BASELINE_DAYS:7,MIN_EVENTS_FOR_ANOMALY_DETECTION:50},Gt={PAGE_URL_EXCLUDED:"excluded",PAGE_URL_UNKNOWN:"unknown"},Ft={init:vt,event:At,on:yt,off:Nt,isInitialized:Mt,destroy:wt};var Z,ve=-1,R=function(r){addEventListener("pageshow",function(e){e.persisted&&(ve=e.timeStamp,r(e))},!0)},q=function(){var r=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(r&&r.responseStart>0&&r.responseStart<performance.now())return r},F=function(){var r=q();return r&&r.activationStart||0},E=function(r,e){var t=q(),s="navigate";return ve>=0?s="back-forward-cache":t&&(document.prerendering||F()>0?s="prerender":document.wasDiscarded?s="restore":t.type&&(s=t.type.replace(/_/g,"-"))),{name:r,value:e===void 0?-1:e,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:s}},D=function(r,e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(r)){var s=new PerformanceObserver(function(n){Promise.resolve().then(function(){e(n.getEntries())})});return s.observe(Object.assign({type:r,buffered:!0},t||{})),s}}catch{}},S=function(r,e,t,s){var n,i;return function(a){e.value>=0&&(a||s)&&((i=e.value-(n||0))||n===void 0)&&(n=e.value,e.delta=i,e.rating=function(l,c){return l>c[1]?"poor":l>c[0]?"needs-improvement":"good"}(e.value,t),r(e))}},J=function(r){requestAnimationFrame(function(){return requestAnimationFrame(function(){return r()})})},x=function(r){document.addEventListener("visibilitychange",function(){document.visibilityState==="hidden"&&r()})},ee=function(r){var e=!1;return function(){e||(r(),e=!0)}},O=-1,Ae=function(){return document.visibilityState!=="hidden"||document.prerendering?1/0:0},X=function(r){document.visibilityState==="hidden"&&O>-1&&(O=r.type==="visibilitychange"?r.timeStamp:0,xt())},ye=function(){addEventListener("visibilitychange",X,!0),addEventListener("prerenderingchange",X,!0)},xt=function(){removeEventListener("visibilitychange",X,!0),removeEventListener("prerenderingchange",X,!0)},Ne=function(){return O<0&&(O=Ae(),ye(),R(function(){setTimeout(function(){O=Ae(),ye()},0)})),{get firstHiddenTime(){return O}}},B=function(r){document.prerendering?addEventListener("prerenderingchange",function(){return r()},!0):r()},te=[1800,3e3],Me=function(r,e){e=e||{},B(function(){var t,s=Ne(),n=E("FCP"),i=D("paint",function(a){a.forEach(function(l){l.name==="first-contentful-paint"&&(i.disconnect(),l.startTime<s.firstHiddenTime&&(n.value=Math.max(l.startTime-F(),0),n.entries.push(l),t(!0)))})});i&&(t=S(r,n,te,e.reportAllChanges),R(function(a){n=E("FCP"),t=S(r,n,te,e.reportAllChanges),J(function(){n.value=performance.now()-a.timeStamp,t(!0)})}))})},re=[.1,.25],Xt=function(r,e){e=e||{},Me(ee(function(){var t,s=E("CLS",0),n=0,i=[],a=function(c){c.forEach(function(d){if(!d.hadRecentInput){var v=i[0],P=i[i.length-1];n&&d.startTime-P.startTime<1e3&&d.startTime-v.startTime<5e3?(n+=d.value,i.push(d)):(n=d.value,i=[d])}}),n>s.value&&(s.value=n,s.entries=i,t())},l=D("layout-shift",a);l&&(t=S(r,s,re,e.reportAllChanges),x(function(){a(l.takeRecords()),t(!0)}),R(function(){n=0,s=E("CLS",0),t=S(r,s,re,e.reportAllChanges),J(function(){return t()})}),setTimeout(t,0))}))},we=0,se=1/0,$=0,Bt=function(r){r.forEach(function(e){e.interactionId&&(se=Math.min(se,e.interactionId),$=Math.max($,e.interactionId),we=$?($-se)/7+1:0)})},Le=function(){return Z?we:performance.interactionCount||0},$t=function(){"interactionCount"in performance||Z||(Z=D("event",Bt,{type:"event",buffered:!0,durationThreshold:0}))},_=[],z=new Map,Ce=0,zt=function(){var r=Math.min(_.length-1,Math.floor((Le()-Ce)/50));return _[r]},Yt=[],Qt=function(r){if(Yt.forEach(function(n){return n(r)}),r.interactionId||r.entryType==="first-input"){var e=_[_.length-1],t=z.get(r.interactionId);if(t||_.length<10||r.duration>e.latency){if(t)r.duration>t.latency?(t.entries=[r],t.latency=r.duration):r.duration===t.latency&&r.startTime===t.entries[0].startTime&&t.entries.push(r);else{var s={id:r.interactionId,latency:r.duration,entries:[r]};z.set(s.id,s),_.push(s)}_.sort(function(n,i){return i.latency-n.latency}),_.length>10&&_.splice(10).forEach(function(n){return z.delete(n.id)})}}},Re=function(r){var e=self.requestIdleCallback||self.setTimeout,t=-1;return r=ee(r),document.visibilityState==="hidden"?r():(t=e(r),x(r)),t},ne=[200,500],jt=function(r,e){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(e=e||{},B(function(){var t;$t();var s,n=E("INP"),i=function(l){Re(function(){l.forEach(Qt);var c=zt();c&&c.latency!==n.value&&(n.value=c.latency,n.entries=c.entries,s())})},a=D("event",i,{durationThreshold:(t=e.durationThreshold)!==null&&t!==void 0?t:40});s=S(r,n,ne,e.reportAllChanges),a&&(a.observe({type:"first-input",buffered:!0}),x(function(){i(a.takeRecords()),s(!0)}),R(function(){Ce=Le(),_.length=0,z.clear(),n=E("INP"),s=S(r,n,ne,e.reportAllChanges)}))}))},ie=[2500,4e3],ae={},Kt=function(r,e){e=e||{},B(function(){var t,s=Ne(),n=E("LCP"),i=function(c){e.reportAllChanges||(c=c.slice(-1)),c.forEach(function(d){d.startTime<s.firstHiddenTime&&(n.value=Math.max(d.startTime-F(),0),n.entries=[d],t())})},a=D("largest-contentful-paint",i);if(a){t=S(r,n,ie,e.reportAllChanges);var l=ee(function(){ae[n.id]||(i(a.takeRecords()),a.disconnect(),ae[n.id]=!0,t(!0))});["keydown","click"].forEach(function(c){addEventListener(c,function(){return Re(l)},{once:!0,capture:!0})}),x(l),R(function(c){n=E("LCP"),t=S(r,n,ie,e.reportAllChanges),J(function(){n.value=performance.now()-c.timeStamp,ae[n.id]=!0,t(!0)})})}})},oe=[800,1800],Wt=function r(e){document.prerendering?B(function(){return r(e)}):document.readyState!=="complete"?addEventListener("load",function(){return r(e)},!0):setTimeout(e,0)},Zt=function(r,e){e=e||{};var t=E("TTFB"),s=S(r,t,oe,e.reportAllChanges);Wt(function(){var n=q();n&&(t.value=Math.max(n.responseStart-F(),0),t.entries=[n],s(!0),R(function(){t=E("TTFB",0),(s=S(r,t,oe,e.reportAllChanges))(!0)}))})};const qt=Object.freeze(Object.defineProperty({__proto__:null,CLSThresholds:re,FCPThresholds:te,INPThresholds:ne,LCPThresholds:ie,TTFBThresholds:oe,onCLS:Xt,onFCP:Me,onINP:jt,onLCP:Kt,onTTFB:Zt},Symbol.toStringTag,{value:"Module"}));u.ANALYTICS_QUERY_LIMITS=Ht,u.ANOMALY_DETECTION=Vt,u.AppConfigValidationError=y,u.CONTENT_ANALYTICS=Dt,u.DATA_PROTECTION=Ct,u.DEVICE_ANALYTICS=bt,u.DeviceType=m,u.ENGAGEMENT_THRESHOLDS=Rt,u.EmitterEvent=H,u.ErrorType=M,u.EventType=h,u.INSIGHT_THRESHOLDS=Pt,u.InitializationTimeoutError=Ue,u.IntegrationValidationError=p,u.MAX_ARRAY_LENGTH=100,u.MAX_CUSTOM_EVENT_ARRAY_SIZE=10,u.MAX_CUSTOM_EVENT_ARRAY_SIZE_BACKEND=100,u.MAX_CUSTOM_EVENT_JSON_SIZE_BACKEND=51200,u.MAX_CUSTOM_EVENT_KEYS=10,u.MAX_CUSTOM_EVENT_KEYS_BACKEND=50,u.MAX_CUSTOM_EVENT_NAME_LENGTH=120,u.MAX_CUSTOM_EVENT_STRING_SIZE=8192,u.MAX_METADATA_NESTING_DEPTH=1,u.MAX_METADATA_NESTING_DEPTH_BACKEND=2,u.MAX_NESTED_OBJECT_KEYS=20,u.MAX_STRING_LENGTH=1e3,u.MAX_STRING_LENGTH_BACKEND=2e3,u.MAX_STRING_LENGTH_IN_ARRAY=500,u.Mode=w,u.PERFORMANCE_CONFIG=Lt,u.PermanentError=A,u.SEGMENTATION_ANALYTICS=kt,u.SESSION_ANALYTICS=Ot,u.SPECIAL_PAGE_URLS=Gt,u.SamplingRateValidationError=Y,u.ScrollDirection=b,u.SessionTimeoutValidationError=ce,u.SpecialApiUrl=k,u.TEMPORAL_ANALYSIS=Ut,u.TraceLogValidationError=L,u.tracelog=Ft,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})})(this.TraceLog=this.TraceLog||{});typeof window<"u"&&window.TraceLog?.tracelog&&(window.tracelog=window.TraceLog.tracelog);
|