summaryrefslogtreecommitdiff
path: root/shared/logger/node_modules/@sentry/browser
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /shared/logger/node_modules/@sentry/browser
init commit
Diffstat (limited to 'shared/logger/node_modules/@sentry/browser')
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/client.js139
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/eventbuilder.js304
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/helpers.js154
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/index.js39
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/breadcrumbs.js320
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/dedupe.js211
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/globalhandlers.js248
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/httpcontext.js47
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/linkederrors.js87
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js281
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/profiling/hubextensions.js240
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/profiling/integration.js81
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/profiling/utils.js438
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/sdk.js293
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/stack-parsers.js168
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js64
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/transports/offline.js133
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/transports/utils.js85
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js52
-rw-r--r--shared/logger/node_modules/@sentry/browser/esm/userfeedback.js41
20 files changed, 3425 insertions, 0 deletions
diff --git a/shared/logger/node_modules/@sentry/browser/esm/client.js b/shared/logger/node_modules/@sentry/browser/esm/client.js
new file mode 100644
index 0000000..a171d99
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/client.js
@@ -0,0 +1,139 @@
+import { BaseClient, SDK_VERSION } from '@sentry/core';
+import { getSDKSource, logger, createClientReportEnvelope, dsnToString } from '@sentry/utils';
+import { eventFromException, eventFromMessage } from './eventbuilder.js';
+import { WINDOW } from './helpers.js';
+import { BREADCRUMB_INTEGRATION_ID } from './integrations/breadcrumbs.js';
+import { createUserFeedbackEnvelope } from './userfeedback.js';
+
+/**
+ * Configuration options for the Sentry Browser SDK.
+ * @see @sentry/types Options for more information.
+ */
+
+/**
+ * The Sentry Browser SDK Client.
+ *
+ * @see BrowserOptions for documentation on configuration options.
+ * @see SentryClient for usage documentation.
+ */
+class BrowserClient extends BaseClient {
+ /**
+ * Creates a new Browser SDK instance.
+ *
+ * @param options Configuration options for this SDK.
+ */
+ constructor(options) {
+ const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();
+
+ options._metadata = options._metadata || {};
+ options._metadata.sdk = options._metadata.sdk || {
+ name: 'sentry.javascript.browser',
+ packages: [
+ {
+ name: `${sdkSource}:@sentry/browser`,
+ version: SDK_VERSION,
+ },
+ ],
+ version: SDK_VERSION,
+ };
+
+ super(options);
+
+ if (options.sendClientReports && WINDOW.document) {
+ WINDOW.document.addEventListener('visibilitychange', () => {
+ if (WINDOW.document.visibilityState === 'hidden') {
+ this._flushOutcomes();
+ }
+ });
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ eventFromException(exception, hint) {
+ return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ eventFromMessage(
+ message,
+ // eslint-disable-next-line deprecation/deprecation
+ level = 'info',
+ hint,
+ ) {
+ return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ sendEvent(event, hint) {
+ // We only want to add the sentry event breadcrumb when the user has the breadcrumb integration installed and
+ // activated its `sentry` option.
+ // We also do not want to use the `Breadcrumbs` class here directly, because we do not want it to be included in
+ // bundles, if it is not used by the SDK.
+ // This all sadly is a bit ugly, but we currently don't have a "pre-send" hook on the integrations so we do it this
+ // way for now.
+ const breadcrumbIntegration = this.getIntegrationById(BREADCRUMB_INTEGRATION_ID) ;
+ // We check for definedness of `addSentryBreadcrumb` in case users provided their own integration with id
+ // "Breadcrumbs" that does not have this function.
+ if (breadcrumbIntegration && breadcrumbIntegration.addSentryBreadcrumb) {
+ breadcrumbIntegration.addSentryBreadcrumb(event);
+ }
+
+ super.sendEvent(event, hint);
+ }
+
+ /**
+ * Sends user feedback to Sentry.
+ */
+ captureUserFeedback(feedback) {
+ if (!this._isEnabled()) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('SDK not enabled, will not capture user feedback.');
+ return;
+ }
+
+ const envelope = createUserFeedbackEnvelope(feedback, {
+ metadata: this.getSdkMetadata(),
+ dsn: this.getDsn(),
+ tunnel: this.getOptions().tunnel,
+ });
+ void this._sendEnvelope(envelope);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ _prepareEvent(event, hint, scope) {
+ event.platform = event.platform || 'javascript';
+ return super._prepareEvent(event, hint, scope);
+ }
+
+ /**
+ * Sends client reports as an envelope.
+ */
+ _flushOutcomes() {
+ const outcomes = this._clearOutcomes();
+
+ if (outcomes.length === 0) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('No outcomes to send');
+ return;
+ }
+
+ if (!this._dsn) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('No dsn provided, will not send outcomes');
+ return;
+ }
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('Sending outcomes:', outcomes);
+
+ const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn));
+ void this._sendEnvelope(envelope);
+ }
+}
+
+export { BrowserClient };
+//# sourceMappingURL=client.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/eventbuilder.js b/shared/logger/node_modules/@sentry/browser/esm/eventbuilder.js
new file mode 100644
index 0000000..08e5653
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/eventbuilder.js
@@ -0,0 +1,304 @@
+import { getCurrentHub } from '@sentry/core';
+import { addExceptionMechanism, resolvedSyncPromise, isErrorEvent, isDOMError, isDOMException, addExceptionTypeValue, isError, isPlainObject, isEvent, normalizeToSize, extractExceptionKeysForMessage } from '@sentry/utils';
+
+/**
+ * This function creates an exception from a JavaScript Error
+ */
+function exceptionFromError(stackParser, ex) {
+ // Get the frames first since Opera can lose the stack if we touch anything else first
+ const frames = parseStackFrames(stackParser, ex);
+
+ const exception = {
+ type: ex && ex.name,
+ value: extractMessage(ex),
+ };
+
+ if (frames.length) {
+ exception.stacktrace = { frames };
+ }
+
+ if (exception.type === undefined && exception.value === '') {
+ exception.value = 'Unrecoverable error caught';
+ }
+
+ return exception;
+}
+
+/**
+ * @hidden
+ */
+function eventFromPlainObject(
+ stackParser,
+ exception,
+ syntheticException,
+ isUnhandledRejection,
+) {
+ const hub = getCurrentHub();
+ const client = hub.getClient();
+ const normalizeDepth = client && client.getOptions().normalizeDepth;
+
+ const event = {
+ exception: {
+ values: [
+ {
+ type: isEvent(exception) ? exception.constructor.name : isUnhandledRejection ? 'UnhandledRejection' : 'Error',
+ value: getNonErrorObjectExceptionValue(exception, { isUnhandledRejection }),
+ },
+ ],
+ },
+ extra: {
+ __serialized__: normalizeToSize(exception, normalizeDepth),
+ },
+ };
+
+ if (syntheticException) {
+ const frames = parseStackFrames(stackParser, syntheticException);
+ if (frames.length) {
+ // event.exception.values[0] has been set above
+ (event.exception ).values[0].stacktrace = { frames };
+ }
+ }
+
+ return event;
+}
+
+/**
+ * @hidden
+ */
+function eventFromError(stackParser, ex) {
+ return {
+ exception: {
+ values: [exceptionFromError(stackParser, ex)],
+ },
+ };
+}
+
+/** Parses stack frames from an error */
+function parseStackFrames(
+ stackParser,
+ ex,
+) {
+ // Access and store the stacktrace property before doing ANYTHING
+ // else to it because Opera is not very good at providing it
+ // reliably in other circumstances.
+ const stacktrace = ex.stacktrace || ex.stack || '';
+
+ const popSize = getPopSize(ex);
+
+ try {
+ return stackParser(stacktrace, popSize);
+ } catch (e) {
+ // no-empty
+ }
+
+ return [];
+}
+
+// Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108
+const reactMinifiedRegexp = /Minified React error #\d+;/i;
+
+function getPopSize(ex) {
+ if (ex) {
+ if (typeof ex.framesToPop === 'number') {
+ return ex.framesToPop;
+ }
+
+ if (reactMinifiedRegexp.test(ex.message)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * There are cases where stacktrace.message is an Event object
+ * https://github.com/getsentry/sentry-javascript/issues/1949
+ * In this specific case we try to extract stacktrace.message.error.message
+ */
+function extractMessage(ex) {
+ const message = ex && ex.message;
+ if (!message) {
+ return 'No error message';
+ }
+ if (message.error && typeof message.error.message === 'string') {
+ return message.error.message;
+ }
+ return message;
+}
+
+/**
+ * Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`.
+ * @hidden
+ */
+function eventFromException(
+ stackParser,
+ exception,
+ hint,
+ attachStacktrace,
+) {
+ const syntheticException = (hint && hint.syntheticException) || undefined;
+ const event = eventFromUnknownInput(stackParser, exception, syntheticException, attachStacktrace);
+ addExceptionMechanism(event); // defaults to { type: 'generic', handled: true }
+ event.level = 'error';
+ if (hint && hint.event_id) {
+ event.event_id = hint.event_id;
+ }
+ return resolvedSyncPromise(event);
+}
+
+/**
+ * Builds and Event from a Message
+ * @hidden
+ */
+function eventFromMessage(
+ stackParser,
+ message,
+ // eslint-disable-next-line deprecation/deprecation
+ level = 'info',
+ hint,
+ attachStacktrace,
+) {
+ const syntheticException = (hint && hint.syntheticException) || undefined;
+ const event = eventFromString(stackParser, message, syntheticException, attachStacktrace);
+ event.level = level;
+ if (hint && hint.event_id) {
+ event.event_id = hint.event_id;
+ }
+ return resolvedSyncPromise(event);
+}
+
+/**
+ * @hidden
+ */
+function eventFromUnknownInput(
+ stackParser,
+ exception,
+ syntheticException,
+ attachStacktrace,
+ isUnhandledRejection,
+) {
+ let event;
+
+ if (isErrorEvent(exception ) && (exception ).error) {
+ // If it is an ErrorEvent with `error` property, extract it to get actual Error
+ const errorEvent = exception ;
+ return eventFromError(stackParser, errorEvent.error );
+ }
+
+ // If it is a `DOMError` (which is a legacy API, but still supported in some browsers) then we just extract the name
+ // and message, as it doesn't provide anything else. According to the spec, all `DOMExceptions` should also be
+ // `Error`s, but that's not the case in IE11, so in that case we treat it the same as we do a `DOMError`.
+ //
+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMError
+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMException
+ // https://webidl.spec.whatwg.org/#es-DOMException-specialness
+ if (isDOMError(exception) || isDOMException(exception )) {
+ const domException = exception ;
+
+ if ('stack' in (exception )) {
+ event = eventFromError(stackParser, exception );
+ } else {
+ const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException');
+ const message = domException.message ? `${name}: ${domException.message}` : name;
+ event = eventFromString(stackParser, message, syntheticException, attachStacktrace);
+ addExceptionTypeValue(event, message);
+ }
+ if ('code' in domException) {
+ // eslint-disable-next-line deprecation/deprecation
+ event.tags = { ...event.tags, 'DOMException.code': `${domException.code}` };
+ }
+
+ return event;
+ }
+ if (isError(exception)) {
+ // we have a real Error object, do nothing
+ return eventFromError(stackParser, exception);
+ }
+ if (isPlainObject(exception) || isEvent(exception)) {
+ // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize
+ // it manually. This will allow us to group events based on top-level keys which is much better than creating a new
+ // group on any key/value change.
+ const objectException = exception ;
+ event = eventFromPlainObject(stackParser, objectException, syntheticException, isUnhandledRejection);
+ addExceptionMechanism(event, {
+ synthetic: true,
+ });
+ return event;
+ }
+
+ // If none of previous checks were valid, then it means that it's not:
+ // - an instance of DOMError
+ // - an instance of DOMException
+ // - an instance of Event
+ // - an instance of Error
+ // - a valid ErrorEvent (one with an error property)
+ // - a plain Object
+ //
+ // So bail out and capture it as a simple message:
+ event = eventFromString(stackParser, exception , syntheticException, attachStacktrace);
+ addExceptionTypeValue(event, `${exception}`, undefined);
+ addExceptionMechanism(event, {
+ synthetic: true,
+ });
+
+ return event;
+}
+
+/**
+ * @hidden
+ */
+function eventFromString(
+ stackParser,
+ input,
+ syntheticException,
+ attachStacktrace,
+) {
+ const event = {
+ message: input,
+ };
+
+ if (attachStacktrace && syntheticException) {
+ const frames = parseStackFrames(stackParser, syntheticException);
+ if (frames.length) {
+ event.exception = {
+ values: [{ value: input, stacktrace: { frames } }],
+ };
+ }
+ }
+
+ return event;
+}
+
+function getNonErrorObjectExceptionValue(
+ exception,
+ { isUnhandledRejection },
+) {
+ const keys = extractExceptionKeysForMessage(exception);
+ const captureType = isUnhandledRejection ? 'promise rejection' : 'exception';
+
+ // Some ErrorEvent instances do not have an `error` property, which is why they are not handled before
+ // We still want to try to get a decent message for these cases
+ if (isErrorEvent(exception)) {
+ return `Event \`ErrorEvent\` captured as ${captureType} with message \`${exception.message}\``;
+ }
+
+ if (isEvent(exception)) {
+ const className = getObjectClassName(exception);
+ return `Event \`${className}\` (type=${exception.type}) captured as ${captureType}`;
+ }
+
+ return `Object captured as ${captureType} with keys: ${keys}`;
+}
+
+function getObjectClassName(obj) {
+ try {
+ const prototype = Object.getPrototypeOf(obj);
+ return prototype ? prototype.constructor.name : undefined;
+ } catch (e) {
+ // ignore errors here
+ }
+}
+
+export { eventFromError, eventFromException, eventFromMessage, eventFromPlainObject, eventFromString, eventFromUnknownInput, exceptionFromError, parseStackFrames };
+//# sourceMappingURL=eventbuilder.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/helpers.js b/shared/logger/node_modules/@sentry/browser/esm/helpers.js
new file mode 100644
index 0000000..cfa1229
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/helpers.js
@@ -0,0 +1,154 @@
+import { withScope, captureException } from '@sentry/core';
+import { GLOBAL_OBJ, getOriginalFunction, markFunctionWrapped, addNonEnumerableProperty, addExceptionTypeValue, addExceptionMechanism } from '@sentry/utils';
+
+const WINDOW = GLOBAL_OBJ ;
+
+let ignoreOnError = 0;
+
+/**
+ * @hidden
+ */
+function shouldIgnoreOnError() {
+ return ignoreOnError > 0;
+}
+
+/**
+ * @hidden
+ */
+function ignoreNextOnError() {
+ // onerror should trigger before setTimeout
+ ignoreOnError++;
+ setTimeout(() => {
+ ignoreOnError--;
+ });
+}
+
+/**
+ * Instruments the given function and sends an event to Sentry every time the
+ * function throws an exception.
+ *
+ * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always
+ * has a correct `this` context.
+ * @returns The wrapped function.
+ * @hidden
+ */
+function wrap(
+ fn,
+ options
+
+ = {},
+ before,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+) {
+ // for future readers what this does is wrap a function and then create
+ // a bi-directional wrapping between them.
+ //
+ // example: wrapped = wrap(original);
+ // original.__sentry_wrapped__ -> wrapped
+ // wrapped.__sentry_original__ -> original
+
+ if (typeof fn !== 'function') {
+ return fn;
+ }
+
+ try {
+ // if we're dealing with a function that was previously wrapped, return
+ // the original wrapper.
+ const wrapper = fn.__sentry_wrapped__;
+ if (wrapper) {
+ return wrapper;
+ }
+
+ // We don't wanna wrap it twice
+ if (getOriginalFunction(fn)) {
+ return fn;
+ }
+ } catch (e) {
+ // Just accessing custom props in some Selenium environments
+ // can cause a "Permission denied" exception (see raven-js#495).
+ // Bail on wrapping and return the function as-is (defers to window.onerror).
+ return fn;
+ }
+
+ /* eslint-disable prefer-rest-params */
+ // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`
+ const sentryWrapped = function () {
+ const args = Array.prototype.slice.call(arguments);
+
+ try {
+ if (before && typeof before === 'function') {
+ before.apply(this, arguments);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
+ const wrappedArguments = args.map((arg) => wrap(arg, options));
+
+ // Attempt to invoke user-land function
+ // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
+ // means the sentry.javascript SDK caught an error invoking your application code. This
+ // is expected behavior and NOT indicative of a bug with sentry.javascript.
+ return fn.apply(this, wrappedArguments);
+ } catch (ex) {
+ ignoreNextOnError();
+
+ withScope((scope) => {
+ scope.addEventProcessor((event) => {
+ if (options.mechanism) {
+ addExceptionTypeValue(event, undefined, undefined);
+ addExceptionMechanism(event, options.mechanism);
+ }
+
+ event.extra = {
+ ...event.extra,
+ arguments: args,
+ };
+
+ return event;
+ });
+
+ captureException(ex);
+ });
+
+ throw ex;
+ }
+ };
+ /* eslint-enable prefer-rest-params */
+
+ // Accessing some objects may throw
+ // ref: https://github.com/getsentry/sentry-javascript/issues/1168
+ try {
+ for (const property in fn) {
+ if (Object.prototype.hasOwnProperty.call(fn, property)) {
+ sentryWrapped[property] = fn[property];
+ }
+ }
+ } catch (_oO) {} // eslint-disable-line no-empty
+
+ // Signal that this function has been wrapped/filled already
+ // for both debugging and to prevent it to being wrapped/filled twice
+ markFunctionWrapped(sentryWrapped, fn);
+
+ addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);
+
+ // Restore original function name (not all browsers allow that)
+ try {
+ const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name') ;
+ if (descriptor.configurable) {
+ Object.defineProperty(sentryWrapped, 'name', {
+ get() {
+ return fn.name;
+ },
+ });
+ }
+ // eslint-disable-next-line no-empty
+ } catch (_oO) {}
+
+ return sentryWrapped;
+}
+
+/**
+ * All properties the report dialog supports
+ */
+
+export { WINDOW, ignoreNextOnError, shouldIgnoreOnError, wrap };
+//# sourceMappingURL=helpers.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/index.js b/shared/logger/node_modules/@sentry/browser/esm/index.js
new file mode 100644
index 0000000..188f9c0
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/index.js
@@ -0,0 +1,39 @@
+import { Integrations } from '@sentry/core';
+export { FunctionToString, Hub, InboundFilters, SDK_VERSION, Scope, addBreadcrumb, addGlobalEventProcessor, addTracingExtensions, captureEvent, captureException, captureMessage, configureScope, createTransport, extractTraceparentData, getActiveTransaction, getCurrentHub, getHubFromCarrier, makeMain, makeMultiplexedTransport, setContext, setExtra, setExtras, setTag, setTags, setUser, spanStatusfromHttpCode, startTransaction, trace, withScope } from '@sentry/core';
+import { WINDOW } from './helpers.js';
+export { WINDOW } from './helpers.js';
+export { BrowserClient } from './client.js';
+export { makeFetchTransport } from './transports/fetch.js';
+export { makeXHRTransport } from './transports/xhr.js';
+export { chromeStackLineParser, defaultStackLineParsers, defaultStackParser, geckoStackLineParser, opera10StackLineParser, opera11StackLineParser, winjsStackLineParser } from './stack-parsers.js';
+export { eventFromException, eventFromMessage } from './eventbuilder.js';
+export { createUserFeedbackEnvelope } from './userfeedback.js';
+export { captureUserFeedback, close, defaultIntegrations, flush, forceLoad, init, lastEventId, onLoad, showReportDialog, wrap } from './sdk.js';
+import * as index from './integrations/index.js';
+export { Replay } from '@sentry/replay';
+export { BrowserTracing, defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from '@sentry-internal/tracing';
+export { makeBrowserOfflineTransport } from './transports/offline.js';
+export { onProfilingStartRouteTransaction } from './profiling/hubextensions.js';
+export { BrowserProfilingIntegration } from './profiling/integration.js';
+export { GlobalHandlers } from './integrations/globalhandlers.js';
+export { TryCatch } from './integrations/trycatch.js';
+export { Breadcrumbs } from './integrations/breadcrumbs.js';
+export { LinkedErrors } from './integrations/linkederrors.js';
+export { HttpContext } from './integrations/httpcontext.js';
+export { Dedupe } from './integrations/dedupe.js';
+
+let windowIntegrations = {};
+
+// This block is needed to add compatibility with the integrations packages when used with a CDN
+if (WINDOW.Sentry && WINDOW.Sentry.Integrations) {
+ windowIntegrations = WINDOW.Sentry.Integrations;
+}
+
+const INTEGRATIONS = {
+ ...windowIntegrations,
+ ...Integrations,
+ ...index,
+};
+
+export { INTEGRATIONS as Integrations };
+//# sourceMappingURL=index.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/breadcrumbs.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
new file mode 100644
index 0000000..4117cc4
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
@@ -0,0 +1,320 @@
+import { getCurrentHub } from '@sentry/core';
+import { addInstrumentationHandler, getEventDescription, severityLevelFromString, safeJoin, SENTRY_XHR_DATA_KEY, parseUrl, logger, htmlTreeAsString } from '@sentry/utils';
+import { WINDOW } from '../helpers.js';
+
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+
+/** maxStringLength gets capped to prevent 100 breadcrumbs exceeding 1MB event payload size */
+const MAX_ALLOWED_STRING_LENGTH = 1024;
+
+const BREADCRUMB_INTEGRATION_ID = 'Breadcrumbs';
+
+/**
+ * Default Breadcrumbs instrumentations
+ * TODO: Deprecated - with v6, this will be renamed to `Instrument`
+ */
+class Breadcrumbs {
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = BREADCRUMB_INTEGRATION_ID;}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = Breadcrumbs.id;}
+
+ /**
+ * Options of the breadcrumbs integration.
+ */
+ // This field is public, because we use it in the browser client to check if the `sentry` option is enabled.
+
+ /**
+ * @inheritDoc
+ */
+ constructor(options) {Breadcrumbs.prototype.__init.call(this);
+ this.options = {
+ console: true,
+ dom: true,
+ fetch: true,
+ history: true,
+ sentry: true,
+ xhr: true,
+ ...options,
+ };
+ }
+
+ /**
+ * Instrument browser built-ins w/ breadcrumb capturing
+ * - Console API
+ * - DOM API (click/typing)
+ * - XMLHttpRequest API
+ * - Fetch API
+ * - History API
+ */
+ setupOnce() {
+ if (this.options.console) {
+ addInstrumentationHandler('console', _consoleBreadcrumb);
+ }
+ if (this.options.dom) {
+ addInstrumentationHandler('dom', _domBreadcrumb(this.options.dom));
+ }
+ if (this.options.xhr) {
+ addInstrumentationHandler('xhr', _xhrBreadcrumb);
+ }
+ if (this.options.fetch) {
+ addInstrumentationHandler('fetch', _fetchBreadcrumb);
+ }
+ if (this.options.history) {
+ addInstrumentationHandler('history', _historyBreadcrumb);
+ }
+ }
+
+ /**
+ * Adds a breadcrumb for Sentry events or transactions if this option is enabled.
+ */
+ addSentryBreadcrumb(event) {
+ if (this.options.sentry) {
+ getCurrentHub().addBreadcrumb(
+ {
+ category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`,
+ event_id: event.event_id,
+ level: event.level,
+ message: getEventDescription(event),
+ },
+ {
+ event,
+ },
+ );
+ }
+ }
+} Breadcrumbs.__initStatic();
+
+/**
+ * A HOC that creaes a function that creates breadcrumbs from DOM API calls.
+ * This is a HOC so that we get access to dom options in the closure.
+ */
+function _domBreadcrumb(dom) {
+ function _innerDomBreadcrumb(handlerData) {
+ let target;
+ let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;
+
+ let maxStringLength =
+ typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined;
+ if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(
+ `\`dom.maxStringLength\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`,
+ );
+ maxStringLength = MAX_ALLOWED_STRING_LENGTH;
+ }
+
+ if (typeof keyAttrs === 'string') {
+ keyAttrs = [keyAttrs];
+ }
+
+ // Accessing event.target can throw (see getsentry/raven-js#838, #768)
+ try {
+ const event = handlerData.event ;
+ target = _isEvent(event)
+ ? htmlTreeAsString(event.target, { keyAttrs, maxStringLength })
+ : htmlTreeAsString(event, { keyAttrs, maxStringLength });
+ } catch (e) {
+ target = '<unknown>';
+ }
+
+ if (target.length === 0) {
+ return;
+ }
+
+ getCurrentHub().addBreadcrumb(
+ {
+ category: `ui.${handlerData.name}`,
+ message: target,
+ },
+ {
+ event: handlerData.event,
+ name: handlerData.name,
+ global: handlerData.global,
+ },
+ );
+ }
+
+ return _innerDomBreadcrumb;
+}
+
+/**
+ * Creates breadcrumbs from console API calls
+ */
+function _consoleBreadcrumb(handlerData) {
+ // This is a hack to fix a Vue3-specific bug that causes an infinite loop of
+ // console warnings. This happens when a Vue template is rendered with
+ // an undeclared variable, which we try to stringify, ultimately causing
+ // Vue to issue another warning which repeats indefinitely.
+ // see: https://github.com/getsentry/sentry-javascript/pull/6010
+ // see: https://github.com/getsentry/sentry-javascript/issues/5916
+ for (let i = 0; i < handlerData.args.length; i++) {
+ if (handlerData.args[i] === 'ref=Ref<') {
+ handlerData.args[i + 1] = 'viewRef';
+ break;
+ }
+ }
+ const breadcrumb = {
+ category: 'console',
+ data: {
+ arguments: handlerData.args,
+ logger: 'console',
+ },
+ level: severityLevelFromString(handlerData.level),
+ message: safeJoin(handlerData.args, ' '),
+ };
+
+ if (handlerData.level === 'assert') {
+ if (handlerData.args[0] === false) {
+ breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;
+ breadcrumb.data.arguments = handlerData.args.slice(1);
+ } else {
+ // Don't capture a breadcrumb for passed assertions
+ return;
+ }
+ }
+
+ getCurrentHub().addBreadcrumb(breadcrumb, {
+ input: handlerData.args,
+ level: handlerData.level,
+ });
+}
+
+/**
+ * Creates breadcrumbs from XHR API calls
+ */
+function _xhrBreadcrumb(handlerData) {
+ const { startTimestamp, endTimestamp } = handlerData;
+
+ const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];
+
+ // We only capture complete, non-sentry requests
+ if (!startTimestamp || !endTimestamp || !sentryXhrData) {
+ return;
+ }
+
+ const { method, url, status_code, body } = sentryXhrData;
+
+ const data = {
+ method,
+ url,
+ status_code,
+ };
+
+ const hint = {
+ xhr: handlerData.xhr,
+ input: body,
+ startTimestamp,
+ endTimestamp,
+ };
+
+ getCurrentHub().addBreadcrumb(
+ {
+ category: 'xhr',
+ data,
+ type: 'http',
+ },
+ hint,
+ );
+}
+
+/**
+ * Creates breadcrumbs from fetch API calls
+ */
+function _fetchBreadcrumb(handlerData) {
+ const { startTimestamp, endTimestamp } = handlerData;
+
+ // We only capture complete fetch requests
+ if (!endTimestamp) {
+ return;
+ }
+
+ if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {
+ // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)
+ return;
+ }
+
+ if (handlerData.error) {
+ const data = handlerData.fetchData;
+ const hint = {
+ data: handlerData.error,
+ input: handlerData.args,
+ startTimestamp,
+ endTimestamp,
+ };
+
+ getCurrentHub().addBreadcrumb(
+ {
+ category: 'fetch',
+ data,
+ level: 'error',
+ type: 'http',
+ },
+ hint,
+ );
+ } else {
+ const data = {
+ ...handlerData.fetchData,
+ status_code: handlerData.response && handlerData.response.status,
+ };
+ const hint = {
+ input: handlerData.args,
+ response: handlerData.response,
+ startTimestamp,
+ endTimestamp,
+ };
+ getCurrentHub().addBreadcrumb(
+ {
+ category: 'fetch',
+ data,
+ type: 'http',
+ },
+ hint,
+ );
+ }
+}
+
+/**
+ * Creates breadcrumbs from history API calls
+ */
+function _historyBreadcrumb(handlerData) {
+ let from = handlerData.from;
+ let to = handlerData.to;
+ const parsedLoc = parseUrl(WINDOW.location.href);
+ let parsedFrom = parseUrl(from);
+ const parsedTo = parseUrl(to);
+
+ // Initial pushState doesn't provide `from` information
+ if (!parsedFrom.path) {
+ parsedFrom = parsedLoc;
+ }
+
+ // Use only the path component of the URL if the URL matches the current
+ // document (almost all the time when using pushState)
+ if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {
+ to = parsedTo.relative;
+ }
+ if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {
+ from = parsedFrom.relative;
+ }
+
+ getCurrentHub().addBreadcrumb({
+ category: 'navigation',
+ data: {
+ from,
+ to,
+ },
+ });
+}
+
+function _isEvent(event) {
+ return !!event && !!(event ).target;
+}
+
+export { BREADCRUMB_INTEGRATION_ID, Breadcrumbs };
+//# sourceMappingURL=breadcrumbs.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/dedupe.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/dedupe.js
new file mode 100644
index 0000000..591a552
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/dedupe.js
@@ -0,0 +1,211 @@
+import { logger } from '@sentry/utils';
+
+/** Deduplication filter */
+class Dedupe {constructor() { Dedupe.prototype.__init.call(this); }
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = 'Dedupe';}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = Dedupe.id;}
+
+ /**
+ * @inheritDoc
+ */
+
+ /**
+ * @inheritDoc
+ */
+ setupOnce(addGlobalEventProcessor, getCurrentHub) {
+ const eventProcessor = currentEvent => {
+ // We want to ignore any non-error type events, e.g. transactions or replays
+ // These should never be deduped, and also not be compared against as _previousEvent.
+ if (currentEvent.type) {
+ return currentEvent;
+ }
+
+ const self = getCurrentHub().getIntegration(Dedupe);
+ if (self) {
+ // Juuust in case something goes wrong
+ try {
+ if (_shouldDropEvent(currentEvent, self._previousEvent)) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('Event dropped due to being a duplicate of previously captured event.');
+ return null;
+ }
+ } catch (_oO) {
+ return (self._previousEvent = currentEvent);
+ }
+
+ return (self._previousEvent = currentEvent);
+ }
+ return currentEvent;
+ };
+
+ eventProcessor.id = this.name;
+ addGlobalEventProcessor(eventProcessor);
+ }
+} Dedupe.__initStatic();
+
+/** JSDoc */
+function _shouldDropEvent(currentEvent, previousEvent) {
+ if (!previousEvent) {
+ return false;
+ }
+
+ if (_isSameMessageEvent(currentEvent, previousEvent)) {
+ return true;
+ }
+
+ if (_isSameExceptionEvent(currentEvent, previousEvent)) {
+ return true;
+ }
+
+ return false;
+}
+
+/** JSDoc */
+function _isSameMessageEvent(currentEvent, previousEvent) {
+ const currentMessage = currentEvent.message;
+ const previousMessage = previousEvent.message;
+
+ // If neither event has a message property, they were both exceptions, so bail out
+ if (!currentMessage && !previousMessage) {
+ return false;
+ }
+
+ // If only one event has a stacktrace, but not the other one, they are not the same
+ if ((currentMessage && !previousMessage) || (!currentMessage && previousMessage)) {
+ return false;
+ }
+
+ if (currentMessage !== previousMessage) {
+ return false;
+ }
+
+ if (!_isSameFingerprint(currentEvent, previousEvent)) {
+ return false;
+ }
+
+ if (!_isSameStacktrace(currentEvent, previousEvent)) {
+ return false;
+ }
+
+ return true;
+}
+
+/** JSDoc */
+function _isSameExceptionEvent(currentEvent, previousEvent) {
+ const previousException = _getExceptionFromEvent(previousEvent);
+ const currentException = _getExceptionFromEvent(currentEvent);
+
+ if (!previousException || !currentException) {
+ return false;
+ }
+
+ if (previousException.type !== currentException.type || previousException.value !== currentException.value) {
+ return false;
+ }
+
+ if (!_isSameFingerprint(currentEvent, previousEvent)) {
+ return false;
+ }
+
+ if (!_isSameStacktrace(currentEvent, previousEvent)) {
+ return false;
+ }
+
+ return true;
+}
+
+/** JSDoc */
+function _isSameStacktrace(currentEvent, previousEvent) {
+ let currentFrames = _getFramesFromEvent(currentEvent);
+ let previousFrames = _getFramesFromEvent(previousEvent);
+
+ // If neither event has a stacktrace, they are assumed to be the same
+ if (!currentFrames && !previousFrames) {
+ return true;
+ }
+
+ // If only one event has a stacktrace, but not the other one, they are not the same
+ if ((currentFrames && !previousFrames) || (!currentFrames && previousFrames)) {
+ return false;
+ }
+
+ currentFrames = currentFrames ;
+ previousFrames = previousFrames ;
+
+ // If number of frames differ, they are not the same
+ if (previousFrames.length !== currentFrames.length) {
+ return false;
+ }
+
+ // Otherwise, compare the two
+ for (let i = 0; i < previousFrames.length; i++) {
+ const frameA = previousFrames[i];
+ const frameB = currentFrames[i];
+
+ if (
+ frameA.filename !== frameB.filename ||
+ frameA.lineno !== frameB.lineno ||
+ frameA.colno !== frameB.colno ||
+ frameA.function !== frameB.function
+ ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/** JSDoc */
+function _isSameFingerprint(currentEvent, previousEvent) {
+ let currentFingerprint = currentEvent.fingerprint;
+ let previousFingerprint = previousEvent.fingerprint;
+
+ // If neither event has a fingerprint, they are assumed to be the same
+ if (!currentFingerprint && !previousFingerprint) {
+ return true;
+ }
+
+ // If only one event has a fingerprint, but not the other one, they are not the same
+ if ((currentFingerprint && !previousFingerprint) || (!currentFingerprint && previousFingerprint)) {
+ return false;
+ }
+
+ currentFingerprint = currentFingerprint ;
+ previousFingerprint = previousFingerprint ;
+
+ // Otherwise, compare the two
+ try {
+ return !!(currentFingerprint.join('') === previousFingerprint.join(''));
+ } catch (_oO) {
+ return false;
+ }
+}
+
+/** JSDoc */
+function _getExceptionFromEvent(event) {
+ return event.exception && event.exception.values && event.exception.values[0];
+}
+
+/** JSDoc */
+function _getFramesFromEvent(event) {
+ const exception = event.exception;
+
+ if (exception) {
+ try {
+ // @ts-ignore Object could be undefined
+ return exception.values[0].stacktrace.frames;
+ } catch (_oO) {
+ return undefined;
+ }
+ }
+ return undefined;
+}
+
+export { Dedupe };
+//# sourceMappingURL=dedupe.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/globalhandlers.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/globalhandlers.js
new file mode 100644
index 0000000..65c343c
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/globalhandlers.js
@@ -0,0 +1,248 @@
+import { getCurrentHub } from '@sentry/core';
+import { addInstrumentationHandler, isString, isPrimitive, isErrorEvent, getLocationHref, logger, addExceptionMechanism } from '@sentry/utils';
+import { eventFromUnknownInput } from '../eventbuilder.js';
+import { shouldIgnoreOnError } from '../helpers.js';
+
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+
+/** Global handlers */
+class GlobalHandlers {
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = 'GlobalHandlers';}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = GlobalHandlers.id;}
+
+ /** JSDoc */
+
+ /**
+ * Stores references functions to installing handlers. Will set to undefined
+ * after they have been run so that they are not used twice.
+ */
+ __init2() {this._installFunc = {
+ onerror: _installGlobalOnErrorHandler,
+ onunhandledrejection: _installGlobalOnUnhandledRejectionHandler,
+ };}
+
+ /** JSDoc */
+ constructor(options) {GlobalHandlers.prototype.__init.call(this);GlobalHandlers.prototype.__init2.call(this);
+ this._options = {
+ onerror: true,
+ onunhandledrejection: true,
+ ...options,
+ };
+ }
+ /**
+ * @inheritDoc
+ */
+ setupOnce() {
+ Error.stackTraceLimit = 50;
+ const options = this._options;
+
+ // We can disable guard-for-in as we construct the options object above + do checks against
+ // `this._installFunc` for the property.
+ // eslint-disable-next-line guard-for-in
+ for (const key in options) {
+ const installFunc = this._installFunc[key ];
+ if (installFunc && options[key ]) {
+ globalHandlerLog(key);
+ installFunc();
+ this._installFunc[key ] = undefined;
+ }
+ }
+ }
+} GlobalHandlers.__initStatic();
+
+/** JSDoc */
+function _installGlobalOnErrorHandler() {
+ addInstrumentationHandler(
+ 'error',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (data) => {
+ const [hub, stackParser, attachStacktrace] = getHubAndOptions();
+ if (!hub.getIntegration(GlobalHandlers)) {
+ return;
+ }
+ const { msg, url, line, column, error } = data;
+ if (shouldIgnoreOnError() || (error && error.__sentry_own_request__)) {
+ return;
+ }
+
+ const event =
+ error === undefined && isString(msg)
+ ? _eventFromIncompleteOnError(msg, url, line, column)
+ : _enhanceEventWithInitialFrame(
+ eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),
+ url,
+ line,
+ column,
+ );
+
+ event.level = 'error';
+
+ addMechanismAndCapture(hub, error, event, 'onerror');
+ },
+ );
+}
+
+/** JSDoc */
+function _installGlobalOnUnhandledRejectionHandler() {
+ addInstrumentationHandler(
+ 'unhandledrejection',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (e) => {
+ const [hub, stackParser, attachStacktrace] = getHubAndOptions();
+ if (!hub.getIntegration(GlobalHandlers)) {
+ return;
+ }
+ let error = e;
+
+ // dig the object of the rejection out of known event types
+ try {
+ // PromiseRejectionEvents store the object of the rejection under 'reason'
+ // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
+ if ('reason' in e) {
+ error = e.reason;
+ }
+ // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
+ // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
+ // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
+ // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
+ // https://github.com/getsentry/sentry-javascript/issues/2380
+ else if ('detail' in e && 'reason' in e.detail) {
+ error = e.detail.reason;
+ }
+ } catch (_oO) {
+ // no-empty
+ }
+
+ if (shouldIgnoreOnError() || (error && error.__sentry_own_request__)) {
+ return true;
+ }
+
+ const event = isPrimitive(error)
+ ? _eventFromRejectionWithPrimitive(error)
+ : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);
+
+ event.level = 'error';
+
+ addMechanismAndCapture(hub, error, event, 'onunhandledrejection');
+ return;
+ },
+ );
+}
+
+/**
+ * Create an event from a promise rejection where the `reason` is a primitive.
+ *
+ * @param reason: The `reason` property of the promise rejection
+ * @returns An Event object with an appropriate `exception` value
+ */
+function _eventFromRejectionWithPrimitive(reason) {
+ return {
+ exception: {
+ values: [
+ {
+ type: 'UnhandledRejection',
+ // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)
+ value: `Non-Error promise rejection captured with value: ${String(reason)}`,
+ },
+ ],
+ },
+ };
+}
+
+/**
+ * This function creates a stack from an old, error-less onerror handler.
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function _eventFromIncompleteOnError(msg, url, line, column) {
+ const ERROR_TYPES_RE =
+ /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;
+
+ // If 'message' is ErrorEvent, get real message from inside
+ let message = isErrorEvent(msg) ? msg.message : msg;
+ let name = 'Error';
+
+ const groups = message.match(ERROR_TYPES_RE);
+ if (groups) {
+ name = groups[1];
+ message = groups[2];
+ }
+
+ const event = {
+ exception: {
+ values: [
+ {
+ type: name,
+ value: message,
+ },
+ ],
+ },
+ };
+
+ return _enhanceEventWithInitialFrame(event, url, line, column);
+}
+
+/** JSDoc */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function _enhanceEventWithInitialFrame(event, url, line, column) {
+ // event.exception
+ const e = (event.exception = event.exception || {});
+ // event.exception.values
+ const ev = (e.values = e.values || []);
+ // event.exception.values[0]
+ const ev0 = (ev[0] = ev[0] || {});
+ // event.exception.values[0].stacktrace
+ const ev0s = (ev0.stacktrace = ev0.stacktrace || {});
+ // event.exception.values[0].stacktrace.frames
+ const ev0sf = (ev0s.frames = ev0s.frames || []);
+
+ const colno = isNaN(parseInt(column, 10)) ? undefined : column;
+ const lineno = isNaN(parseInt(line, 10)) ? undefined : line;
+ const filename = isString(url) && url.length > 0 ? url : getLocationHref();
+
+ // event.exception.values[0].stacktrace.frames
+ if (ev0sf.length === 0) {
+ ev0sf.push({
+ colno,
+ filename,
+ function: '?',
+ in_app: true,
+ lineno,
+ });
+ }
+
+ return event;
+}
+
+function globalHandlerLog(type) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log(`Global Handler attached: ${type}`);
+}
+
+function addMechanismAndCapture(hub, error, event, type) {
+ addExceptionMechanism(event, {
+ handled: false,
+ type,
+ });
+ hub.captureEvent(event, {
+ originalException: error,
+ });
+}
+
+function getHubAndOptions() {
+ const hub = getCurrentHub();
+ const client = hub.getClient();
+ const options = (client && client.getOptions()) || {
+ stackParser: () => [],
+ attachStacktrace: false,
+ };
+ return [hub, options.stackParser, options.attachStacktrace];
+}
+
+export { GlobalHandlers };
+//# sourceMappingURL=globalhandlers.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/httpcontext.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/httpcontext.js
new file mode 100644
index 0000000..014a182
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/httpcontext.js
@@ -0,0 +1,47 @@
+import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
+import { WINDOW } from '../helpers.js';
+
+/** HttpContext integration collects information about HTTP request headers */
+class HttpContext {constructor() { HttpContext.prototype.__init.call(this); }
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = 'HttpContext';}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = HttpContext.id;}
+
+ /**
+ * @inheritDoc
+ */
+ setupOnce() {
+ addGlobalEventProcessor((event) => {
+ if (getCurrentHub().getIntegration(HttpContext)) {
+ // if none of the information we want exists, don't bother
+ if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {
+ return event;
+ }
+
+ // grab as much info as exists and add it to the event
+ const url = (event.request && event.request.url) || (WINDOW.location && WINDOW.location.href);
+ const { referrer } = WINDOW.document || {};
+ const { userAgent } = WINDOW.navigator || {};
+
+ const headers = {
+ ...(event.request && event.request.headers),
+ ...(referrer && { Referer: referrer }),
+ ...(userAgent && { 'User-Agent': userAgent }),
+ };
+ const request = { ...event.request, ...(url && { url }), headers };
+
+ return { ...event, request };
+ }
+ return event;
+ });
+ }
+} HttpContext.__initStatic();
+
+export { HttpContext };
+//# sourceMappingURL=httpcontext.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/linkederrors.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/linkederrors.js
new file mode 100644
index 0000000..d44a5e9
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/linkederrors.js
@@ -0,0 +1,87 @@
+import { getCurrentHub, addGlobalEventProcessor } from '@sentry/core';
+import { isInstanceOf } from '@sentry/utils';
+import { exceptionFromError } from '../eventbuilder.js';
+
+const DEFAULT_KEY = 'cause';
+const DEFAULT_LIMIT = 5;
+
+/** Adds SDK info to an event. */
+class LinkedErrors {
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = 'LinkedErrors';}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = LinkedErrors.id;}
+
+ /**
+ * @inheritDoc
+ */
+
+ /**
+ * @inheritDoc
+ */
+
+ /**
+ * @inheritDoc
+ */
+ constructor(options = {}) {LinkedErrors.prototype.__init.call(this);
+ this._key = options.key || DEFAULT_KEY;
+ this._limit = options.limit || DEFAULT_LIMIT;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ setupOnce() {
+ const client = getCurrentHub().getClient();
+ if (!client) {
+ return;
+ }
+ addGlobalEventProcessor((event, hint) => {
+ const self = getCurrentHub().getIntegration(LinkedErrors);
+ return self ? _handler(client.getOptions().stackParser, self._key, self._limit, event, hint) : event;
+ });
+ }
+} LinkedErrors.__initStatic();
+
+/**
+ * @inheritDoc
+ */
+function _handler(
+ parser,
+ key,
+ limit,
+ event,
+ hint,
+) {
+ if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) {
+ return event;
+ }
+ const linkedErrors = _walkErrorTree(parser, limit, hint.originalException , key);
+ event.exception.values = [...linkedErrors, ...event.exception.values];
+ return event;
+}
+
+/**
+ * JSDOC
+ */
+function _walkErrorTree(
+ parser,
+ limit,
+ error,
+ key,
+ stack = [],
+) {
+ if (!isInstanceOf(error[key], Error) || stack.length + 1 >= limit) {
+ return stack;
+ }
+ const exception = exceptionFromError(parser, error[key]);
+ return _walkErrorTree(parser, limit, error[key], key, [exception, ...stack]);
+}
+
+export { LinkedErrors, _handler, _walkErrorTree };
+//# sourceMappingURL=linkederrors.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js b/shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js
new file mode 100644
index 0000000..69e112f
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js
@@ -0,0 +1,281 @@
+import { fill, getFunctionName, getOriginalFunction } from '@sentry/utils';
+import { WINDOW, wrap } from '../helpers.js';
+
+const DEFAULT_EVENT_TARGET = [
+ 'EventTarget',
+ 'Window',
+ 'Node',
+ 'ApplicationCache',
+ 'AudioTrackList',
+ 'ChannelMergerNode',
+ 'CryptoOperation',
+ 'EventSource',
+ 'FileReader',
+ 'HTMLUnknownElement',
+ 'IDBDatabase',
+ 'IDBRequest',
+ 'IDBTransaction',
+ 'KeyOperation',
+ 'MediaController',
+ 'MessagePort',
+ 'ModalWindow',
+ 'Notification',
+ 'SVGElementInstance',
+ 'Screen',
+ 'TextTrack',
+ 'TextTrackCue',
+ 'TextTrackList',
+ 'WebSocket',
+ 'WebSocketWorker',
+ 'Worker',
+ 'XMLHttpRequest',
+ 'XMLHttpRequestEventTarget',
+ 'XMLHttpRequestUpload',
+];
+
+/** Wrap timer functions and event targets to catch errors and provide better meta data */
+class TryCatch {
+ /**
+ * @inheritDoc
+ */
+ static __initStatic() {this.id = 'TryCatch';}
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = TryCatch.id;}
+
+ /** JSDoc */
+
+ /**
+ * @inheritDoc
+ */
+ constructor(options) {TryCatch.prototype.__init.call(this);
+ this._options = {
+ XMLHttpRequest: true,
+ eventTarget: true,
+ requestAnimationFrame: true,
+ setInterval: true,
+ setTimeout: true,
+ ...options,
+ };
+ }
+
+ /**
+ * Wrap timer functions and event targets to catch errors
+ * and provide better metadata.
+ */
+ setupOnce() {
+ if (this._options.setTimeout) {
+ fill(WINDOW, 'setTimeout', _wrapTimeFunction);
+ }
+
+ if (this._options.setInterval) {
+ fill(WINDOW, 'setInterval', _wrapTimeFunction);
+ }
+
+ if (this._options.requestAnimationFrame) {
+ fill(WINDOW, 'requestAnimationFrame', _wrapRAF);
+ }
+
+ if (this._options.XMLHttpRequest && 'XMLHttpRequest' in WINDOW) {
+ fill(XMLHttpRequest.prototype, 'send', _wrapXHR);
+ }
+
+ const eventTargetOption = this._options.eventTarget;
+ if (eventTargetOption) {
+ const eventTarget = Array.isArray(eventTargetOption) ? eventTargetOption : DEFAULT_EVENT_TARGET;
+ eventTarget.forEach(_wrapEventTarget);
+ }
+ }
+} TryCatch.__initStatic();
+
+/** JSDoc */
+function _wrapTimeFunction(original) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return function ( ...args) {
+ const originalCallback = args[0];
+ args[0] = wrap(originalCallback, {
+ mechanism: {
+ data: { function: getFunctionName(original) },
+ handled: true,
+ type: 'instrument',
+ },
+ });
+ return original.apply(this, args);
+ };
+}
+
+/** JSDoc */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function _wrapRAF(original) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return function ( callback) {
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ return original.apply(this, [
+ wrap(callback, {
+ mechanism: {
+ data: {
+ function: 'requestAnimationFrame',
+ handler: getFunctionName(original),
+ },
+ handled: true,
+ type: 'instrument',
+ },
+ }),
+ ]);
+ };
+}
+
+/** JSDoc */
+function _wrapXHR(originalSend) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return function ( ...args) {
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ const xhr = this;
+ const xmlHttpRequestProps = ['onload', 'onerror', 'onprogress', 'onreadystatechange'];
+
+ xmlHttpRequestProps.forEach(prop => {
+ if (prop in xhr && typeof xhr[prop] === 'function') {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ fill(xhr, prop, function (original) {
+ const wrapOptions = {
+ mechanism: {
+ data: {
+ function: prop,
+ handler: getFunctionName(original),
+ },
+ handled: true,
+ type: 'instrument',
+ },
+ };
+
+ // If Instrument integration has been called before TryCatch, get the name of original function
+ const originalFunction = getOriginalFunction(original);
+ if (originalFunction) {
+ wrapOptions.mechanism.data.handler = getFunctionName(originalFunction);
+ }
+
+ // Otherwise wrap directly
+ return wrap(original, wrapOptions);
+ });
+ }
+ });
+
+ return originalSend.apply(this, args);
+ };
+}
+
+/** JSDoc */
+function _wrapEventTarget(target) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const globalObject = WINDOW ;
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ const proto = globalObject[target] && globalObject[target].prototype;
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
+ if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
+ return;
+ }
+
+ fill(proto, 'addEventListener', function (original)
+
+ {
+ return function (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
+ eventName,
+ fn,
+ options,
+ ) {
+ try {
+ if (typeof fn.handleEvent === 'function') {
+ // ESlint disable explanation:
+ // First, it is generally safe to call `wrap` with an unbound function. Furthermore, using `.bind()` would
+ // introduce a bug here, because bind returns a new function that doesn't have our
+ // flags(like __sentry_original__) attached. `wrap` checks for those flags to avoid unnecessary wrapping.
+ // Without those flags, every call to addEventListener wraps the function again, causing a memory leak.
+ // eslint-disable-next-line @typescript-eslint/unbound-method
+ fn.handleEvent = wrap(fn.handleEvent, {
+ mechanism: {
+ data: {
+ function: 'handleEvent',
+ handler: getFunctionName(fn),
+ target,
+ },
+ handled: true,
+ type: 'instrument',
+ },
+ });
+ }
+ } catch (err) {
+ // can sometimes get 'Permission denied to access property "handle Event'
+ }
+
+ return original.apply(this, [
+ eventName,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ wrap(fn , {
+ mechanism: {
+ data: {
+ function: 'addEventListener',
+ handler: getFunctionName(fn),
+ target,
+ },
+ handled: true,
+ type: 'instrument',
+ },
+ }),
+ options,
+ ]);
+ };
+ });
+
+ fill(
+ proto,
+ 'removeEventListener',
+ function (
+ originalRemoveEventListener,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ) {
+ return function (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
+ eventName,
+ fn,
+ options,
+ ) {
+ /**
+ * There are 2 possible scenarios here:
+ *
+ * 1. Someone passes a callback, which was attached prior to Sentry initialization, or by using unmodified
+ * method, eg. `document.addEventListener.call(el, name, handler). In this case, we treat this function
+ * as a pass-through, and call original `removeEventListener` with it.
+ *
+ * 2. Someone passes a callback, which was attached after Sentry was initialized, which means that it was using
+ * our wrapped version of `addEventListener`, which internally calls `wrap` helper.
+ * This helper "wraps" whole callback inside a try/catch statement, and attached appropriate metadata to it,
+ * in order for us to make a distinction between wrapped/non-wrapped functions possible.
+ * If a function was wrapped, it has additional property of `__sentry_wrapped__`, holding the handler.
+ *
+ * When someone adds a handler prior to initialization, and then do it again, but after,
+ * then we have to detach both of them. Otherwise, if we'd detach only wrapped one, it'd be impossible
+ * to get rid of the initial handler and it'd stick there forever.
+ */
+ const wrappedEventHandler = fn ;
+ try {
+ const originalEventHandler = wrappedEventHandler && wrappedEventHandler.__sentry_wrapped__;
+ if (originalEventHandler) {
+ originalRemoveEventListener.call(this, eventName, originalEventHandler, options);
+ }
+ } catch (e) {
+ // ignore, accessing __sentry_wrapped__ will throw in some Selenium environments
+ }
+ return originalRemoveEventListener.call(this, eventName, wrappedEventHandler, options);
+ };
+ },
+ );
+}
+
+export { TryCatch };
+//# sourceMappingURL=trycatch.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/profiling/hubextensions.js b/shared/logger/node_modules/@sentry/browser/esm/profiling/hubextensions.js
new file mode 100644
index 0000000..c1cd92d
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/profiling/hubextensions.js
@@ -0,0 +1,240 @@
+import { getCurrentHub } from '@sentry/core';
+import { logger, uuid4 } from '@sentry/utils';
+import { WINDOW } from '../helpers.js';
+import { isValidSampleRate, addProfileToMap } from './utils.js';
+
+/* eslint-disable complexity */
+
+const MAX_PROFILE_DURATION_MS = 30000;
+// Keep a flag value to avoid re-initializing the profiler constructor. If it fails
+// once, it will always fail and this allows us to early return.
+let PROFILING_CONSTRUCTOR_FAILED = false;
+
+/**
+ * Check if profiler constructor is available.
+ * @param maybeProfiler
+ */
+function isJSProfilerSupported(maybeProfiler) {
+ return typeof maybeProfiler === 'function';
+}
+
+/**
+ * Safety wrapper for startTransaction for the unlikely case that transaction starts before tracing is imported -
+ * if that happens we want to avoid throwing an error from profiling code.
+ * see https://github.com/getsentry/sentry-javascript/issues/4731.
+ *
+ * @experimental
+ */
+function onProfilingStartRouteTransaction(transaction) {
+ if (!transaction) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log('[Profiling] Transaction is undefined, skipping profiling');
+ }
+ return transaction;
+ }
+
+ return wrapTransactionWithProfiling(transaction);
+}
+
+/**
+ * Wraps startTransaction and stopTransaction with profiling related logic.
+ * startProfiling is called after the call to startTransaction in order to avoid our own code from
+ * being profiled. Because of that same reason, stopProfiling is called before the call to stopTransaction.
+ */
+function wrapTransactionWithProfiling(transaction) {
+ // Feature support check first
+ const JSProfilerConstructor = WINDOW.Profiler;
+
+ if (!isJSProfilerSupported(JSProfilerConstructor)) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(
+ '[Profiling] Profiling is not supported by this browser, Profiler interface missing on window object.',
+ );
+ }
+ return transaction;
+ }
+
+ // If constructor failed once, it will always fail, so we can early return.
+ if (PROFILING_CONSTRUCTOR_FAILED) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log('[Profiling] Profiling has been disabled for the duration of the current user session.');
+ }
+ return transaction;
+ }
+
+ const client = getCurrentHub().getClient();
+ const options = client && client.getOptions();
+ if (!options) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Profiling] Profiling disabled, no options found.');
+ return transaction;
+ }
+
+ // @ts-ignore profilesSampleRate is not part of the browser options yet
+ const profilesSampleRate = options.profilesSampleRate;
+
+ // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
+ // only valid values are booleans or numbers between 0 and 1.)
+ if (!isValidSampleRate(profilesSampleRate)) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('[Profiling] Discarding profile because of invalid sample rate.');
+ return transaction;
+ }
+
+ // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped
+ if (!profilesSampleRate) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log(
+ '[Profiling] Discarding profile because a negative sampling decision was inherited or profileSampleRate is set to 0',
+ );
+ return transaction;
+ }
+
+ // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is
+ // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.
+ const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;
+ // Check if we should sample this profile
+ if (!sampled) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log(
+ `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(
+ profilesSampleRate,
+ )})`,
+ );
+ return transaction;
+ }
+
+ // From initial testing, it seems that the minimum value for sampleInterval is 10ms.
+ const samplingIntervalMS = 10;
+ // Start the profiler
+ const maxSamples = Math.floor(MAX_PROFILE_DURATION_MS / samplingIntervalMS);
+ let profiler;
+
+ // Attempt to initialize the profiler constructor, if it fails, we disable profiling for the current user session.
+ // This is likely due to a missing 'Document-Policy': 'js-profiling' header. We do not want to throw an error if this happens
+ // as we risk breaking the user's application, so just disable profiling and log an error.
+ try {
+ profiler = new JSProfilerConstructor({ sampleInterval: samplingIntervalMS, maxBufferSize: maxSamples });
+ } catch (e) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(
+ "[Profiling] Failed to initialize the Profiling constructor, this is likely due to a missing 'Document-Policy': 'js-profiling' header.",
+ );
+ logger.log('[Profiling] Disabling profiling for current user session.');
+ }
+ PROFILING_CONSTRUCTOR_FAILED = true;
+ }
+
+ // We failed to construct the profiler, fallback to original transaction - there is no need to log
+ // anything as we already did that in the try/catch block.
+ if (!profiler) {
+ return transaction;
+ }
+
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(`[Profiling] started profiling transaction: ${transaction.name || transaction.description}`);
+ }
+
+ // We create "unique" transaction names to avoid concurrent transactions with same names
+ // from being ignored by the profiler. From here on, only this transaction name should be used when
+ // calling the profiler methods. Note: we log the original name to the user to avoid confusion.
+ const profileId = uuid4();
+
+ /**
+ * Idempotent handler for profile stop
+ */
+ async function onProfileHandler() {
+ // Check if the profile exists and return it the behavior has to be idempotent as users may call transaction.finish multiple times.
+ if (!transaction) {
+ return null;
+ }
+ // Satisfy the type checker, but profiler will always be defined here.
+ if (!profiler) {
+ return null;
+ }
+
+ // This is temporary - we will use the collected span data to evaluate
+ // if deferring txn.finish until profiler resolves is a viable approach.
+ const stopProfilerSpan = transaction.startChild({ description: 'profiler.stop', op: 'profiler' });
+
+ return profiler
+ .stop()
+ .then((p) => {
+ stopProfilerSpan.finish();
+
+ if (maxDurationTimeoutID) {
+ WINDOW.clearTimeout(maxDurationTimeoutID);
+ maxDurationTimeoutID = undefined;
+ }
+
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(`[Profiling] stopped profiling of transaction: ${transaction.name || transaction.description}`);
+ }
+
+ // In case of an overlapping transaction, stopProfiling may return null and silently ignore the overlapping profile.
+ if (!p) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(
+ `[Profiling] profiler returned null profile for: ${transaction.name || transaction.description}`,
+ 'this may indicate an overlapping transaction or a call to stopProfiling with a profile title that was never started',
+ );
+ }
+ return null;
+ }
+
+ addProfileToMap(profileId, p);
+ return null;
+ })
+ .catch(error => {
+ stopProfilerSpan.finish();
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log('[Profiling] error while stopping profiler:', error);
+ }
+ return null;
+ });
+ }
+
+ // Enqueue a timeout to prevent profiles from running over max duration.
+ let maxDurationTimeoutID = WINDOW.setTimeout(() => {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(
+ '[Profiling] max profile duration elapsed, stopping profiling for:',
+ transaction.name || transaction.description,
+ );
+ }
+ // If the timeout exceeds, we want to stop profiling, but not finish the transaction
+ void onProfileHandler();
+ }, MAX_PROFILE_DURATION_MS);
+
+ // We need to reference the original finish call to avoid creating an infinite loop
+ const originalFinish = transaction.finish.bind(transaction);
+
+ /**
+ * Wraps startTransaction and stopTransaction with profiling related logic.
+ * startProfiling is called after the call to startTransaction in order to avoid our own code from
+ * being profiled. Because of that same reason, stopProfiling is called before the call to stopTransaction.
+ */
+ function profilingWrappedTransactionFinish() {
+ if (!transaction) {
+ return originalFinish();
+ }
+ // onProfileHandler should always return the same profile even if this is called multiple times.
+ // Always call onProfileHandler to ensure stopProfiling is called and the timeout is cleared.
+ void onProfileHandler().then(
+ () => {
+ transaction.setContext('profile', { profile_id: profileId });
+ originalFinish();
+ },
+ () => {
+ // If onProfileHandler fails, we still want to call the original finish method.
+ originalFinish();
+ },
+ );
+
+ return transaction;
+ }
+
+ transaction.finish = profilingWrappedTransactionFinish;
+ return transaction;
+}
+
+export { MAX_PROFILE_DURATION_MS, onProfilingStartRouteTransaction, wrapTransactionWithProfiling };
+//# sourceMappingURL=hubextensions.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/profiling/integration.js b/shared/logger/node_modules/@sentry/browser/esm/profiling/integration.js
new file mode 100644
index 0000000..f09e4ed
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/profiling/integration.js
@@ -0,0 +1,81 @@
+import { logger } from '@sentry/utils';
+import { wrapTransactionWithProfiling } from './hubextensions.js';
+import { PROFILE_MAP, findProfiledTransactionsFromEnvelope, createProfilingEvent, addProfilesToEnvelope } from './utils.js';
+
+/**
+ * Browser profiling integration. Stores any event that has contexts["profile"]["profile_id"]
+ * This exists because we do not want to await async profiler.stop calls as transaction.finish is called
+ * in a synchronous context. Instead, we handle sending the profile async from the promise callback and
+ * rely on being able to pull the event from the cache when we need to construct the envelope. This makes the
+ * integration less reliable as we might be dropping profiles when the cache is full.
+ *
+ * @experimental
+ */
+class BrowserProfilingIntegration {constructor() { BrowserProfilingIntegration.prototype.__init.call(this);BrowserProfilingIntegration.prototype.__init2.call(this); }
+ __init() {this.name = 'BrowserProfilingIntegration';}
+ __init2() {this.getCurrentHub = undefined;}
+
+ /**
+ * @inheritDoc
+ */
+ setupOnce(addGlobalEventProcessor, getCurrentHub) {
+ this.getCurrentHub = getCurrentHub;
+ const client = this.getCurrentHub().getClient() ;
+
+ if (client && typeof client.on === 'function') {
+ client.on('startTransaction', (transaction) => {
+ wrapTransactionWithProfiling(transaction);
+ });
+
+ client.on('beforeEnvelope', (envelope) => {
+ // if not profiles are in queue, there is nothing to add to the envelope.
+ if (!PROFILE_MAP['size']) {
+ return;
+ }
+
+ const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);
+ if (!profiledTransactionEvents.length) {
+ return;
+ }
+
+ const profilesToAddToEnvelope = [];
+
+ for (const profiledTransaction of profiledTransactionEvents) {
+ const context = profiledTransaction && profiledTransaction.contexts;
+ const profile_id = context && context['profile'] && (context['profile']['profile_id'] );
+
+ if (!profile_id) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log('[Profiling] cannot find profile for a transaction without a profile context');
+ continue;
+ }
+
+ // Remove the profile from the transaction context before sending, relay will take care of the rest.
+ if (context && context['profile']) {
+ delete context.profile;
+ }
+
+ const profile = PROFILE_MAP.get(profile_id);
+ if (!profile) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
+ continue;
+ }
+
+ PROFILE_MAP.delete(profile_id);
+ const profileEvent = createProfilingEvent(profile_id, profile, profiledTransaction );
+
+ if (profileEvent) {
+ profilesToAddToEnvelope.push(profileEvent);
+ }
+ }
+
+ addProfilesToEnvelope(envelope, profilesToAddToEnvelope);
+ });
+ } else {
+ logger.warn('[Profiling] Client does not support hooks, profiling will be disabled');
+ }
+ }
+}
+
+export { BrowserProfilingIntegration };
+//# sourceMappingURL=integration.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/profiling/utils.js b/shared/logger/node_modules/@sentry/browser/esm/profiling/utils.js
new file mode 100644
index 0000000..e8beae2
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/profiling/utils.js
@@ -0,0 +1,438 @@
+import { DEFAULT_ENVIRONMENT, getCurrentHub } from '@sentry/core';
+import { forEachEnvelopeItem, logger, uuid4, GLOBAL_OBJ } from '@sentry/utils';
+import { WINDOW } from '../helpers.js';
+
+/* eslint-disable max-lines */
+
+const MS_TO_NS = 1e6;
+// Use 0 as main thread id which is identical to threadId in node:worker_threads
+// where main logs 0 and workers seem to log in increments of 1
+const THREAD_ID_STRING = String(0);
+const THREAD_NAME = 'main';
+
+// Machine properties (eval only once)
+let OS_PLATFORM = '';
+let OS_PLATFORM_VERSION = '';
+let OS_ARCH = '';
+let OS_BROWSER = (WINDOW.navigator && WINDOW.navigator.userAgent) || '';
+let OS_MODEL = '';
+const OS_LOCALE =
+ (WINDOW.navigator && WINDOW.navigator.language) ||
+ (WINDOW.navigator && WINDOW.navigator.languages && WINDOW.navigator.languages[0]) ||
+ '';
+
+function isUserAgentData(data) {
+ return typeof data === 'object' && data !== null && 'getHighEntropyValues' in data;
+}
+
+// @ts-ignore userAgentData is not part of the navigator interface yet
+const userAgentData = WINDOW.navigator && WINDOW.navigator.userAgentData;
+
+if (isUserAgentData(userAgentData)) {
+ userAgentData
+ .getHighEntropyValues(['architecture', 'model', 'platform', 'platformVersion', 'fullVersionList'])
+ .then((ua) => {
+ OS_PLATFORM = ua.platform || '';
+ OS_ARCH = ua.architecture || '';
+ OS_MODEL = ua.model || '';
+ OS_PLATFORM_VERSION = ua.platformVersion || '';
+
+ if (ua.fullVersionList && ua.fullVersionList.length > 0) {
+ const firstUa = ua.fullVersionList[ua.fullVersionList.length - 1];
+ OS_BROWSER = `${firstUa.brand} ${firstUa.version}`;
+ }
+ })
+ .catch(e => void e);
+}
+
+function isProcessedJSSelfProfile(profile) {
+ return !('thread_metadata' in profile);
+}
+
+// Enriches the profile with threadId of the current thread.
+// This is done in node as we seem to not be able to get the info from C native code.
+/**
+ *
+ */
+function enrichWithThreadInformation(profile) {
+ if (!isProcessedJSSelfProfile(profile)) {
+ return profile;
+ }
+
+ return convertJSSelfProfileToSampledFormat(profile);
+}
+
+// Profile is marked as optional because it is deleted from the metadata
+// by the integration before the event is processed by other integrations.
+
+function getTraceId(event) {
+ const traceId = event && event.contexts && event.contexts['trace'] && event.contexts['trace']['trace_id'];
+ // Log a warning if the profile has an invalid traceId (should be uuidv4).
+ // All profiles and transactions are rejected if this is the case and we want to
+ // warn users that this is happening if they enable debug flag
+ if (typeof traceId === 'string' && traceId.length !== 32) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log(`[Profiling] Invalid traceId: ${traceId} on profiled event`);
+ }
+ }
+ if (typeof traceId !== 'string') {
+ return '';
+ }
+
+ return traceId;
+}
+/**
+ * Creates a profiling event envelope from a Sentry event. If profile does not pass
+ * validation, returns null.
+ * @param event
+ * @param dsn
+ * @param metadata
+ * @param tunnel
+ * @returns {EventEnvelope | null}
+ */
+
+/**
+ * Creates a profiling event envelope from a Sentry event.
+ */
+function createProfilePayload(
+ event,
+ processedProfile,
+ profile_id,
+) {
+ if (event.type !== 'transaction') {
+ // createProfilingEventEnvelope should only be called for transactions,
+ // we type guard this behavior with isProfiledTransactionEvent.
+ throw new TypeError('Profiling events may only be attached to transactions, this should never occur.');
+ }
+
+ if (processedProfile === undefined || processedProfile === null) {
+ throw new TypeError(
+ `Cannot construct profiling event envelope without a valid profile. Got ${processedProfile} instead.`,
+ );
+ }
+
+ const traceId = getTraceId(event);
+ const enrichedThreadProfile = enrichWithThreadInformation(processedProfile);
+ const transactionStartMs = typeof event.start_timestamp === 'number' ? event.start_timestamp * 1000 : Date.now();
+ const transactionEndMs = typeof event.timestamp === 'number' ? event.timestamp * 1000 : Date.now();
+
+ const profile = {
+ event_id: profile_id,
+ timestamp: new Date(transactionStartMs).toISOString(),
+ platform: 'javascript',
+ version: '1',
+ release: event.release || '',
+ environment: event.environment || DEFAULT_ENVIRONMENT,
+ runtime: {
+ name: 'javascript',
+ version: WINDOW.navigator.userAgent,
+ },
+ os: {
+ name: OS_PLATFORM,
+ version: OS_PLATFORM_VERSION,
+ build_number: OS_BROWSER,
+ },
+ device: {
+ locale: OS_LOCALE,
+ model: OS_MODEL,
+ manufacturer: OS_BROWSER,
+ architecture: OS_ARCH,
+ is_emulator: false,
+ },
+ debug_meta: {
+ images: applyDebugMetadata(processedProfile.resources),
+ },
+ profile: enrichedThreadProfile,
+ transactions: [
+ {
+ name: event.transaction || '',
+ id: event.event_id || uuid4(),
+ trace_id: traceId,
+ active_thread_id: THREAD_ID_STRING,
+ relative_start_ns: '0',
+ relative_end_ns: ((transactionEndMs - transactionStartMs) * 1e6).toFixed(0),
+ },
+ ],
+ };
+
+ return profile;
+}
+
+/**
+ * Converts a JSSelfProfile to a our sampled format.
+ * Does not currently perform stack indexing.
+ */
+function convertJSSelfProfileToSampledFormat(input) {
+ let EMPTY_STACK_ID = undefined;
+ let STACK_ID = 0;
+
+ // Initialize the profile that we will fill with data
+ const profile = {
+ samples: [],
+ stacks: [],
+ frames: [],
+ thread_metadata: {
+ [THREAD_ID_STRING]: { name: THREAD_NAME },
+ },
+ };
+
+ if (!input.samples.length) {
+ return profile;
+ }
+
+ // We assert samples.length > 0 above and timestamp should always be present
+ const start = input.samples[0].timestamp;
+
+ for (let i = 0; i < input.samples.length; i++) {
+ const jsSample = input.samples[i];
+
+ // If sample has no stack, add an empty sample
+ if (jsSample.stackId === undefined) {
+ if (EMPTY_STACK_ID === undefined) {
+ EMPTY_STACK_ID = STACK_ID;
+ profile.stacks[EMPTY_STACK_ID] = [];
+ STACK_ID++;
+ }
+
+ profile['samples'][i] = {
+ // convert ms timestamp to ns
+ elapsed_since_start_ns: ((jsSample.timestamp - start) * MS_TO_NS).toFixed(0),
+ stack_id: EMPTY_STACK_ID,
+ thread_id: THREAD_ID_STRING,
+ };
+ continue;
+ }
+
+ let stackTop = input.stacks[jsSample.stackId];
+
+ // Functions in top->down order (root is last)
+ // We follow the stackTop.parentId trail and collect each visited frameId
+ const stack = [];
+
+ while (stackTop) {
+ stack.push(stackTop.frameId);
+
+ const frame = input.frames[stackTop.frameId];
+
+ // If our frame has not been indexed yet, index it
+ if (profile.frames[stackTop.frameId] === undefined) {
+ profile.frames[stackTop.frameId] = {
+ function: frame.name,
+ file: frame.resourceId ? input.resources[frame.resourceId] : undefined,
+ line: frame.line,
+ column: frame.column,
+ };
+ }
+
+ stackTop = stackTop.parentId === undefined ? undefined : input.stacks[stackTop.parentId];
+ }
+
+ const sample = {
+ // convert ms timestamp to ns
+ elapsed_since_start_ns: ((jsSample.timestamp - start) * MS_TO_NS).toFixed(0),
+ stack_id: STACK_ID,
+ thread_id: THREAD_ID_STRING,
+ };
+
+ profile['stacks'][STACK_ID] = stack;
+ profile['samples'][i] = sample;
+ STACK_ID++;
+ }
+
+ return profile;
+}
+
+/**
+ * Adds items to envelope if they are not already present - mutates the envelope.
+ * @param envelope
+ */
+function addProfilesToEnvelope(envelope, profiles) {
+ if (!profiles.length) {
+ return envelope;
+ }
+
+ for (const profile of profiles) {
+ // @ts-ignore untyped envelope
+ envelope[1].push([{ type: 'profile' }, profile]);
+ }
+ return envelope;
+}
+
+/**
+ * Finds transactions with profile_id context in the envelope
+ * @param envelope
+ * @returns
+ */
+function findProfiledTransactionsFromEnvelope(envelope) {
+ const events = [];
+
+ forEachEnvelopeItem(envelope, (item, type) => {
+ if (type !== 'transaction') {
+ return;
+ }
+
+ for (let j = 1; j < item.length; j++) {
+ const event = item[j] ;
+
+ if (event && event.contexts && event.contexts['profile'] && event.contexts['profile']['profile_id']) {
+ events.push(item[j] );
+ }
+ }
+ });
+
+ return events;
+}
+
+const debugIdStackParserCache = new WeakMap();
+/**
+ * Applies debug meta data to an event from a list of paths to resources (sourcemaps)
+ */
+function applyDebugMetadata(resource_paths) {
+ const debugIdMap = GLOBAL_OBJ._sentryDebugIds;
+
+ if (!debugIdMap) {
+ return [];
+ }
+
+ const hub = getCurrentHub();
+ if (!hub) {
+ return [];
+ }
+ const client = hub.getClient();
+ if (!client) {
+ return [];
+ }
+ const options = client.getOptions();
+ if (!options) {
+ return [];
+ }
+ const stackParser = options.stackParser;
+ if (!stackParser) {
+ return [];
+ }
+
+ let debugIdStackFramesCache;
+ const cachedDebugIdStackFrameCache = debugIdStackParserCache.get(stackParser);
+ if (cachedDebugIdStackFrameCache) {
+ debugIdStackFramesCache = cachedDebugIdStackFrameCache;
+ } else {
+ debugIdStackFramesCache = new Map();
+ debugIdStackParserCache.set(stackParser, debugIdStackFramesCache);
+ }
+
+ // Build a map of filename -> debug_id
+ const filenameDebugIdMap = Object.keys(debugIdMap).reduce((acc, debugIdStackTrace) => {
+ let parsedStack;
+
+ const cachedParsedStack = debugIdStackFramesCache.get(debugIdStackTrace);
+ if (cachedParsedStack) {
+ parsedStack = cachedParsedStack;
+ } else {
+ parsedStack = stackParser(debugIdStackTrace);
+ debugIdStackFramesCache.set(debugIdStackTrace, parsedStack);
+ }
+
+ for (let i = parsedStack.length - 1; i >= 0; i--) {
+ const stackFrame = parsedStack[i];
+ const file = stackFrame && stackFrame.filename;
+
+ if (stackFrame && file) {
+ acc[file] = debugIdMap[debugIdStackTrace] ;
+ break;
+ }
+ }
+ return acc;
+ }, {});
+
+ const images = [];
+ for (const path of resource_paths) {
+ if (path && filenameDebugIdMap[path]) {
+ images.push({
+ type: 'sourcemap',
+ code_file: path,
+ debug_id: filenameDebugIdMap[path] ,
+ });
+ }
+ }
+
+ return images;
+}
+
+/**
+ * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
+ */
+function isValidSampleRate(rate) {
+ // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
+ if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(
+ `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(
+ rate,
+ )} of type ${JSON.stringify(typeof rate)}.`,
+ );
+ return false;
+ }
+
+ // Boolean sample rates are always valid
+ if (rate === true || rate === false) {
+ return true;
+ }
+
+ // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false
+ if (rate < 0 || rate > 1) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);
+ return false;
+ }
+ return true;
+}
+
+function isValidProfile(profile) {
+ if (profile.samples.length < 2) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ // Log a warning if the profile has less than 2 samples so users can know why
+ // they are not seeing any profiling data and we cant avoid the back and forth
+ // of asking them to provide us with a dump of the profile data.
+ logger.log('[Profiling] Discarding profile because it contains less than 2 samples');
+ }
+ return false;
+ }
+
+ if (!profile.frames.length) {
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ logger.log('[Profiling] Discarding profile because it contains no frames');
+ }
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Creates a profiling envelope item, if the profile does not pass validation, returns null.
+ * @param event
+ * @returns {Profile | null}
+ */
+function createProfilingEvent(profile_id, profile, event) {
+ if (!isValidProfile(profile)) {
+ return null;
+ }
+
+ return createProfilePayload(event, profile, profile_id);
+}
+
+const PROFILE_MAP = new Map();
+/**
+ *
+ */
+function addProfileToMap(profile_id, profile) {
+ PROFILE_MAP.set(profile_id, profile);
+
+ if (PROFILE_MAP.size > 30) {
+ const last = PROFILE_MAP.keys().next().value;
+ PROFILE_MAP.delete(last);
+ }
+}
+
+export { PROFILE_MAP, addProfileToMap, addProfilesToEnvelope, applyDebugMetadata, convertJSSelfProfileToSampledFormat, createProfilePayload, createProfilingEvent, enrichWithThreadInformation, findProfiledTransactionsFromEnvelope, isValidSampleRate };
+//# sourceMappingURL=utils.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/sdk.js b/shared/logger/node_modules/@sentry/browser/esm/sdk.js
new file mode 100644
index 0000000..2b4edf2
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/sdk.js
@@ -0,0 +1,293 @@
+import { Integrations, getIntegrationsToSetup, initAndBind, getReportDialogEndpoint, getCurrentHub } from '@sentry/core';
+import { stackParserFromStackParserOptions, supportsFetch, logger, resolvedSyncPromise, addInstrumentationHandler } from '@sentry/utils';
+import { BrowserClient } from './client.js';
+import { WINDOW, wrap as wrap$1 } from './helpers.js';
+import { GlobalHandlers } from './integrations/globalhandlers.js';
+import { TryCatch } from './integrations/trycatch.js';
+import { Breadcrumbs } from './integrations/breadcrumbs.js';
+import { LinkedErrors } from './integrations/linkederrors.js';
+import { HttpContext } from './integrations/httpcontext.js';
+import { Dedupe } from './integrations/dedupe.js';
+import { defaultStackParser } from './stack-parsers.js';
+import { makeFetchTransport } from './transports/fetch.js';
+import { makeXHRTransport } from './transports/xhr.js';
+
+const defaultIntegrations = [
+ new Integrations.InboundFilters(),
+ new Integrations.FunctionToString(),
+ new TryCatch(),
+ new Breadcrumbs(),
+ new GlobalHandlers(),
+ new LinkedErrors(),
+ new Dedupe(),
+ new HttpContext(),
+];
+
+/**
+ * A magic string that build tooling can leverage in order to inject a release value into the SDK.
+ */
+
+/**
+ * The Sentry Browser SDK Client.
+ *
+ * To use this SDK, call the {@link init} function as early as possible when
+ * loading the web page. To set context information or send manual events, use
+ * the provided methods.
+ *
+ * @example
+ *
+ * ```
+ *
+ * import { init } from '@sentry/browser';
+ *
+ * init({
+ * dsn: '__DSN__',
+ * // ...
+ * });
+ * ```
+ *
+ * @example
+ * ```
+ *
+ * import { configureScope } from '@sentry/browser';
+ * configureScope((scope: Scope) => {
+ * scope.setExtra({ battery: 0.7 });
+ * scope.setTag({ user_mode: 'admin' });
+ * scope.setUser({ id: '4711' });
+ * });
+ * ```
+ *
+ * @example
+ * ```
+ *
+ * import { addBreadcrumb } from '@sentry/browser';
+ * addBreadcrumb({
+ * message: 'My Breadcrumb',
+ * // ...
+ * });
+ * ```
+ *
+ * @example
+ *
+ * ```
+ *
+ * import * as Sentry from '@sentry/browser';
+ * Sentry.captureMessage('Hello, world!');
+ * Sentry.captureException(new Error('Good bye'));
+ * Sentry.captureEvent({
+ * message: 'Manual',
+ * stacktrace: [
+ * // ...
+ * ],
+ * });
+ * ```
+ *
+ * @see {@link BrowserOptions} for documentation on configuration options.
+ */
+function init(options = {}) {
+ if (options.defaultIntegrations === undefined) {
+ options.defaultIntegrations = defaultIntegrations;
+ }
+ if (options.release === undefined) {
+ // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value
+ if (typeof __SENTRY_RELEASE__ === 'string') {
+ options.release = __SENTRY_RELEASE__;
+ }
+
+ // This supports the variable that sentry-webpack-plugin injects
+ if (WINDOW.SENTRY_RELEASE && WINDOW.SENTRY_RELEASE.id) {
+ options.release = WINDOW.SENTRY_RELEASE.id;
+ }
+ }
+ if (options.autoSessionTracking === undefined) {
+ options.autoSessionTracking = true;
+ }
+ if (options.sendClientReports === undefined) {
+ options.sendClientReports = true;
+ }
+
+ const clientOptions = {
+ ...options,
+ stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
+ integrations: getIntegrationsToSetup(options),
+ transport: options.transport || (supportsFetch() ? makeFetchTransport : makeXHRTransport),
+ };
+
+ initAndBind(BrowserClient, clientOptions);
+
+ if (options.autoSessionTracking) {
+ startSessionTracking();
+ }
+}
+
+/**
+ * Present the user with a report dialog.
+ *
+ * @param options Everything is optional, we try to fetch all info need from the global scope.
+ */
+function showReportDialog(options = {}, hub = getCurrentHub()) {
+ // doesn't work without a document (React Native)
+ if (!WINDOW.document) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('Global document not defined in showReportDialog call');
+ return;
+ }
+
+ const { client, scope } = hub.getStackTop();
+ const dsn = options.dsn || (client && client.getDsn());
+ if (!dsn) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('DSN not configured for showReportDialog call');
+ return;
+ }
+
+ if (scope) {
+ options.user = {
+ ...scope.getUser(),
+ ...options.user,
+ };
+ }
+
+ if (!options.eventId) {
+ options.eventId = hub.lastEventId();
+ }
+
+ const script = WINDOW.document.createElement('script');
+ script.async = true;
+ script.src = getReportDialogEndpoint(dsn, options);
+
+ if (options.onLoad) {
+ script.onload = options.onLoad;
+ }
+
+ const injectionPoint = WINDOW.document.head || WINDOW.document.body;
+ if (injectionPoint) {
+ injectionPoint.appendChild(script);
+ } else {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('Not injecting report dialog. No injection point found in HTML');
+ }
+}
+
+/**
+ * This is the getter for lastEventId.
+ *
+ * @returns The last event id of a captured event.
+ */
+function lastEventId() {
+ return getCurrentHub().lastEventId();
+}
+
+/**
+ * This function is here to be API compatible with the loader.
+ * @hidden
+ */
+function forceLoad() {
+ // Noop
+}
+
+/**
+ * This function is here to be API compatible with the loader.
+ * @hidden
+ */
+function onLoad(callback) {
+ callback();
+}
+
+/**
+ * Call `flush()` on the current client, if there is one. See {@link Client.flush}.
+ *
+ * @param timeout Maximum time in ms the client should wait to flush its event queue. Omitting this parameter will cause
+ * the client to wait until all events are sent before resolving the promise.
+ * @returns A promise which resolves to `true` if the queue successfully drains before the timeout, or `false` if it
+ * doesn't (or if there's no client defined).
+ */
+function flush(timeout) {
+ const client = getCurrentHub().getClient();
+ if (client) {
+ return client.flush(timeout);
+ }
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('Cannot flush events. No client defined.');
+ return resolvedSyncPromise(false);
+}
+
+/**
+ * Call `close()` on the current client, if there is one. See {@link Client.close}.
+ *
+ * @param timeout Maximum time in ms the client should wait to flush its event queue before shutting down. Omitting this
+ * parameter will cause the client to wait until all events are sent before disabling itself.
+ * @returns A promise which resolves to `true` if the queue successfully drains before the timeout, or `false` if it
+ * doesn't (or if there's no client defined).
+ */
+function close(timeout) {
+ const client = getCurrentHub().getClient();
+ if (client) {
+ return client.close(timeout);
+ }
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('Cannot flush events and disable SDK. No client defined.');
+ return resolvedSyncPromise(false);
+}
+
+/**
+ * Wrap code within a try/catch block so the SDK is able to capture errors.
+ *
+ * @param fn A function to wrap.
+ *
+ * @returns The result of wrapped function call.
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function wrap(fn) {
+ return wrap$1(fn)();
+}
+
+function startSessionOnHub(hub) {
+ hub.startSession({ ignoreDuration: true });
+ hub.captureSession();
+}
+
+/**
+ * Enable automatic Session Tracking for the initial page load.
+ */
+function startSessionTracking() {
+ if (typeof WINDOW.document === 'undefined') {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.');
+ return;
+ }
+
+ const hub = getCurrentHub();
+
+ // The only way for this to be false is for there to be a version mismatch between @sentry/browser (>= 6.0.0) and
+ // @sentry/hub (< 5.27.0). In the simple case, there won't ever be such a mismatch, because the two packages are
+ // pinned at the same version in package.json, but there are edge cases where it's possible. See
+ // https://github.com/getsentry/sentry-javascript/issues/3207 and
+ // https://github.com/getsentry/sentry-javascript/issues/3234 and
+ // https://github.com/getsentry/sentry-javascript/issues/3278.
+ if (!hub.captureSession) {
+ return;
+ }
+
+ // The session duration for browser sessions does not track a meaningful
+ // concept that can be used as a metric.
+ // Automatically captured sessions are akin to page views, and thus we
+ // discard their duration.
+ startSessionOnHub(hub);
+
+ // We want to create a session for every navigation as well
+ addInstrumentationHandler('history', ({ from, to }) => {
+ // Don't create an additional session for the initial route or if the location did not change
+ if (!(from === undefined || from === to)) {
+ startSessionOnHub(getCurrentHub());
+ }
+ });
+}
+
+/**
+ * Captures user feedback and sends it to Sentry.
+ */
+function captureUserFeedback(feedback) {
+ const client = getCurrentHub().getClient();
+ if (client) {
+ client.captureUserFeedback(feedback);
+ }
+}
+
+export { captureUserFeedback, close, defaultIntegrations, flush, forceLoad, init, lastEventId, onLoad, showReportDialog, wrap };
+//# sourceMappingURL=sdk.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/stack-parsers.js b/shared/logger/node_modules/@sentry/browser/esm/stack-parsers.js
new file mode 100644
index 0000000..4f3da89
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/stack-parsers.js
@@ -0,0 +1,168 @@
+import { createStackParser } from '@sentry/utils';
+
+// global reference to slice
+const UNKNOWN_FUNCTION = '?';
+
+const OPERA10_PRIORITY = 10;
+const OPERA11_PRIORITY = 20;
+const CHROME_PRIORITY = 30;
+const WINJS_PRIORITY = 40;
+const GECKO_PRIORITY = 50;
+
+function createFrame(filename, func, lineno, colno) {
+ const frame = {
+ filename,
+ function: func,
+ in_app: true, // All browser frames are considered in_app
+ };
+
+ if (lineno !== undefined) {
+ frame.lineno = lineno;
+ }
+
+ if (colno !== undefined) {
+ frame.colno = colno;
+ }
+
+ return frame;
+}
+
+// Chromium based browsers: Chrome, Brave, new Opera, new Edge
+const chromeRegex =
+ /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
+const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
+
+const chrome = line => {
+ const parts = chromeRegex.exec(line);
+
+ if (parts) {
+ const isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
+
+ if (isEval) {
+ const subMatch = chromeEvalRegex.exec(parts[2]);
+
+ if (subMatch) {
+ // throw out eval line/column and use top-most line/column number
+ parts[2] = subMatch[1]; // url
+ parts[3] = subMatch[2]; // line
+ parts[4] = subMatch[3]; // column
+ }
+ }
+
+ // Kamil: One more hack won't hurt us right? Understanding and adding more rules on top of these regexps right now
+ // would be way too time consuming. (TODO: Rewrite whole RegExp to be more readable)
+ const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
+
+ return createFrame(filename, func, parts[3] ? +parts[3] : undefined, parts[4] ? +parts[4] : undefined);
+ }
+
+ return;
+};
+
+const chromeStackLineParser = [CHROME_PRIORITY, chrome];
+
+// gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it
+// generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
+// We need this specific case for now because we want no other regex to match.
+const geckoREgex =
+ /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
+const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
+
+const gecko = line => {
+ const parts = geckoREgex.exec(line);
+
+ if (parts) {
+ const isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
+ if (isEval) {
+ const subMatch = geckoEvalRegex.exec(parts[3]);
+
+ if (subMatch) {
+ // throw out eval line/column and use top-most line number
+ parts[1] = parts[1] || 'eval';
+ parts[3] = subMatch[1];
+ parts[4] = subMatch[2];
+ parts[5] = ''; // no column when eval
+ }
+ }
+
+ let filename = parts[3];
+ let func = parts[1] || UNKNOWN_FUNCTION;
+ [func, filename] = extractSafariExtensionDetails(func, filename);
+
+ return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined);
+ }
+
+ return;
+};
+
+const geckoStackLineParser = [GECKO_PRIORITY, gecko];
+
+const winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
+
+const winjs = line => {
+ const parts = winjsRegex.exec(line);
+
+ return parts
+ ? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined)
+ : undefined;
+};
+
+const winjsStackLineParser = [WINJS_PRIORITY, winjs];
+
+const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
+
+const opera10 = line => {
+ const parts = opera10Regex.exec(line);
+ return parts ? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : undefined;
+};
+
+const opera10StackLineParser = [OPERA10_PRIORITY, opera10];
+
+const opera11Regex =
+ / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
+
+const opera11 = line => {
+ const parts = opera11Regex.exec(line);
+ return parts ? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined;
+};
+
+const opera11StackLineParser = [OPERA11_PRIORITY, opera11];
+
+const defaultStackLineParsers = [chromeStackLineParser, geckoStackLineParser, winjsStackLineParser];
+
+const defaultStackParser = createStackParser(...defaultStackLineParsers);
+
+/**
+ * Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
+ * What it means, is that instead of format like:
+ *
+ * Error: wat
+ * at function@url:row:col
+ * at function@url:row:col
+ * at function@url:row:col
+ *
+ * it produces something like:
+ *
+ * function@url:row:col
+ * function@url:row:col
+ * function@url:row:col
+ *
+ * Because of that, it won't be captured by `chrome` RegExp and will fall into `Gecko` branch.
+ * This function is extracted so that we can use it in both places without duplicating the logic.
+ * Unfortunately "just" changing RegExp is too complicated now and making it pass all tests
+ * and fix this case seems like an impossible, or at least way too time-consuming task.
+ */
+const extractSafariExtensionDetails = (func, filename) => {
+ const isSafariExtension = func.indexOf('safari-extension') !== -1;
+ const isSafariWebExtension = func.indexOf('safari-web-extension') !== -1;
+
+ return isSafariExtension || isSafariWebExtension
+ ? [
+ func.indexOf('@') !== -1 ? func.split('@')[0] : UNKNOWN_FUNCTION,
+ isSafariExtension ? `safari-extension:${filename}` : `safari-web-extension:${filename}`,
+ ]
+ : [func, filename];
+};
+
+export { chromeStackLineParser, defaultStackLineParsers, defaultStackParser, geckoStackLineParser, opera10StackLineParser, opera11StackLineParser, winjsStackLineParser };
+//# sourceMappingURL=stack-parsers.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js b/shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js
new file mode 100644
index 0000000..bb836e3
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/transports/fetch.js
@@ -0,0 +1,64 @@
+import { createTransport } from '@sentry/core';
+import { rejectedSyncPromise } from '@sentry/utils';
+import { getNativeFetchImplementation, clearCachedFetchImplementation } from './utils.js';
+
+/**
+ * Creates a Transport that uses the Fetch API to send events to Sentry.
+ */
+function makeFetchTransport(
+ options,
+ nativeFetch = getNativeFetchImplementation(),
+) {
+ let pendingBodySize = 0;
+ let pendingCount = 0;
+
+ function makeRequest(request) {
+ const requestSize = request.body.length;
+ pendingBodySize += requestSize;
+ pendingCount++;
+
+ const requestOptions = {
+ body: request.body,
+ method: 'POST',
+ referrerPolicy: 'origin',
+ headers: options.headers,
+ // Outgoing requests are usually cancelled when navigating to a different page, causing a "TypeError: Failed to
+ // fetch" error and sending a "network_error" client-outcome - in Chrome, the request status shows "(cancelled)".
+ // The `keepalive` flag keeps outgoing requests alive, even when switching pages. We want this since we're
+ // frequently sending events right before the user is switching pages (eg. whenfinishing navigation transactions).
+ // Gotchas:
+ // - `keepalive` isn't supported by Firefox
+ // - As per spec (https://fetch.spec.whatwg.org/#http-network-or-cache-fetch):
+ // If the sum of contentLength and inflightKeepaliveBytes is greater than 64 kibibytes, then return a network error.
+ // We will therefore only activate the flag when we're below that limit.
+ // There is also a limit of requests that can be open at the same time, so we also limit this to 15
+ // See https://github.com/getsentry/sentry-javascript/pull/7553 for details
+ keepalive: pendingBodySize <= 60000 && pendingCount < 15,
+ ...options.fetchOptions,
+ };
+
+ try {
+ return nativeFetch(options.url, requestOptions).then(response => {
+ pendingBodySize -= requestSize;
+ pendingCount--;
+ return {
+ statusCode: response.status,
+ headers: {
+ 'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
+ 'retry-after': response.headers.get('Retry-After'),
+ },
+ };
+ });
+ } catch (e) {
+ clearCachedFetchImplementation();
+ pendingBodySize -= requestSize;
+ pendingCount--;
+ return rejectedSyncPromise(e);
+ }
+ }
+
+ return createTransport(options, makeRequest);
+}
+
+export { makeFetchTransport };
+//# sourceMappingURL=fetch.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/transports/offline.js b/shared/logger/node_modules/@sentry/browser/esm/transports/offline.js
new file mode 100644
index 0000000..c60a02d
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/transports/offline.js
@@ -0,0 +1,133 @@
+import { makeOfflineTransport } from '@sentry/core';
+import { serializeEnvelope, parseEnvelope } from '@sentry/utils';
+
+// 'Store', 'promisifyRequest' and 'createStore' were originally copied from the 'idb-keyval' package before being
+// modified and simplified: https://github.com/jakearchibald/idb-keyval
+//
+// At commit: 0420a704fd6cbb4225429c536b1f61112d012fca
+// Original licence:
+
+// Copyright 2016, Jake Archibald
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+function promisifyRequest(request) {
+ return new Promise((resolve, reject) => {
+ // @ts-ignore - file size hacks
+ request.oncomplete = request.onsuccess = () => resolve(request.result);
+ // @ts-ignore - file size hacks
+ request.onabort = request.onerror = () => reject(request.error);
+ });
+}
+
+/** Create or open an IndexedDb store */
+function createStore(dbName, storeName) {
+ const request = indexedDB.open(dbName);
+ request.onupgradeneeded = () => request.result.createObjectStore(storeName);
+ const dbp = promisifyRequest(request);
+
+ return callback => dbp.then(db => callback(db.transaction(storeName, 'readwrite').objectStore(storeName)));
+}
+
+function keys(store) {
+ return promisifyRequest(store.getAllKeys() );
+}
+
+/** Insert into the store */
+function insert(store, value, maxQueueSize) {
+ return store(store => {
+ return keys(store).then(keys => {
+ if (keys.length >= maxQueueSize) {
+ return;
+ }
+
+ // We insert with an incremented key so that the entries are popped in order
+ store.put(value, Math.max(...keys, 0) + 1);
+ return promisifyRequest(store.transaction);
+ });
+ });
+}
+
+/** Pop the oldest value from the store */
+function pop(store) {
+ return store(store => {
+ return keys(store).then(keys => {
+ if (keys.length === 0) {
+ return undefined;
+ }
+
+ return promisifyRequest(store.get(keys[0])).then(value => {
+ store.delete(keys[0]);
+ return promisifyRequest(store.transaction).then(() => value);
+ });
+ });
+ });
+}
+
+function createIndexedDbStore(options) {
+ let store;
+
+ // Lazily create the store only when it's needed
+ function getStore() {
+ if (store == undefined) {
+ store = createStore(options.dbName || 'sentry-offline', options.storeName || 'queue');
+ }
+
+ return store;
+ }
+
+ return {
+ insert: async (env) => {
+ try {
+ const serialized = await serializeEnvelope(env, options.textEncoder);
+ await insert(getStore(), serialized, options.maxQueueSize || 30);
+ } catch (_) {
+ //
+ }
+ },
+ pop: async () => {
+ try {
+ const deserialized = await pop(getStore());
+ if (deserialized) {
+ return parseEnvelope(
+ deserialized,
+ options.textEncoder || new TextEncoder(),
+ options.textDecoder || new TextDecoder(),
+ );
+ }
+ } catch (_) {
+ //
+ }
+
+ return undefined;
+ },
+ };
+}
+
+function makeIndexedDbOfflineTransport(
+ createTransport,
+) {
+ return options => createTransport({ ...options, createStore: createIndexedDbStore });
+}
+
+/**
+ * Creates a transport that uses IndexedDb to store events when offline.
+ */
+function makeBrowserOfflineTransport(
+ createTransport,
+) {
+ return makeIndexedDbOfflineTransport(makeOfflineTransport(createTransport));
+}
+
+export { createStore, insert, makeBrowserOfflineTransport, pop };
+//# sourceMappingURL=offline.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/transports/utils.js b/shared/logger/node_modules/@sentry/browser/esm/transports/utils.js
new file mode 100644
index 0000000..bc50f0c
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/transports/utils.js
@@ -0,0 +1,85 @@
+import { isNativeFetch, logger } from '@sentry/utils';
+import { WINDOW } from '../helpers.js';
+
+let cachedFetchImpl = undefined;
+
+/**
+ * A special usecase for incorrectly wrapped Fetch APIs in conjunction with ad-blockers.
+ * Whenever someone wraps the Fetch API and returns the wrong promise chain,
+ * this chain becomes orphaned and there is no possible way to capture it's rejections
+ * other than allowing it bubble up to this very handler. eg.
+ *
+ * const f = window.fetch;
+ * window.fetch = function () {
+ * const p = f.apply(this, arguments);
+ *
+ * p.then(function() {
+ * console.log('hi.');
+ * });
+ *
+ * return p;
+ * }
+ *
+ * `p.then(function () { ... })` is producing a completely separate promise chain,
+ * however, what's returned is `p` - the result of original `fetch` call.
+ *
+ * This mean, that whenever we use the Fetch API to send our own requests, _and_
+ * some ad-blocker blocks it, this orphaned chain will _always_ reject,
+ * effectively causing another event to be captured.
+ * This makes a whole process become an infinite loop, which we need to somehow
+ * deal with, and break it in one way or another.
+ *
+ * To deal with this issue, we are making sure that we _always_ use the real
+ * browser Fetch API, instead of relying on what `window.fetch` exposes.
+ * The only downside to this would be missing our own requests as breadcrumbs,
+ * but because we are already not doing this, it should be just fine.
+ *
+ * Possible failed fetch error messages per-browser:
+ *
+ * Chrome: Failed to fetch
+ * Edge: Failed to Fetch
+ * Firefox: NetworkError when attempting to fetch resource
+ * Safari: resource blocked by content blocker
+ */
+function getNativeFetchImplementation() {
+ if (cachedFetchImpl) {
+ return cachedFetchImpl;
+ }
+
+ /* eslint-disable @typescript-eslint/unbound-method */
+
+ // Fast path to avoid DOM I/O
+ if (isNativeFetch(WINDOW.fetch)) {
+ return (cachedFetchImpl = WINDOW.fetch.bind(WINDOW));
+ }
+
+ const document = WINDOW.document;
+ let fetchImpl = WINDOW.fetch;
+ // eslint-disable-next-line deprecation/deprecation
+ if (document && typeof document.createElement === 'function') {
+ try {
+ const sandbox = document.createElement('iframe');
+ sandbox.hidden = true;
+ document.head.appendChild(sandbox);
+ const contentWindow = sandbox.contentWindow;
+ if (contentWindow && contentWindow.fetch) {
+ fetchImpl = contentWindow.fetch;
+ }
+ document.head.removeChild(sandbox);
+ } catch (e) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e);
+ }
+ }
+
+ return (cachedFetchImpl = fetchImpl.bind(WINDOW));
+ /* eslint-enable @typescript-eslint/unbound-method */
+}
+
+/** Clears cached fetch impl */
+function clearCachedFetchImplementation() {
+ cachedFetchImpl = undefined;
+}
+
+export { clearCachedFetchImplementation, getNativeFetchImplementation };
+//# sourceMappingURL=utils.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js b/shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js
new file mode 100644
index 0000000..4cb34a0
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/transports/xhr.js
@@ -0,0 +1,52 @@
+import { createTransport } from '@sentry/core';
+import { SyncPromise } from '@sentry/utils';
+
+/**
+ * The DONE ready state for XmlHttpRequest
+ *
+ * Defining it here as a constant b/c XMLHttpRequest.DONE is not always defined
+ * (e.g. during testing, it is `undefined`)
+ *
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState}
+ */
+const XHR_READYSTATE_DONE = 4;
+
+/**
+ * Creates a Transport that uses the XMLHttpRequest API to send events to Sentry.
+ */
+function makeXHRTransport(options) {
+ function makeRequest(request) {
+ return new SyncPromise((resolve, reject) => {
+ const xhr = new XMLHttpRequest();
+
+ xhr.onerror = reject;
+
+ xhr.onreadystatechange = () => {
+ if (xhr.readyState === XHR_READYSTATE_DONE) {
+ resolve({
+ statusCode: xhr.status,
+ headers: {
+ 'x-sentry-rate-limits': xhr.getResponseHeader('X-Sentry-Rate-Limits'),
+ 'retry-after': xhr.getResponseHeader('Retry-After'),
+ },
+ });
+ }
+ };
+
+ xhr.open('POST', options.url);
+
+ for (const header in options.headers) {
+ if (Object.prototype.hasOwnProperty.call(options.headers, header)) {
+ xhr.setRequestHeader(header, options.headers[header]);
+ }
+ }
+
+ xhr.send(request.body);
+ });
+ }
+
+ return createTransport(options, makeRequest);
+}
+
+export { makeXHRTransport };
+//# sourceMappingURL=xhr.js.map
diff --git a/shared/logger/node_modules/@sentry/browser/esm/userfeedback.js b/shared/logger/node_modules/@sentry/browser/esm/userfeedback.js
new file mode 100644
index 0000000..4765c98
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/browser/esm/userfeedback.js
@@ -0,0 +1,41 @@
+import { dsnToString, createEnvelope } from '@sentry/utils';
+
+/**
+ * Creates an envelope from a user feedback.
+ */
+function createUserFeedbackEnvelope(
+ feedback,
+ {
+ metadata,
+ tunnel,
+ dsn,
+ }
+
+,
+) {
+ const headers = {
+ event_id: feedback.event_id,
+ sent_at: new Date().toISOString(),
+ ...(metadata &&
+ metadata.sdk && {
+ sdk: {
+ name: metadata.sdk.name,
+ version: metadata.sdk.version,
+ },
+ }),
+ ...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),
+ };
+ const item = createUserFeedbackEnvelopeItem(feedback);
+
+ return createEnvelope(headers, [item]);
+}
+
+function createUserFeedbackEnvelopeItem(feedback) {
+ const feedbackHeaders = {
+ type: 'user_report',
+ };
+ return [feedbackHeaders, feedback];
+}
+
+export { createUserFeedbackEnvelope };
+//# sourceMappingURL=userfeedback.js.map