diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a29d239945b..03dadf042f89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 7.83.0 + +- chore(astro): Allow Astro 4.0 in peer dependencies (#9683) +- feat(astro): Add `assets` option to source maps upload options (#9668) +- feat(react): Support `exactOptionalPropertyTypes` on `ErrorBoundary` (#9098) +- fix: Don't depend on browser types in `types` (#9682) +- fix(astro): Configure sourcemap assets directory for Vercel adapter (#9665) +- fix(remix): Check the error data before spreading. (#9664) + ## 7.82.0 - feat(astro): Automatically add Sentry middleware in Astro integration (#9532) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9af7a880a407..717e548c5a9a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ Pro tip: If any of your breakpoints are in code run by multiple tests, and you r ## Debug Build Flags -Throughout the codebase, you will find the `__DEBUG_BUILD__` flag guarding various code sections. This flag serves two purposes: +Throughout the codebase, you will find a `__DEBUG_BUILD__` constant. This flag serves two purposes: 1. It enables us to remove debug code from our minified CDN bundles during build, by replacing the flag with `false` before tree-shaking occurs. 2. It enables users to remove Sentry debug code from their production bundles during their own build. When we build our npm packages, we replace the flag with `(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)`. If the user does nothing, this evaluates to `true` and logging is included. But if the user runs their own replacement during build (again replacing the flag with `false`), the build will tree-shake the logging away, just as our bundle builds do. diff --git a/packages/astro/package.json b/packages/astro/package.json index 7de67f5e4e02..3797589ef805 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -40,7 +40,7 @@ "access": "public" }, "peerDependencies": { - "astro": "3.x" + "astro": ">=3.x" }, "dependencies": { "@sentry/browser": "7.82.0", diff --git a/packages/astro/src/integration/index.ts b/packages/astro/src/integration/index.ts index 5f5629697e3e..213fae64ed7a 100644 --- a/packages/astro/src/integration/index.ts +++ b/packages/astro/src/integration/index.ts @@ -42,7 +42,7 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => { authToken: uploadOptions.authToken ?? env.SENTRY_AUTH_TOKEN, telemetry: uploadOptions.telemetry ?? true, sourcemaps: { - assets: [getSourcemapsAssetsGlob(config)], + assets: uploadOptions.assets ?? [getSourcemapsAssetsGlob(config)], }, debug: options.debug ?? false, }), @@ -100,9 +100,19 @@ function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined { } function getSourcemapsAssetsGlob(config: AstroConfig): string { + // The vercel adapter puts the output into its .vercel directory + // However, the way this adapter is written, the config.outDir value is update too late for + // us to reliably detect it. Also, server files are first temporarily written to /dist and then + // only copied over to /.vercel. This seems to happen too late though. + // So we glob on both of these directories. + // Another case of "it ain't pretty but it works":( + if (config.adapter?.name?.startsWith('@astrojs/vercel')) { + return '{.vercel,dist}/**/*'; + } + // paths are stored as "file://" URLs const outDirPathname = config.outDir && path.resolve(config.outDir.pathname); - const rootDirName = path.resolve((config.root && config.root.pathname) || process.cwd()); + const rootDirName = path.resolve(config.root?.pathname || process.cwd()); if (outDirPathname) { const relativePath = path.relative(rootDirName, outDirPathname); diff --git a/packages/astro/src/integration/types.ts b/packages/astro/src/integration/types.ts index 7d27402c5a45..8c069a2516a7 100644 --- a/packages/astro/src/integration/types.ts +++ b/packages/astro/src/integration/types.ts @@ -68,6 +68,18 @@ type SourceMapsOptions = { * @default true */ telemetry?: boolean; + + /** + * A glob or an array of globs that specify the build artifacts and source maps that will uploaded to Sentry. + * + * If this option is not specified, sensible defaults based on your `outDir`, `rootDir` and `adapter` + * config will be used. Use this option to override these defaults, for instance if you have a + * customized build setup that diverges from Astro's defaults. + * + * The globbing patterns must follow the implementation of the `glob` package. + * @see https://www.npmjs.com/package/glob#glob-primer + */ + assets?: string | Array; }; }; diff --git a/packages/astro/test/integration/index.test.ts b/packages/astro/test/integration/index.test.ts index 51132971321d..7dba9a0ef347 100644 --- a/packages/astro/test/integration/index.test.ts +++ b/packages/astro/test/integration/index.test.ts @@ -83,6 +83,65 @@ describe('sentryAstro integration', () => { }); }); + it('sets the correct assets glob for vercel if the Vercel adapter is used', async () => { + const integration = sentryAstro({ + sourceMapsUploadOptions: { enabled: true, org: 'my-org', project: 'my-project', telemetry: false }, + }); + // @ts-expect-error - the hook exists and we only need to pass what we actually use + await integration.hooks['astro:config:setup']({ + updateConfig, + injectScript, + config: { + // @ts-expect-error - we only need to pass what we actually use + adapter: { name: '@astrojs/vercel/serverless' }, + }, + }); + + expect(sentryVitePluginSpy).toHaveBeenCalledTimes(1); + expect(sentryVitePluginSpy).toHaveBeenCalledWith({ + authToken: 'my-token', + org: 'my-org', + project: 'my-project', + telemetry: false, + debug: false, + sourcemaps: { + assets: ['{.vercel,dist}/**/*'], + }, + }); + }); + + it('prefers user-specified assets-globs over the default values', async () => { + const integration = sentryAstro({ + sourceMapsUploadOptions: { + enabled: true, + org: 'my-org', + project: 'my-project', + assets: ['dist/server/**/*, dist/client/**/*'], + }, + }); + // @ts-expect-error - the hook exists and we only need to pass what we actually use + await integration.hooks['astro:config:setup']({ + updateConfig, + injectScript, + // @ts-expect-error - only passing in partial config + config: { + outDir: new URL('file://path/to/project/build'), + }, + }); + + expect(sentryVitePluginSpy).toHaveBeenCalledTimes(1); + expect(sentryVitePluginSpy).toHaveBeenCalledWith({ + authToken: 'my-token', + org: 'my-org', + project: 'my-project', + telemetry: true, + debug: false, + sourcemaps: { + assets: ['dist/server/**/*, dist/client/**/*'], + }, + }); + }); + it("doesn't enable source maps if `sourceMapsUploadOptions.enabled` is `false`", async () => { const integration = sentryAstro({ sourceMapsUploadOptions: { enabled: false }, diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 4c0ace57547b..4e46314f6711 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -13,6 +13,7 @@ import type { } from '@sentry/types'; import { createClientReportEnvelope, dsnToString, getSDKSource, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { eventFromException, eventFromMessage } from './eventbuilder'; import { WINDOW } from './helpers'; import type { BrowserTransportOptions } from './transports/types'; @@ -96,7 +97,7 @@ export class BrowserClient extends BaseClient { */ public captureUserFeedback(feedback: UserFeedback): void { if (!this._isEnabled()) { - __DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture user feedback.'); + DEBUG_BUILD && logger.warn('SDK not enabled, will not capture user feedback.'); return; } @@ -123,17 +124,17 @@ export class BrowserClient extends BaseClient { const outcomes = this._clearOutcomes(); if (outcomes.length === 0) { - __DEBUG_BUILD__ && logger.log('No outcomes to send'); + DEBUG_BUILD && logger.log('No outcomes to send'); return; } // This is really the only place where we want to check for a DSN and only send outcomes then if (!this._dsn) { - __DEBUG_BUILD__ && logger.log('No dsn provided, will not send outcomes'); + DEBUG_BUILD && logger.log('No dsn provided, will not send outcomes'); return; } - __DEBUG_BUILD__ && logger.log('Sending outcomes:', outcomes); + DEBUG_BUILD && logger.log('Sending outcomes:', outcomes); const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn)); void this._sendEnvelope(envelope); diff --git a/packages/browser/src/debug-build.ts b/packages/browser/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/browser/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 83db8af4fc63..2679cabed5f5 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -30,6 +30,7 @@ import { severityLevelFromString, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { getClient } from '../exports'; import { WINDOW } from '../helpers'; @@ -148,7 +149,7 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: HandlerDa let maxStringLength = typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined; if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) { - __DEBUG_BUILD__ && + DEBUG_BUILD && 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.`, ); diff --git a/packages/browser/src/integrations/dedupe.ts b/packages/browser/src/integrations/dedupe.ts index c7a5cb5470b3..74d22d5a462c 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,6 +1,8 @@ import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -40,7 +42,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, this._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); return null; } } catch (_oO) {} // eslint-disable-line no-empty diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 47acd2a75140..0c3f3be60e2d 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -12,6 +12,7 @@ import { } from '@sentry/utils'; import type { BrowserClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { eventFromUnknownInput } from '../eventbuilder'; import { shouldIgnoreOnError } from '../helpers'; @@ -254,7 +255,7 @@ function _enhanceEventWithInitialFrame(event: Event, url: any, line: any, column } function globalHandlerLog(type: string): void { - __DEBUG_BUILD__ && logger.log(`Global Handler attached: ${type}`); + DEBUG_BUILD && logger.log(`Global Handler attached: ${type}`); } function getHubAndOptions(): [Hub, StackParser, boolean | undefined] { diff --git a/packages/browser/src/profiling/hubextensions.ts b/packages/browser/src/profiling/hubextensions.ts index 0c23b5e5f128..82492081b924 100644 --- a/packages/browser/src/profiling/hubextensions.ts +++ b/packages/browser/src/profiling/hubextensions.ts @@ -2,6 +2,7 @@ import type { Transaction } from '@sentry/types'; import { logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { WINDOW } from '../helpers'; import type { JSSelfProfile } from './jsSelfProfiling'; import { @@ -21,7 +22,7 @@ import { */ export function onProfilingStartRouteTransaction(transaction: Transaction | undefined): Transaction | undefined { if (!transaction) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Transaction is undefined, skipping profiling'); } return transaction; @@ -54,7 +55,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return transaction; } - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log(`[Profiling] started profiling transaction: ${transaction.name || transaction.description}`); } @@ -85,7 +86,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return null; } if (processedProfile) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] profile for:', transaction.name || transaction.description, @@ -103,13 +104,13 @@ export function startProfileForTransaction(transaction: Transaction): Transactio maxDurationTimeoutID = undefined; } - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { 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 (!profile) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { 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', @@ -122,7 +123,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return null; }) .catch(error => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] error while stopping profiler:', error); } return null; @@ -131,7 +132,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio // Enqueue a timeout to prevent profiles from running over max duration. let maxDurationTimeoutID: number | undefined = WINDOW.setTimeout(() => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] max profile duration elapsed, stopping profiling for:', transaction.name || transaction.description, diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index 1ccfd63cf798..3f5251c4583f 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -2,6 +2,7 @@ import type { EventProcessor, Hub, Integration, Transaction } from '@sentry/type import type { Profile } from '@sentry/types/src/profiling'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { startProfileForTransaction } from './hubextensions'; import type { ProfiledEvent } from './utils'; import { @@ -78,14 +79,12 @@ export class BrowserProfilingIntegration implements Integration { const start_timestamp = context && context['profile'] && context['profile']['start_timestamp']; if (typeof profile_id !== 'string') { - __DEBUG_BUILD__ && - logger.log('[Profiling] cannot find profile for a transaction without a profile context'); + DEBUG_BUILD && logger.log('[Profiling] cannot find profile for a transaction without a profile context'); continue; } if (!profile_id) { - __DEBUG_BUILD__ && - logger.log('[Profiling] cannot find profile for a transaction without a profile context'); + DEBUG_BUILD && logger.log('[Profiling] cannot find profile for a transaction without a profile context'); continue; } @@ -96,7 +95,7 @@ export class BrowserProfilingIntegration implements Integration { const profile = takeProfileFromGlobalCache(profile_id); if (!profile) { - __DEBUG_BUILD__ && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); + DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); continue; } diff --git a/packages/browser/src/profiling/utils.ts b/packages/browser/src/profiling/utils.ts index 4c8a74adf247..ddf966d86deb 100644 --- a/packages/browser/src/profiling/utils.ts +++ b/packages/browser/src/profiling/utils.ts @@ -5,6 +5,7 @@ import type { DebugImage, Envelope, Event, StackFrame, StackParser, Transaction import type { Profile, ThreadCpuProfile } from '@sentry/types/src/profiling'; import { browserPerformanceTimeOrigin, forEachEnvelopeItem, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { getClient } from '../exports'; import { WINDOW } from '../helpers'; import type { JSSelfProfile, JSSelfProfiler, JSSelfProfilerConstructor, JSSelfProfileStack } from './jsSelfProfiling'; @@ -96,7 +97,7 @@ function getTraceId(event: Event): string { // 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 (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log(`[Profiling] Invalid traceId: ${traceId} on profiled event`); } } @@ -418,7 +419,7 @@ export function applyDebugMetadata(resource_paths: ReadonlyArray): Debug export function isValidSampleRate(rate: unknown): boolean { // 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))) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -434,8 +435,7 @@ export function isValidSampleRate(rate: unknown): boolean { // 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) { - __DEBUG_BUILD__ && - logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); + DEBUG_BUILD && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } return true; @@ -443,7 +443,7 @@ export function isValidSampleRate(rate: unknown): boolean { function isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { profile_id: string } { if (profile.samples.length < 2) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { // 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. @@ -453,7 +453,7 @@ function isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { pr } if (!profile.frames.length) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Discarding profile because it contains no frames'); } return false; @@ -483,7 +483,7 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { const JSProfilerConstructor = WINDOW.Profiler; if (!isJSProfilerSupported(JSProfilerConstructor)) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] Profiling is not supported by this browser, Profiler interface missing on window object.', ); @@ -502,7 +502,7 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { try { return new JSProfilerConstructor({ sampleInterval: samplingIntervalMS, maxBufferSize: maxSamples }); } catch (e) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( "[Profiling] Failed to initialize the Profiling constructor, this is likely due to a missing 'Document-Policy': 'js-profiling' header.", ); @@ -520,14 +520,14 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { export function shouldProfileTransaction(transaction: Transaction): boolean { // If constructor failed once, it will always fail, so we can early return. if (PROFILING_CONSTRUCTOR_FAILED) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Profiling has been disabled for the duration of the current user session.'); } return false; } if (!transaction.sampled) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Discarding profile because transaction was not sampled.'); } return false; @@ -536,7 +536,7 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { const client = getClient(); const options = client && client.getOptions(); if (!options) { - __DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no options found.'); + DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.'); return false; } @@ -546,13 +546,13 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { // 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)) { - __DEBUG_BUILD__ && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); return false; } // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped if (!profilesSampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( '[Profiling] Discarding profile because a negative sampling decision was inherited or profileSampleRate is set to 0', ); @@ -564,7 +564,7 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate; // Check if we should sample this profile if (!sampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( profilesSampleRate, diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 0244af0ba98e..2bee5912e15e 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -17,6 +17,7 @@ import { import type { BrowserClientOptions, BrowserOptions } from './client'; import { BrowserClient } from './client'; +import { DEBUG_BUILD } from './debug-build'; import type { ReportDialogOptions } from './helpers'; import { WINDOW, wrap as internalWrap } from './helpers'; import { Breadcrumbs, Dedupe, GlobalHandlers, HttpContext, LinkedErrors, TryCatch } from './integrations'; @@ -140,14 +141,14 @@ export function init(options: BrowserOptions = {}): void { export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = getCurrentHub()): void { // doesn't work without a document (React Native) if (!WINDOW.document) { - __DEBUG_BUILD__ && logger.error('Global document not defined in showReportDialog call'); + DEBUG_BUILD && logger.error('Global document not defined in showReportDialog call'); return; } const { client, scope } = hub.getStackTop(); const dsn = options.dsn || (client && client.getDsn()); if (!dsn) { - __DEBUG_BUILD__ && logger.error('DSN not configured for showReportDialog call'); + DEBUG_BUILD && logger.error('DSN not configured for showReportDialog call'); return; } @@ -189,7 +190,7 @@ export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = g if (injectionPoint) { injectionPoint.appendChild(script); } else { - __DEBUG_BUILD__ && logger.error('Not injecting report dialog. No injection point found in HTML'); + DEBUG_BUILD && logger.error('Not injecting report dialog. No injection point found in HTML'); } } @@ -236,8 +237,7 @@ function startSessionOnHub(hub: Hub): void { */ function startSessionTracking(): void { if (typeof WINDOW.document === 'undefined') { - __DEBUG_BUILD__ && - logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + DEBUG_BUILD && logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); return; } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 9852d754ec7b..6b42ae77b480 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,5 +1,6 @@ import { isNativeFetch, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { WINDOW } from '../helpers'; let cachedFetchImpl: FetchImpl | undefined = undefined; @@ -70,8 +71,7 @@ export function getNativeFetchImplementation(): FetchImpl { } document.head.removeChild(sandbox); } catch (e) { - __DEBUG_BUILD__ && - logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); + DEBUG_BUILD && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); } } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 915bafffa9bc..df3444126e8d 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -44,6 +44,7 @@ import { } from '@sentry/utils'; import { getEnvelopeEndpointWithUrlEncodedAuth } from './api'; +import { DEBUG_BUILD } from './debug-build'; import { createEventEnvelope, createSessionEnvelope } from './envelope'; import type { IntegrationIndex } from './integration'; import { setupIntegration, setupIntegrations } from './integration'; @@ -128,7 +129,7 @@ export abstract class BaseClient implements Client { if (options.dsn) { this._dsn = makeDsn(options.dsn); } else { - __DEBUG_BUILD__ && logger.warn('No DSN provided, client will not send events.'); + DEBUG_BUILD && logger.warn('No DSN provided, client will not send events.'); } if (this._dsn) { @@ -148,7 +149,7 @@ export abstract class BaseClient implements Client { public captureException(exception: any, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (checkOrSetAlreadyCaught(exception)) { - __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); + DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -198,7 +199,7 @@ export abstract class BaseClient implements Client { public captureEvent(event: Event, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (hint && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) { - __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); + DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -218,7 +219,7 @@ export abstract class BaseClient implements Client { */ public captureSession(session: Session): void { if (!(typeof session.release === 'string')) { - __DEBUG_BUILD__ && logger.warn('Discarded session because of missing or non-string release'); + DEBUG_BUILD && logger.warn('Discarded session because of missing or non-string release'); } else { this.sendSession(session); // After sending, we set init false to indicate it's not the first occurrence @@ -316,7 +317,7 @@ export abstract class BaseClient implements Client { try { return (this._integrations[integration.id] as T) || null; } catch (_oO) { - __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); return null; } } @@ -374,7 +375,7 @@ export abstract class BaseClient implements Client { // would be `Partial>>>` // With typescript 4.1 we could even use template literal types const key = `${reason}:${category}`; - __DEBUG_BUILD__ && logger.log(`Adding outcome: "${key}"`); + DEBUG_BUILD && logger.log(`Adding outcome: "${key}"`); // The following works because undefined + 1 === NaN and NaN is falsy this._outcomes[key] = this._outcomes[key] + 1 || 1; @@ -604,7 +605,7 @@ export abstract class BaseClient implements Client { return finalEvent.event_id; }, reason => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { // If something's gone wrong, log the error as a warning. If it's just us having used a `SentryError` for // control flow, log just the message (no stack) as a log-level log. const sentryError = reason as SentryError; @@ -739,10 +740,10 @@ export abstract class BaseClient implements Client { if (this._isEnabled() && this._transport) { return this._transport.send(envelope).then(null, reason => { - __DEBUG_BUILD__ && logger.error('Error while sending event:', reason); + DEBUG_BUILD && logger.error('Error while sending event:', reason); }); } else { - __DEBUG_BUILD__ && logger.error('Transport disabled'); + DEBUG_BUILD && logger.error('Transport disabled'); } } diff --git a/packages/core/src/debug-build.ts b/packages/core/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/core/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/core/src/eventProcessors.ts b/packages/core/src/eventProcessors.ts index 4596788b9dcb..cc4a39cc84ea 100644 --- a/packages/core/src/eventProcessors.ts +++ b/packages/core/src/eventProcessors.ts @@ -1,6 +1,8 @@ import type { Event, EventHint, EventProcessor } from '@sentry/types'; import { getGlobalSingleton, isThenable, logger, SyncPromise } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** * Returns the global event processors. */ @@ -32,10 +34,7 @@ export function notifyEventProcessors( } else { const result = processor({ ...event }, hint) as Event | null; - __DEBUG_BUILD__ && - processor.id && - result === null && - logger.log(`Event processor "${processor.id}" dropped event`); + DEBUG_BUILD && processor.id && result === null && logger.log(`Event processor "${processor.id}" dropped event`); if (isThenable(result)) { void result diff --git a/packages/core/src/exports.ts b/packages/core/src/exports.ts index 6d1d52e60863..6d1e80600a75 100644 --- a/packages/core/src/exports.ts +++ b/packages/core/src/exports.ts @@ -18,6 +18,7 @@ import type { } from '@sentry/types'; import { isThenable, logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import type { Hub } from './hub'; import { getCurrentHub } from './hub'; import type { Scope } from './scope'; @@ -205,9 +206,9 @@ export function captureCheckIn(checkIn: CheckIn, upsertMonitorConfig?: MonitorCo const scope = hub.getScope(); const client = hub.getClient(); if (!client) { - __DEBUG_BUILD__ && logger.warn('Cannot capture check-in. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot capture check-in. No client defined.'); } else if (!client.captureCheckIn) { - __DEBUG_BUILD__ && logger.warn('Cannot capture check-in. Client does not support sending check-ins.'); + DEBUG_BUILD && logger.warn('Cannot capture check-in. Client does not support sending check-ins.'); } else { return client.captureCheckIn(checkIn, upsertMonitorConfig, scope); } @@ -271,7 +272,7 @@ export async function flush(timeout?: number): Promise { if (client) { return client.flush(timeout); } - __DEBUG_BUILD__ && logger.warn('Cannot flush events. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); return Promise.resolve(false); } @@ -288,7 +289,7 @@ export async function close(timeout?: number): Promise { if (client) { return client.close(timeout); } - __DEBUG_BUILD__ && logger.warn('Cannot flush events and disable SDK. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); return Promise.resolve(false); } diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index c25f9fe00f67..6d19b463b73b 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -23,6 +23,7 @@ import type { import { consoleSandbox, dateTimestampInSeconds, getGlobalSingleton, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils'; import { DEFAULT_ENVIRONMENT } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import { Scope } from './scope'; import { closeSession, makeSession, updateSession } from './session'; @@ -362,7 +363,7 @@ export class Hub implements HubInterface { try { return client.getIntegration(integration); } catch (_oO) { - __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); + DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); return null; } } @@ -373,16 +374,14 @@ export class Hub implements HubInterface { public startTransaction(context: TransactionContext, customSamplingContext?: CustomSamplingContext): Transaction { const result = this._callExtensionMethod('startTransaction', context, customSamplingContext); - if (__DEBUG_BUILD__ && !result) { + if (DEBUG_BUILD && !result) { const client = this.getClient(); if (!client) { - // eslint-disable-next-line no-console - console.warn( + logger.warn( "Tracing extension 'startTransaction' is missing. You should 'init' the SDK before calling 'startTransaction'", ); } else { - // eslint-disable-next-line no-console - console.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init': + logger.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init': Sentry.addTracingExtensions(); Sentry.init({...}); `); @@ -505,7 +504,7 @@ Sentry.init({...}); if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') { return sentry.extensions[method].apply(this, args); } - __DEBUG_BUILD__ && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); + DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); } } diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 8b05139af74b..2f21339a0842 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,6 +1,7 @@ import type { Client, Event, EventHint, Integration, Options } from '@sentry/types'; import { arrayify, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { addGlobalEventProcessor } from './eventProcessors'; import { getClient } from './exports'; import { getCurrentHub } from './hub'; @@ -128,7 +129,7 @@ export function setupIntegration(client: Client, integration: Integration, integ client.addEventProcessor(processor); } - __DEBUG_BUILD__ && logger.log(`Integration installed: ${integration.name}`); + DEBUG_BUILD && logger.log(`Integration installed: ${integration.name}`); } /** Add an integration to the current hub's client. */ @@ -136,7 +137,7 @@ export function addIntegration(integration: Integration): void { const client = getClient(); if (!client || !client.addIntegration) { - __DEBUG_BUILD__ && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`); + DEBUG_BUILD && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`); return; } diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 20721d9dbcec..c1fcadb1076b 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,6 +1,8 @@ import type { Client, Event, EventHint, Integration, StackFrame } from '@sentry/types'; import { getEventDescription, logger, stringMatchesSomePattern } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + // "Script error." is hard coded into browsers for errors that it can't read. // this is the result of a script being pulled in from an external domain and CORS. const DEFAULT_IGNORE_ERRORS = [/^Script error\.?$/, /^Javascript error: Script error\.? on line 0$/]; @@ -85,26 +87,26 @@ export function _mergeOptions( /** JSDoc */ export function _shouldDropEvent(event: Event, options: Partial): boolean { if (options.ignoreInternal && _isSentryError(event)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); return true; } if (_isIgnoredError(event, options.ignoreErrors)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isIgnoredTransaction(event, options.ignoreTransactions)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`ignoreTransactions\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isDeniedUrl(event, options.denyUrls)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( event, @@ -113,7 +115,7 @@ export function _shouldDropEvent(event: Event, options: Partial( options: O, ): void { if (options.debug === true) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.enable(); } else { // use `console.warn` rather than `logger.warn` since by non-debug bundles have all `logger.x` statements stripped - // eslint-disable-next-line no-console - console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.'); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.'); + }); } } const hub = getCurrentHub(); diff --git a/packages/core/src/server-runtime-client.ts b/packages/core/src/server-runtime-client.ts index 67d7055a1623..398a4224ef6d 100644 --- a/packages/core/src/server-runtime-client.ts +++ b/packages/core/src/server-runtime-client.ts @@ -15,6 +15,7 @@ import { eventFromMessage, eventFromUnknownInput, logger, resolvedSyncPromise, u import { BaseClient } from './baseclient'; import { createCheckInEnvelope } from './checkin'; +import { DEBUG_BUILD } from './debug-build'; import { getCurrentHub } from './hub'; import type { Scope } from './scope'; import { SessionFlusher } from './sessionflusher'; @@ -129,7 +130,7 @@ export class ServerRuntimeClient< public initSessionFlusher(): void { const { release, environment } = this._options; if (!release) { - __DEBUG_BUILD__ && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); + DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); } else { this._sessionFlusher = new SessionFlusher(this, { release, @@ -148,7 +149,7 @@ export class ServerRuntimeClient< public captureCheckIn(checkIn: CheckIn, monitorConfig?: MonitorConfig, scope?: Scope): string { const id = checkIn.status !== 'in_progress' && checkIn.checkInId ? checkIn.checkInId : uuid4(); if (!this._isEnabled()) { - __DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture checkin.'); + DEBUG_BUILD && logger.warn('SDK not enabled, will not capture checkin.'); return id; } @@ -191,7 +192,7 @@ export class ServerRuntimeClient< this.getDsn(), ); - __DEBUG_BUILD__ && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status); + DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status); void this._sendEnvelope(envelope); return id; } @@ -202,7 +203,7 @@ export class ServerRuntimeClient< */ protected _captureRequestSession(): void { if (!this._sessionFlusher) { - __DEBUG_BUILD__ && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); + DEBUG_BUILD && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); } else { this._sessionFlusher.incrementSessionStatusCount(); } diff --git a/packages/core/src/tracing/errors.ts b/packages/core/src/tracing/errors.ts index 477629cb7f9e..9030f02efadc 100644 --- a/packages/core/src/tracing/errors.ts +++ b/packages/core/src/tracing/errors.ts @@ -4,6 +4,7 @@ import { logger, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { SpanStatusType } from './span'; import { getActiveTransaction } from './utils'; @@ -29,7 +30,7 @@ function errorCallback(): void { const activeTransaction = getActiveTransaction(); if (activeTransaction) { const status: SpanStatusType = 'internal_error'; - __DEBUG_BUILD__ && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); + DEBUG_BUILD && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); activeTransaction.setStatus(status); } } diff --git a/packages/core/src/tracing/hubextensions.ts b/packages/core/src/tracing/hubextensions.ts index 007612d8fb34..7cd8286860b2 100644 --- a/packages/core/src/tracing/hubextensions.ts +++ b/packages/core/src/tracing/hubextensions.ts @@ -1,6 +1,7 @@ import type { ClientOptions, CustomSamplingContext, TransactionContext } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getMainCarrier } from '../hub'; import { registerErrorInstrumentation } from './errors'; @@ -47,7 +48,7 @@ function _startTransaction( const transactionInstrumenter = transactionContext.instrumenter || 'sentry'; if (configInstrumenter !== transactionInstrumenter) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `A transaction was started with instrumenter=\`${transactionInstrumenter}\`, but the SDK is configured with the \`${configInstrumenter}\` instrumenter. The transaction will not be sampled. Please use the ${configInstrumenter} instrumentation to start transactions.`, diff --git a/packages/core/src/tracing/idletransaction.ts b/packages/core/src/tracing/idletransaction.ts index 1c4086ceecb7..b49b1d15e9b1 100644 --- a/packages/core/src/tracing/idletransaction.ts +++ b/packages/core/src/tracing/idletransaction.ts @@ -2,6 +2,7 @@ import type { TransactionContext } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import type { Span } from './span'; import { SpanRecorder } from './span'; @@ -119,7 +120,7 @@ export class IdleTransaction extends Transaction { if (_onScope) { // We set the transaction here on the scope so error events pick up the trace // context and attach it to the error. - __DEBUG_BUILD__ && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); + DEBUG_BUILD && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); _idleHub.configureScope(scope => scope.setSpan(this)); } @@ -143,7 +144,7 @@ export class IdleTransaction extends Transaction { } if (this.spanRecorder) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestamp * 1000).toISOString(), this.op); for (const callback of this._beforeFinishCallbacks) { @@ -160,7 +161,7 @@ export class IdleTransaction extends Transaction { if (!span.endTimestamp) { span.endTimestamp = endTimestamp; span.setStatus('cancelled'); - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2)); } @@ -170,7 +171,7 @@ export class IdleTransaction extends Transaction { const timeoutWithMarginOfError = (this._finalTimeout + this._idleTimeout) / 1000; const spanEndedBeforeFinalTimeout = span.endTimestamp - this.startTimestamp < timeoutWithMarginOfError; - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { const stringifiedSpan = JSON.stringify(span, undefined, 2); if (!spanStartedBeforeTransactionFinish) { logger.log('[Tracing] discarding Span since it happened after Transaction was finished', stringifiedSpan); @@ -182,9 +183,9 @@ export class IdleTransaction extends Transaction { return spanStartedBeforeTransactionFinish && spanEndedBeforeFinalTimeout; }); - __DEBUG_BUILD__ && logger.log('[Tracing] flushing IdleTransaction'); + DEBUG_BUILD && logger.log('[Tracing] flushing IdleTransaction'); } else { - __DEBUG_BUILD__ && logger.log('[Tracing] No active IdleTransaction'); + DEBUG_BUILD && logger.log('[Tracing] No active IdleTransaction'); } // if `this._onScope` is `true`, the transaction put itself on the scope when it started @@ -230,7 +231,7 @@ export class IdleTransaction extends Transaction { this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanId, maxlen); // Start heartbeat so that transactions do not run forever. - __DEBUG_BUILD__ && logger.log('Starting heartbeat'); + DEBUG_BUILD && logger.log('Starting heartbeat'); this._pingHeartbeat(); } this.spanRecorder.add(this); @@ -296,9 +297,9 @@ export class IdleTransaction extends Transaction { */ private _pushActivity(spanId: string): void { this.cancelIdleTimeout(undefined, { restartOnChildSpanChange: !this._idleTimeoutCanceledPermanently }); - __DEBUG_BUILD__ && logger.log(`[Tracing] pushActivity: ${spanId}`); + DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`); this.activities[spanId] = true; - __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } /** @@ -307,10 +308,10 @@ export class IdleTransaction extends Transaction { */ private _popActivity(spanId: string): void { if (this.activities[spanId]) { - __DEBUG_BUILD__ && logger.log(`[Tracing] popActivity ${spanId}`); + DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`); // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.activities[spanId]; - __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } if (Object.keys(this.activities).length === 0) { @@ -347,7 +348,7 @@ export class IdleTransaction extends Transaction { this._prevHeartbeatString = heartbeatString; if (this._heartbeatCounter >= 3) { - __DEBUG_BUILD__ && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); + DEBUG_BUILD && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); this.setStatus('deadline_exceeded'); this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[0]; this.finish(); @@ -360,7 +361,7 @@ export class IdleTransaction extends Transaction { * Pings the heartbeat */ private _pingHeartbeat(): void { - __DEBUG_BUILD__ && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); + DEBUG_BUILD && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); setTimeout(() => { this._beat(); }, this._heartbeatInterval); diff --git a/packages/core/src/tracing/sampling.ts b/packages/core/src/tracing/sampling.ts index 4b357b7bf1be..6c6ab19bf7c9 100644 --- a/packages/core/src/tracing/sampling.ts +++ b/packages/core/src/tracing/sampling.ts @@ -1,6 +1,7 @@ import type { Options, SamplingContext } from '@sentry/types'; import { isNaN, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { hasTracingEnabled } from '../utils/hasTracingEnabled'; import type { Transaction } from './transaction'; @@ -58,14 +59,14 @@ export function sampleTransaction( // 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(sampleRate)) { - __DEBUG_BUILD__ && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); transaction.sampled = false; return transaction; } // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped if (!sampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because ${ typeof options.tracesSampler === 'function' @@ -83,7 +84,7 @@ export function sampleTransaction( // if we're not going to keep it, we're done if (!transaction.sampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -92,7 +93,7 @@ export function sampleTransaction( return transaction; } - __DEBUG_BUILD__ && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); + DEBUG_BUILD && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); return transaction; } @@ -103,7 +104,7 @@ function isValidSampleRate(rate: unknown): boolean { // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck // eslint-disable-next-line @typescript-eslint/no-explicit-any if (isNaN(rate) || !(typeof rate === 'number' || typeof rate === 'boolean')) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -114,7 +115,7 @@ function isValidSampleRate(rate: unknown): boolean { // 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) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } diff --git a/packages/core/src/tracing/span.ts b/packages/core/src/tracing/span.ts index be4e420fc8bc..4b341a71e2c2 100644 --- a/packages/core/src/tracing/span.ts +++ b/packages/core/src/tracing/span.ts @@ -10,6 +10,8 @@ import type { } from '@sentry/types'; import { dropUndefinedKeys, generateSentryTraceHeader, logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** * Keeps track of finished spans for a given transaction * @internal @@ -190,7 +192,7 @@ export class Span implements SpanInterface { childSpan.transaction = this.transaction; - if (__DEBUG_BUILD__ && childSpan.transaction) { + if (DEBUG_BUILD && childSpan.transaction) { const opStr = (spanContext && spanContext.op) || '< unknown op >'; const nameStr = childSpan.transaction.name || '< unknown name >'; const idStr = childSpan.transaction.spanId; @@ -260,7 +262,7 @@ export class Span implements SpanInterface { */ public finish(endTimestamp?: number): void { if ( - __DEBUG_BUILD__ && + DEBUG_BUILD && // Don't call this for transactions this.transaction && this.transaction.spanId !== this.spanId diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts index 33e19ec7ecb4..99d706f0585e 100644 --- a/packages/core/src/tracing/trace.ts +++ b/packages/core/src/tracing/trace.ts @@ -1,6 +1,7 @@ import type { TransactionContext } from '@sentry/types'; import { dropUndefinedKeys, isThenable, logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getCurrentHub } from '../hub'; import { hasTracingEnabled } from '../utils/hasTracingEnabled'; @@ -248,7 +249,7 @@ export function continueTrace( currentScope.setPropagationContext(propagationContext); - if (__DEBUG_BUILD__ && traceparentData) { + if (DEBUG_BUILD && traceparentData) { logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); } diff --git a/packages/core/src/tracing/transaction.ts b/packages/core/src/tracing/transaction.ts index 73bfb16996bb..da2ccb32d30b 100644 --- a/packages/core/src/tracing/transaction.ts +++ b/packages/core/src/tracing/transaction.ts @@ -11,6 +11,7 @@ import type { } from '@sentry/types'; import { dropUndefinedKeys, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getCurrentHub } from '../hub'; import { getDynamicSamplingContextFromClient } from './dynamicSamplingContext'; @@ -226,7 +227,7 @@ export class Transaction extends SpanClass implements TransactionInterface { } if (!this.name) { - __DEBUG_BUILD__ && logger.warn('Transaction has no name, falling back to ``.'); + DEBUG_BUILD && logger.warn('Transaction has no name, falling back to ``.'); this.name = ''; } @@ -240,7 +241,7 @@ export class Transaction extends SpanClass implements TransactionInterface { if (this.sampled !== true) { // At this point if `sampled !== true` we want to discard the transaction. - __DEBUG_BUILD__ && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); + DEBUG_BUILD && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); if (client) { client.recordDroppedEvent('sample_rate', 'transaction'); @@ -288,7 +289,7 @@ export class Transaction extends SpanClass implements TransactionInterface { const hasMeasurements = Object.keys(this._measurements).length > 0; if (hasMeasurements) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( '[Measurements] Adding measurements to transaction', JSON.stringify(this._measurements, undefined, 2), @@ -296,7 +297,7 @@ export class Transaction extends SpanClass implements TransactionInterface { transaction.measurements = this._measurements; } - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); return transaction; } diff --git a/packages/core/src/transports/base.ts b/packages/core/src/transports/base.ts index 3111f5f15fca..199cad6c545b 100644 --- a/packages/core/src/transports/base.ts +++ b/packages/core/src/transports/base.ts @@ -24,6 +24,8 @@ import { updateRateLimits, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + export const DEFAULT_TRANSPORT_BUFFER_SIZE = 30; /** @@ -77,7 +79,7 @@ export function createTransport( response => { // We don't want to throw on NOK responses, but we want to at least log them if (response.statusCode !== undefined && (response.statusCode < 200 || response.statusCode >= 300)) { - __DEBUG_BUILD__ && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); + DEBUG_BUILD && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); } rateLimits = updateRateLimits(rateLimits, response); @@ -93,7 +95,7 @@ export function createTransport( result => result, error => { if (error instanceof SentryError) { - __DEBUG_BUILD__ && logger.error('Skipped sending event because buffer is full.'); + DEBUG_BUILD && logger.error('Skipped sending event because buffer is full.'); recordEnvelopeLoss('queue_overflow'); return resolvedSyncPromise(); } else { diff --git a/packages/core/src/transports/offline.ts b/packages/core/src/transports/offline.ts index c3864ead7ec5..c628e538a071 100644 --- a/packages/core/src/transports/offline.ts +++ b/packages/core/src/transports/offline.ts @@ -1,12 +1,14 @@ import type { Envelope, InternalBaseTransportOptions, Transport, TransportMakeRequestResponse } from '@sentry/types'; import { envelopeContainsItemType, logger, parseRetryAfterHeader } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + export const MIN_DELAY = 100; // 100 ms export const START_DELAY = 5_000; // 5 seconds const MAX_DELAY = 3.6e6; // 1 hour function log(msg: string, error?: Error): void { - __DEBUG_BUILD__ && logger.info(`[Offline]: ${msg}`, error); + DEBUG_BUILD && logger.info(`[Offline]: ${msg}`, error); } export interface OfflineStore { diff --git a/packages/deno/src/transports/index.ts b/packages/deno/src/transports/index.ts index 62da327c5d83..964c1a9347af 100644 --- a/packages/deno/src/transports/index.ts +++ b/packages/deno/src/transports/index.ts @@ -1,6 +1,6 @@ import { createTransport } from '@sentry/core'; import type { BaseTransportOptions, Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/types'; -import { rejectedSyncPromise } from '@sentry/utils'; +import { consoleSandbox, rejectedSyncPromise } from '@sentry/utils'; export interface DenoTransportOptions extends BaseTransportOptions { /** Custom headers for the transport. Used by the XHRTransport and FetchTransport */ @@ -14,9 +14,11 @@ export function makeFetchTransport(options: DenoTransportOptions): Transport { const url = new URL(options.url); if (Deno.permissions.querySync({ name: 'net', host: url.host }).state !== 'granted') { - // eslint-disable-next-line no-console - console.warn(`Sentry SDK requires 'net' permission to send events. -Run with '--allow-net=${url.host}' to grant the requires permissions.`); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn(`Sentry SDK requires 'net' permission to send events. + Run with '--allow-net=${url.host}' to grant the requires permissions.`); + }); } function makeRequest(request: TransportRequest): PromiseLike { diff --git a/packages/feedback/src/debug-build.ts b/packages/feedback/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/feedback/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/feedback/src/integration.ts b/packages/feedback/src/integration.ts index 13f155d1ced5..6b1e0fb1b2c4 100644 --- a/packages/feedback/src/integration.ts +++ b/packages/feedback/src/integration.ts @@ -16,6 +16,7 @@ import { SUCCESS_MESSAGE_TEXT, WINDOW, } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import type { FeedbackInternalOptions, FeedbackWidget, OptionalFeedbackConfiguration } from './types'; import { mergeOptions } from './util/mergeOptions'; import { createActorStyles } from './widget/Actor.css'; @@ -173,7 +174,7 @@ export class Feedback implements Integration { this._createWidget(this.options); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); } } @@ -218,7 +219,7 @@ export class Feedback implements Integration { typeof el === 'string' ? doc.querySelector(el) : typeof el.addEventListener === 'function' ? el : null; if (!targetEl) { - __DEBUG_BUILD__ && logger.error('[Feedback] Unable to attach to target element'); + DEBUG_BUILD && logger.error('[Feedback] Unable to attach to target element'); return null; } @@ -232,7 +233,7 @@ export class Feedback implements Integration { return widget; }); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); return null; } } @@ -246,7 +247,7 @@ export class Feedback implements Integration { try { return this._createWidget(mergeOptions(this.options, optionOverrides || {})); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); return null; } } @@ -273,7 +274,7 @@ export class Feedback implements Integration { return true; } } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); } return false; diff --git a/packages/feedback/src/util/handleFeedbackSubmit.ts b/packages/feedback/src/util/handleFeedbackSubmit.ts index eef28c8a2f29..abb3aeb1368d 100644 --- a/packages/feedback/src/util/handleFeedbackSubmit.ts +++ b/packages/feedback/src/util/handleFeedbackSubmit.ts @@ -2,6 +2,7 @@ import type { TransportMakeRequestResponse } from '@sentry/types'; import { logger } from '@sentry/utils'; import { FEEDBACK_WIDGET_SOURCE } from '../constants'; +import { DEBUG_BUILD } from '../debug-build'; import { sendFeedback } from '../sendFeedback'; import type { FeedbackFormData, SendFeedbackOptions } from '../types'; import type { DialogComponent } from '../widget/Dialog'; @@ -35,7 +36,7 @@ export async function handleFeedbackSubmit( // Success! return resp; } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); showFetchError(); } } diff --git a/packages/integration-shims/package.json b/packages/integration-shims/package.json index 8342b5fb3923..95fbcf5c44eb 100644 --- a/packages/integration-shims/package.json +++ b/packages/integration-shims/package.json @@ -43,7 +43,8 @@ "url": "https://github.com/getsentry/sentry-javascript/issues" }, "dependencies": { - "@sentry/types": "7.82.0" + "@sentry/types": "7.82.0", + "@sentry/utils": "7.82.0" }, "engines": { "node": ">=12" diff --git a/packages/integration-shims/src/BrowserTracing.ts b/packages/integration-shims/src/BrowserTracing.ts index 4b2d90d029b6..60acf4fc5df5 100644 --- a/packages/integration-shims/src/BrowserTracing.ts +++ b/packages/integration-shims/src/BrowserTracing.ts @@ -1,4 +1,5 @@ import type { Integration } from '@sentry/types'; +import { consoleSandbox } from '@sentry/utils'; /** * This is a shim for the BrowserTracing integration. @@ -20,8 +21,10 @@ class BrowserTracingShim implements Integration { public constructor(_options: any) { this.name = BrowserTracingShim.id; - // eslint-disable-next-line no-console - console.error('You are using new BrowserTracing() even though this bundle does not include tracing.'); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error('You are using new BrowserTracing() even though this bundle does not include tracing.'); + }); } /** jsdoc */ diff --git a/packages/integration-shims/src/Replay.ts b/packages/integration-shims/src/Replay.ts index a6983344ce6f..921a25c4bdfa 100644 --- a/packages/integration-shims/src/Replay.ts +++ b/packages/integration-shims/src/Replay.ts @@ -1,4 +1,5 @@ import type { Integration } from '@sentry/types'; +import { consoleSandbox } from '@sentry/utils'; /** * This is a shim for the Replay integration. @@ -20,8 +21,10 @@ class ReplayShim implements Integration { public constructor(_options: any) { this.name = ReplayShim.id; - // eslint-disable-next-line no-console - console.error('You are using new Replay() even though this bundle does not include replay.'); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error('You are using new Replay() even though this bundle does not include replay.'); + }); } /** jsdoc */ diff --git a/packages/integrations/src/debug-build.ts b/packages/integrations/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/integrations/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index 49865de3cd79..06ff147a76cb 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,6 +1,8 @@ import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -40,7 +42,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, this._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); return null; } } catch (_oO) { diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index 0ac2729e3baf..a5222fb84833 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,6 +1,8 @@ import type { Contexts, Event, EventHint, ExtendedError, Integration } from '@sentry/types'; import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** JSDoc */ interface ExtraErrorDataOptions { depth: number; @@ -127,7 +129,7 @@ function _extractErrorData(error: ExtendedError): Record | null return extraErrorInfo; } catch (oO) { - __DEBUG_BUILD__ && logger.error('Unable to extract extra data from the Error object:', oO); + DEBUG_BUILD && logger.error('Unable to extract extra data from the Error object:', oO); } return null; diff --git a/packages/integrations/src/httpclient.ts b/packages/integrations/src/httpclient.ts index 623b216e22fa..02918151817b 100644 --- a/packages/integrations/src/httpclient.ts +++ b/packages/integrations/src/httpclient.ts @@ -16,6 +16,8 @@ import { supportsNativeFetch, } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + export type HttpStatusCodeRange = [number, number] | number; export type HttpRequestTarget = string | RegExp; interface HttpClientOptions { @@ -113,7 +115,7 @@ export class HttpClient implements Integration { cookies = this._parseCookieString(cookieString); } } catch (e) { - __DEBUG_BUILD__ && logger.log(`Could not extract cookies from header ${cookieHeader}`); + DEBUG_BUILD && logger.log(`Could not extract cookies from header ${cookieHeader}`); } return { @@ -157,13 +159,13 @@ export class HttpClient implements Integration { responseCookies = this._parseCookieString(cookieString); } } catch (e) { - __DEBUG_BUILD__ && logger.log('Could not extract cookies from response headers'); + DEBUG_BUILD && logger.log('Could not extract cookies from response headers'); } try { responseHeaders = this._getXHRResponseHeaders(xhr); } catch (e) { - __DEBUG_BUILD__ && logger.log('Could not extract headers from response'); + DEBUG_BUILD && logger.log('Could not extract headers from response'); } requestHeaders = headers; @@ -333,7 +335,7 @@ export class HttpClient implements Integration { try { this._xhrResponseHandler(xhr, method, headers); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Error while extracting response event form XHR response', e); + DEBUG_BUILD && logger.warn('Error while extracting response event form XHR response', e); } }); } diff --git a/packages/integrations/src/offline.ts b/packages/integrations/src/offline.ts index bdb3d8324333..9708ffbdc050 100644 --- a/packages/integrations/src/offline.ts +++ b/packages/integrations/src/offline.ts @@ -5,6 +5,8 @@ import type { Event, EventProcessor, Hub, Integration } from '@sentry/types'; import { GLOBAL_OBJ, logger, normalize, uuid4 } from '@sentry/utils'; import localForage from 'localforage'; +import { DEBUG_BUILD } from './debug-build'; + const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; type LocalForage = { @@ -73,7 +75,7 @@ export class Offline implements Integration { if ('addEventListener' in WINDOW) { WINDOW.addEventListener('online', () => { void this._sendEvents().catch(() => { - __DEBUG_BUILD__ && logger.warn('could not send cached events'); + DEBUG_BUILD && logger.warn('could not send cached events'); }); }); } @@ -82,12 +84,12 @@ export class Offline implements Integration { if (this.hub && this.hub.getIntegration(Offline)) { // cache if we are positively offline if ('navigator' in WINDOW && 'onLine' in WINDOW.navigator && !WINDOW.navigator.onLine) { - __DEBUG_BUILD__ && logger.log('Event dropped due to being a offline - caching instead'); + DEBUG_BUILD && logger.log('Event dropped due to being a offline - caching instead'); void this._cacheEvent(event) .then((_event: Event): Promise => this._enforceMaxEvents()) .catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not cache event while offline'); + DEBUG_BUILD && logger.warn('could not cache event while offline'); }); // return null on success or failure, because being offline will still result in an error @@ -104,7 +106,7 @@ export class Offline implements Integration { // if online now, send any events stored in a previous offline session if ('navigator' in WINDOW && 'onLine' in WINDOW.navigator && WINDOW.navigator.onLine) { void this._sendEvents().catch(() => { - __DEBUG_BUILD__ && logger.warn('could not send cached events'); + DEBUG_BUILD && logger.warn('could not send cached events'); }); } } @@ -140,7 +142,7 @@ export class Offline implements Integration { ), ) .catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not enforce max events'); + DEBUG_BUILD && logger.warn('could not enforce max events'); }); } @@ -168,10 +170,10 @@ export class Offline implements Integration { this.hub.captureEvent(event); void this._purgeEvent(cacheKey).catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not purge event from cache'); + DEBUG_BUILD && logger.warn('could not purge event from cache'); }); } else { - __DEBUG_BUILD__ && logger.warn('no hub found - could not send cached event'); + DEBUG_BUILD && logger.warn('no hub found - could not send cached event'); } }); } diff --git a/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts b/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts index c1f8bdc5ccfe..2f5995b8354b 100644 --- a/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts +++ b/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts @@ -11,6 +11,8 @@ import type { NEXT_DATA as NextData } from 'next/dist/next-server/lib/utils'; import { default as Router } from 'next/router'; import type { ParsedUrlQuery } from 'querystring'; +import { DEBUG_BUILD } from '../../common/debug-build'; + const globalObject = WINDOW as typeof WINDOW & { __BUILD_MANIFEST?: { sortedPages?: string[]; @@ -62,7 +64,7 @@ function extractNextDataTagInformation(): NextDataTagInfo { try { nextData = JSON.parse(nextDataTag.innerHTML); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Could not extract __NEXT_DATA__'); + DEBUG_BUILD && logger.warn('Could not extract __NEXT_DATA__'); } } diff --git a/packages/nextjs/src/client/tunnelRoute.ts b/packages/nextjs/src/client/tunnelRoute.ts index 6f10b190727a..6ac5fb50a640 100644 --- a/packages/nextjs/src/client/tunnelRoute.ts +++ b/packages/nextjs/src/client/tunnelRoute.ts @@ -1,6 +1,8 @@ import type { BrowserOptions } from '@sentry/react'; import { dsnFromString, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; + const globalWithInjectedValues = global as typeof global & { __sentryRewritesTunnelPath__?: string; }; @@ -20,9 +22,9 @@ export function applyTunnelRouteOption(options: BrowserOptions): void { const orgId = sentrySaasDsnMatch[1]; const tunnelPath = `${tunnelRouteOption}?o=${orgId}&p=${dsnComponents.projectId}`; options.tunnel = tunnelPath; - __DEBUG_BUILD__ && logger.info(`Tunneling events to "${tunnelPath}"`); + DEBUG_BUILD && logger.info(`Tunneling events to "${tunnelPath}"`); } else { - __DEBUG_BUILD__ && logger.warn('Provided DSN is not a Sentry SaaS DSN. Will not tunnel events.'); + DEBUG_BUILD && logger.warn('Provided DSN is not a Sentry SaaS DSN. Will not tunnel events.'); } } } diff --git a/packages/nextjs/src/common/debug-build.ts b/packages/nextjs/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/nextjs/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/nextjs/src/common/utils/edgeWrapperUtils.ts b/packages/nextjs/src/common/utils/edgeWrapperUtils.ts index bdf7b389fa00..72dc2f142365 100644 --- a/packages/nextjs/src/common/utils/edgeWrapperUtils.ts +++ b/packages/nextjs/src/common/utils/edgeWrapperUtils.ts @@ -9,6 +9,7 @@ import { } from '@sentry/utils'; import type { EdgeRouteHandler } from '../../edge/types'; +import { DEBUG_BUILD } from '../debug-build'; /** * Wraps a function on the edge runtime with error and performance monitoring. @@ -41,7 +42,7 @@ export function withEdgeWrapping( ); currentScope.setPropagationContext(propagationContext); if (traceparentData) { - __DEBUG_BUILD__ && logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); + DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); } span = startTransaction({ diff --git a/packages/nextjs/src/common/utils/responseEnd.ts b/packages/nextjs/src/common/utils/responseEnd.ts index 4cc31de89fb5..35f227261089 100644 --- a/packages/nextjs/src/common/utils/responseEnd.ts +++ b/packages/nextjs/src/common/utils/responseEnd.ts @@ -3,6 +3,7 @@ import type { Transaction } from '@sentry/types'; import { fill, logger } from '@sentry/utils'; import type { ServerResponse } from 'http'; +import { DEBUG_BUILD } from '../debug-build'; import type { ResponseEndMethod, WrappedResponseEndMethod } from '../types'; /** @@ -48,10 +49,10 @@ export async function finishTransaction(transaction: Transaction | undefined, re /** Flush the event queue to ensure that events get sent to Sentry before the response is finished and the lambda ends */ export async function flushQueue(): Promise { try { - __DEBUG_BUILD__ && logger.log('Flushing events...'); + DEBUG_BUILD && logger.log('Flushing events...'); await flush(2000); - __DEBUG_BUILD__ && logger.log('Done flushing events'); + DEBUG_BUILD && logger.log('Done flushing events'); } catch (e) { - __DEBUG_BUILD__ && logger.log('Error while flushing events:\n', e); + DEBUG_BUILD && logger.log('Error while flushing events:\n', e); } } diff --git a/packages/nextjs/src/common/withServerActionInstrumentation.ts b/packages/nextjs/src/common/withServerActionInstrumentation.ts index 8f458fc728a6..dcc1c7d29382 100644 --- a/packages/nextjs/src/common/withServerActionInstrumentation.ts +++ b/packages/nextjs/src/common/withServerActionInstrumentation.ts @@ -1,6 +1,7 @@ import { addTracingExtensions, captureException, flush, getCurrentHub, runWithAsyncContext, trace } from '@sentry/core'; import { logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { platformSupportsStreaming } from './utils/platformSupportsStreaming'; interface Options { @@ -60,7 +61,7 @@ async function withServerActionInstrumentationImplementation { + // eslint-disable-next-line no-console + console.warn( + `[sentry] If Next.js logs a warning "API resolved without sending a response", it's a false positive, which may happen when you use \`withSentry\` manually to wrap your routes. + To suppress this warning, set \`SENTRY_IGNORE_API_RESOLUTION_ERROR\` to 1 in your env. + To suppress the nextjs warning, use the \`externalResolver\` API route option (see https://nextjs.org/docs/api-routes/api-middlewares#custom-config for details).`, + ); + }); } return handlerResult; diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 1e85ae125a92..5c29b2884f41 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -9,6 +9,7 @@ import * as path from 'path'; import { sync as resolveSync } from 'resolve'; import type { Compiler } from 'webpack'; +import { DEBUG_BUILD } from '../common/debug-build'; import type { VercelCronsConfig } from '../common/types'; // Note: If you need to import a type from Webpack, do it in `types.ts` and export it from there. Otherwise, our // circular dependency check thinks this file is importing from itself. See https://github.com/pahen/madge/issues/306. @@ -528,7 +529,7 @@ async function addSentryToEntryProperty( // We always skip these, so it's not worth telling the user that we've done so !['pages/_app', 'pages/_document'].includes(entryPointName) ) { - __DEBUG_BUILD__ && logger.log(`Skipping Sentry injection for ${entryPointName.replace(/^pages/, '')}`); + DEBUG_BUILD && logger.log(`Skipping Sentry injection for ${entryPointName.replace(/^pages/, '')}`); } } } @@ -662,7 +663,7 @@ function checkWebpackPluginOverrides( // warn if any of the default options for the webpack plugin are getting overridden const sentryWebpackPluginOptionOverrides = Object.keys(defaultOptions).filter(key => key in userOptions); if (sentryWebpackPluginOptionOverrides.length > 0) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( '[Sentry] You are overriding the following automatically-set SentryWebpackPlugin config options:\n' + `\t${sentryWebpackPluginOptionOverrides.toString()},\n` + @@ -1070,7 +1071,7 @@ class SentryCliDownloadPlugin implements WebpackPluginInstance { if (!downloadingCliAttempted) { downloadingCliAttempted = true; // eslint-disable-next-line no-console - console.log( + logger.info( `\n${chalk.cyan('info')} - ${chalk.bold( 'Sentry binary to upload source maps not found.', )} Package manager post-install scripts are likely disabled or there is a caching issue. Manually downloading instead...`, @@ -1086,12 +1087,12 @@ class SentryCliDownloadPlugin implements WebpackPluginInstance { cliDownloadPromise.then( () => { // eslint-disable-next-line no-console - console.log(`${chalk.cyan('info')} - Sentry binary was successfully downloaded.\n`); + logger.info(`${chalk.cyan('info')} - Sentry binary was successfully downloaded.\n`); return callback(); }, e => { // eslint-disable-next-line no-console - console.error(`${chalk.red('error')} - Sentry binary download failed:`, e); + logger.error(`${chalk.red('error')} - Sentry binary download failed:`, e); return callback(); }, ); diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 822f2619d127..a672d814bc78 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -7,6 +7,7 @@ import type { IntegrationWithExclusionOption } from '@sentry/utils'; import { addOrUpdateIntegration, escapeStringForRegex, logger } from '@sentry/utils'; import * as path from 'path'; +import { DEBUG_BUILD } from '../common/debug-build'; import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor'; import { getVercelEnv } from '../common/getVercelEnv'; import { buildMetadata } from '../common/metadata'; @@ -77,14 +78,14 @@ export function init(options: NodeOptions): void { autoSessionTracking: false, }; - if (__DEBUG_BUILD__ && opts.debug) { + if (DEBUG_BUILD && opts.debug) { logger.enable(); } - __DEBUG_BUILD__ && logger.log('Initializing SDK...'); + DEBUG_BUILD && logger.log('Initializing SDK...'); if (sdkAlreadyInitialized()) { - __DEBUG_BUILD__ && logger.log('SDK already initialized'); + DEBUG_BUILD && logger.log('SDK already initialized'); return; } @@ -113,7 +114,7 @@ export function init(options: NodeOptions): void { } }); - __DEBUG_BUILD__ && logger.log('SDK successfully initialized'); + DEBUG_BUILD && logger.log('SDK successfully initialized'); } function sdkAlreadyInitialized(): boolean { diff --git a/packages/node-experimental/src/debug-build.ts b/packages/node-experimental/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/node-experimental/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/node-experimental/src/sdk/initOtel.ts b/packages/node-experimental/src/sdk/initOtel.ts index 7b33df8431f1..285938b92c90 100644 --- a/packages/node-experimental/src/sdk/initOtel.ts +++ b/packages/node-experimental/src/sdk/initOtel.ts @@ -13,6 +13,7 @@ import { } from '@sentry/opentelemetry'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { NodeExperimentalClient } from '../types'; import { NodeExperimentalSentrySpanProcessor } from './spanProcessor'; @@ -23,7 +24,7 @@ export function initOtel(): void { const client = getClient(); if (!client) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'No client available, skipping OpenTelemetry setup. This probably means that `Sentry.init()` was not called before `initOtel()`.', ); diff --git a/packages/node/src/debug-build.ts b/packages/node/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/node/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 1a75a76a20ab..339c9553bf26 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -25,6 +25,7 @@ import { import type * as http from 'http'; import type { NodeClient } from './client'; +import { DEBUG_BUILD } from './debug-build'; // TODO (v8 / XXX) Remove this import import type { ParseRequestOptions } from './requestDataDeprecated'; import { isAutoSessionTrackingEnabled } from './sdk'; @@ -178,7 +179,7 @@ export function requestHandler( _end.call(this, chunk, encoding, cb); }) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); _end.call(this, chunk, encoding, cb); }); }; diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index 4fd2e702bb44..be5f061e62e5 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -19,6 +19,7 @@ import type * as http from 'http'; import type * as https from 'https'; import type { NodeClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { NODE_VERSION } from '../nodeVersion'; import type { RequestMethod, RequestMethodArgs, RequestOptions } from './utils/http'; import { cleanSpanDescription, extractRawUrl, extractUrl, normalizeRequestArgs } from './utils/http'; @@ -106,7 +107,7 @@ export class Http implements Integration { // Do not auto-instrument for other instrumenter if (clientOptions && clientOptions.instrumenter !== 'sentry') { - __DEBUG_BUILD__ && logger.log('HTTP Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('HTTP Integration is skipped because of instrumenter configuration.'); return; } @@ -271,7 +272,7 @@ function _createWrappedRequestMethodFactory( addHeadersToRequestOptions(requestOptions, requestUrl, sentryTraceHeader, dynamicSamplingContext); } } else { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Not adding sentry-trace header to outgoing request (${requestUrl}) due to mismatching tracePropagationTargets option.`, ); @@ -323,7 +324,7 @@ function addHeadersToRequestOptions( return; } - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`[Tracing] Adding sentry-trace header ${sentryTraceHeader} to outgoing request to "${requestUrl}": `); const sentryBaggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext); const sentryBaggageHeader = diff --git a/packages/node/src/integrations/onuncaughtexception.ts b/packages/node/src/integrations/onuncaughtexception.ts index b1699f464960..9fcd2fe5fa26 100644 --- a/packages/node/src/integrations/onuncaughtexception.ts +++ b/packages/node/src/integrations/onuncaughtexception.ts @@ -4,6 +4,7 @@ import type { Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; import type { NodeClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { logAndExitProcess } from './utils/errorhandling'; type OnFatalErrorHandler = (firstError: Error, secondError?: Error) => void; @@ -148,7 +149,7 @@ export class OnUncaughtException implements Integration { if (shouldApplyFatalHandlingLogic) { if (calledFatalError) { // we hit an error *after* calling onFatalError - pretty boned at this point, just shut it down - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'uncaught exception after calling fatal error shutdown callback - this is bad! forcing shutdown', ); diff --git a/packages/node/src/integrations/utils/errorhandling.ts b/packages/node/src/integrations/utils/errorhandling.ts index e3f03f064421..5d3abb90afce 100644 --- a/packages/node/src/integrations/utils/errorhandling.ts +++ b/packages/node/src/integrations/utils/errorhandling.ts @@ -1,7 +1,8 @@ import { getClient } from '@sentry/core'; -import { logger } from '@sentry/utils'; +import { consoleSandbox, logger } from '@sentry/utils'; import type { NodeClient } from '../../client'; +import { DEBUG_BUILD } from '../../debug-build'; const DEFAULT_SHUTDOWN_TIMEOUT = 2000; @@ -9,13 +10,15 @@ const DEFAULT_SHUTDOWN_TIMEOUT = 2000; * @hidden */ export function logAndExitProcess(error: Error): void { - // eslint-disable-next-line no-console - console.error(error); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error(error); + }); const client = getClient(); if (client === undefined) { - __DEBUG_BUILD__ && logger.warn('No NodeClient was defined, we are exiting the process now.'); + DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.'); global.process.exit(1); } @@ -26,12 +29,12 @@ export function logAndExitProcess(error: Error): void { client.close(timeout).then( (result: boolean) => { if (!result) { - __DEBUG_BUILD__ && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); + DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); } global.process.exit(1); }, error => { - __DEBUG_BUILD__ && logger.error(error); + DEBUG_BUILD && logger.error(error); }, ); } diff --git a/packages/node/src/transports/http.ts b/packages/node/src/transports/http.ts index 340bcf4800f0..7a2cd50df319 100644 --- a/packages/node/src/transports/http.ts +++ b/packages/node/src/transports/http.ts @@ -6,6 +6,7 @@ import type { TransportRequest, TransportRequestExecutor, } from '@sentry/types'; +import { consoleSandbox } from '@sentry/utils'; import * as http from 'http'; import * as https from 'https'; import { HttpsProxyAgent } from 'https-proxy-agent'; @@ -53,10 +54,12 @@ export function makeNodeTransport(options: NodeTransportOptions): Transport { try { urlSegments = new URL(options.url); } catch (e) { - // eslint-disable-next-line no-console - console.warn( - '[@sentry/node]: Invalid dsn or tunnel option, will not send any events. The tunnel option must be a full URL when used.', - ); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[@sentry/node]: Invalid dsn or tunnel option, will not send any events. The tunnel option must be a full URL when used.', + ); + }); return createTransport(options, () => Promise.resolve({})); } diff --git a/packages/opentelemetry-node/src/debug-build.ts b/packages/opentelemetry-node/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/opentelemetry-node/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/opentelemetry-node/src/spanprocessor.ts b/packages/opentelemetry-node/src/spanprocessor.ts index 98ab46c405cb..571871e1e3f0 100644 --- a/packages/opentelemetry-node/src/spanprocessor.ts +++ b/packages/opentelemetry-node/src/spanprocessor.ts @@ -7,6 +7,7 @@ import type { DynamicSamplingContext, Span as SentrySpan, TraceparentData, Trans import { logger } from '@sentry/utils'; import { SENTRY_DYNAMIC_SAMPLING_CONTEXT_KEY, SENTRY_TRACE_PARENT_CONTEXT_KEY } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import { maybeCaptureExceptionForTimedEvent } from './utils/captureExceptionForTimedEvent'; import { isSentryRequestSpan } from './utils/isSentryRequest'; import { mapOtelStatus } from './utils/mapOtelStatus'; @@ -85,8 +86,7 @@ export class SentrySpanProcessor implements OtelSpanProcessor { const sentrySpan = getSentrySpan(otelSpanId); if (!sentrySpan) { - __DEBUG_BUILD__ && - logger.error(`SentrySpanProcessor could not find span with OTEL-spanId ${otelSpanId} to finish.`); + DEBUG_BUILD && logger.error(`SentrySpanProcessor could not find span with OTEL-spanId ${otelSpanId} to finish.`); clearSpan(otelSpanId); return; } diff --git a/packages/opentelemetry/src/custom/hubextensions.ts b/packages/opentelemetry/src/custom/hubextensions.ts index 4e839a9f3314..a70cb1aaca33 100644 --- a/packages/opentelemetry/src/custom/hubextensions.ts +++ b/packages/opentelemetry/src/custom/hubextensions.ts @@ -1,5 +1,6 @@ import { addTracingExtensions as _addTracingExtensions, getMainCarrier } from '@sentry/core'; import type { CustomSamplingContext, TransactionContext } from '@sentry/types'; +import { consoleSandbox } from '@sentry/utils'; /** * Add tracing extensions, ensuring a patched `startTransaction` to work with OTEL. @@ -22,8 +23,10 @@ function startTransactionNoop( _transactionContext: TransactionContext, _customSamplingContext?: CustomSamplingContext, ): unknown { - // eslint-disable-next-line no-console - console.warn('startTransaction is a noop in @sentry/opentelemetry. Use `startSpan` instead.'); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn('startTransaction is a noop in @sentry/opentelemetry. Use `startSpan` instead.'); + }); // We return an object here as hub.ts checks for the result of this // and renders a different warning if this is empty return {}; diff --git a/packages/opentelemetry/src/custom/scope.ts b/packages/opentelemetry/src/custom/scope.ts index 9c544b018134..b65aa437b14f 100644 --- a/packages/opentelemetry/src/custom/scope.ts +++ b/packages/opentelemetry/src/custom/scope.ts @@ -4,6 +4,7 @@ import { Scope } from '@sentry/core'; import type { Breadcrumb, SeverityLevel, Span as SentrySpan } from '@sentry/types'; import { dateTimestampInSeconds, dropUndefinedKeys, logger, normalize } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { InternalSentrySemanticAttributes } from '../semanticAttributes'; import { convertOtelTimeToSeconds } from '../utils/convertOtelTimeToSeconds'; import { getActiveSpan, getRootSpan } from '../utils/getActiveSpan'; @@ -48,8 +49,7 @@ export class OpenTelemetryScope extends Scope { * Instead, use the global `getActiveSpan()`. */ public getSpan(): undefined { - __DEBUG_BUILD__ && - logger.warn('Calling getSpan() is a noop in @sentry/opentelemetry. Use `getActiveSpan()` instead.'); + DEBUG_BUILD && logger.warn('Calling getSpan() is a noop in @sentry/opentelemetry. Use `getActiveSpan()` instead.'); return undefined; } @@ -59,7 +59,7 @@ export class OpenTelemetryScope extends Scope { * Instead, use the global `startSpan()` to define the active span. */ public setSpan(_span: SentrySpan): this { - __DEBUG_BUILD__ && logger.warn('Calling setSpan() is a noop in @sentry/opentelemetry. Use `startSpan()` instead.'); + DEBUG_BUILD && logger.warn('Calling setSpan() is a noop in @sentry/opentelemetry. Use `startSpan()` instead.'); return this; } diff --git a/packages/opentelemetry/src/debug-build.ts b/packages/opentelemetry/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/opentelemetry/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/opentelemetry/src/sampler.ts b/packages/opentelemetry/src/sampler.ts index 03f82f100a87..f07dc4f8f1e4 100644 --- a/packages/opentelemetry/src/sampler.ts +++ b/packages/opentelemetry/src/sampler.ts @@ -7,6 +7,7 @@ import { hasTracingEnabled } from '@sentry/core'; import type { Client, ClientOptions, SamplingContext } from '@sentry/types'; import { isNaN, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { InternalSentrySemanticAttributes } from './semanticAttributes'; import { getPropagationContextFromContext } from './utils/contextData'; @@ -44,12 +45,11 @@ export class SentrySampler implements Sampler { if (parentContext && isSpanContextValid(parentContext) && parentContext.traceId === traceId) { if (parentContext.isRemote) { parentSampled = getParentRemoteSampled(parentContext, context); - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`[Tracing] Inheriting remote parent's sampled decision for ${spanName}: ${parentSampled}`); } else { parentSampled = Boolean(parentContext.traceFlags & TraceFlags.SAMPLED); - __DEBUG_BUILD__ && - logger.log(`[Tracing] Inheriting parent's sampled decision for ${spanName}: ${parentSampled}`); + DEBUG_BUILD && logger.log(`[Tracing] Inheriting parent's sampled decision for ${spanName}: ${parentSampled}`); } } @@ -72,7 +72,7 @@ export class SentrySampler implements Sampler { // 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(sampleRate)) { - __DEBUG_BUILD__ && logger.warn('[Tracing] Discarding span because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Tracing] Discarding span because of invalid sample rate.'); return { decision: SamplingDecision.NOT_RECORD, @@ -82,7 +82,7 @@ export class SentrySampler implements Sampler { // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped if (!sampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding span because ${ typeof options.tracesSampler === 'function' @@ -103,7 +103,7 @@ export class SentrySampler implements Sampler { // if we're not going to keep it, we're done if (!isSampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding span because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -159,7 +159,7 @@ function isValidSampleRate(rate: unknown): boolean { // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck // eslint-disable-next-line @typescript-eslint/no-explicit-any if (isNaN(rate) || !(typeof rate === 'number' || typeof rate === 'boolean')) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -170,7 +170,7 @@ function isValidSampleRate(rate: unknown): boolean { // 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) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index f2094d132733..d3c3b5b3da90 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -12,6 +12,7 @@ import { getCurrentHub } from './custom/hub'; import { OpenTelemetryScope } from './custom/scope'; import type { OpenTelemetryTransaction } from './custom/transaction'; import { startTransaction } from './custom/transaction'; +import { DEBUG_BUILD } from './debug-build'; import { InternalSentrySemanticAttributes } from './semanticAttributes'; import { convertOtelTimeToSeconds } from './utils/convertOtelTimeToSeconds'; import { getRequestSpanData } from './utils/getRequestSpanData'; @@ -54,12 +55,12 @@ export class SentrySpanExporter implements SpanExporter { const remainingOpenSpanCount = remainingSpans.length; const sentSpanCount = openSpanCount + newSpanCount - remainingOpenSpanCount; - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`SpanExporter exported ${sentSpanCount} spans, ${remainingOpenSpanCount} unsent spans remaining`); this._finishedSpans = remainingSpans.filter(span => { const shouldDrop = shouldCleanupSpan(span, 5 * 60); - __DEBUG_BUILD__ && + DEBUG_BUILD && shouldDrop && logger.log( `SpanExporter dropping span ${span.name} (${ diff --git a/packages/opentelemetry/src/spanProcessor.ts b/packages/opentelemetry/src/spanProcessor.ts index dc8bf53cf83f..a2d7de69fb00 100644 --- a/packages/opentelemetry/src/spanProcessor.ts +++ b/packages/opentelemetry/src/spanProcessor.ts @@ -5,6 +5,7 @@ import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { logger } from '@sentry/utils'; import { getCurrentHub } from './custom/hub'; +import { DEBUG_BUILD } from './debug-build'; import { SentrySpanExporter } from './spanExporter'; import { maybeCaptureExceptionForTimedEvent } from './utils/captureExceptionForTimedEvent'; import { getHubFromContext } from './utils/contextData'; @@ -57,14 +58,14 @@ export class SentrySpanProcessor extends BatchSpanProcessor implements SpanProce public onStart(span: Span, parentContext: Context): void { onSpanStart(span, parentContext); - __DEBUG_BUILD__ && logger.log(`[Tracing] Starting span "${span.name}" (${span.spanContext().spanId})`); + DEBUG_BUILD && logger.log(`[Tracing] Starting span "${span.name}" (${span.spanContext().spanId})`); return super.onStart(span, parentContext); } /** @inheritDoc */ public onEnd(span: Span): void { - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing span "${span.name}" (${span.spanContext().spanId})`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing span "${span.name}" (${span.spanContext().spanId})`); if (!this._shouldSendSpanToSentry(span)) { // Prevent this being called to super.onEnd(), which would pass this to the span exporter diff --git a/packages/opentelemetry/test/helpers/initOtel.ts b/packages/opentelemetry/test/helpers/initOtel.ts index 91be948b2f9d..e69420242a09 100644 --- a/packages/opentelemetry/test/helpers/initOtel.ts +++ b/packages/opentelemetry/test/helpers/initOtel.ts @@ -8,6 +8,7 @@ import { logger } from '@sentry/utils'; import { wrapContextManagerClass } from '../../src/contextManager'; import { getCurrentHub } from '../../src/custom/hub'; +import { DEBUG_BUILD } from '../../src/debug-build'; import { SentryPropagator } from '../../src/propagator'; import { SentrySampler } from '../../src/sampler'; import { setupEventContextTrace } from '../../src/setupEventContextTrace'; @@ -21,7 +22,7 @@ export function initOtel(): void { const client = getCurrentHub().getClient(); if (!client) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'No client available, skipping OpenTelemetry setup. This probably means that `Sentry.init()` was not called before `initOtel()`.', ); diff --git a/packages/react/src/debug-build.ts b/packages/react/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/react/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 61dd976050f6..66a026c7fe6d 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -4,6 +4,8 @@ import { isError, logger } from '@sentry/utils'; import hoistNonReactStatics from 'hoist-non-react-statics'; import * as React from 'react'; +import { DEBUG_BUILD } from './debug-build'; + export function isAtLeastReact17(version: string): boolean { const major = version.match(/^([^.]+)/); return major !== null && parseInt(major[0]) >= 17; @@ -21,12 +23,12 @@ export type FallbackRender = (errorData: { export type ErrorBoundaryProps = { children?: React.ReactNode | (() => React.ReactNode); /** If a Sentry report dialog should be rendered on error */ - showDialog?: boolean; + showDialog?: boolean | undefined; /** * Options to be passed into the Sentry report dialog. * No-op if {@link showDialog} is false. */ - dialogOptions?: ReportDialogOptions; + dialogOptions?: ReportDialogOptions | undefined; /** * A fallback component that gets rendered when the error boundary encounters an error. * @@ -35,17 +37,17 @@ export type ErrorBoundaryProps = { * the error, the component stack, and an function that resets the error boundary on error. * */ - fallback?: React.ReactElement | FallbackRender; + fallback?: React.ReactElement | FallbackRender | undefined; /** Called when the error boundary encounters an error */ - onError?(error: Error, componentStack: string, eventId: string): void; + onError?: ((error: Error, componentStack: string, eventId: string) => void) | undefined; /** Called on componentDidMount() */ - onMount?(): void; + onMount?: (() => void) | undefined; /** Called if resetError() is called from the fallback render props function */ - onReset?(error: Error | null, componentStack: string | null, eventId: string | null): void; + onReset?: ((error: Error | null, componentStack: string | null, eventId: string | null) => void) | undefined; /** Called on componentWillUnmount() */ - onUnmount?(error: Error | null, componentStack: string | null, eventId: string | null): void; + onUnmount?: ((error: Error | null, componentStack: string | null, eventId: string | null) => void) | undefined; /** Called before the error is captured by Sentry, allows for you to add tags or context using the scope */ - beforeCapture?(scope: Scope, error: Error | null, componentStack: string | null): void; + beforeCapture?: ((scope: Scope, error: Error | null, componentStack: string | null) => void) | undefined; }; type ErrorBoundaryState = @@ -208,7 +210,7 @@ class ErrorBoundary extends React.Component, R !_matchRoutes || !_customStartTransaction ) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters. useEffect: ${_useEffect}. useLocation: ${_useLocation}. useNavigationType: ${_useNavigationType}. createRoutesFromChildren: ${_createRoutesFromChildren}. matchRoutes: ${_matchRoutes}. customStartTransaction: ${_customStartTransaction}.`); @@ -218,7 +219,7 @@ export function withSentryReactRouterV6Routing

, R export function wrapUseRoutes(origUseRoutes: UseRoutes): UseRoutes { if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes || !_customStartTransaction) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters.', ); diff --git a/packages/remix/src/client/errors.tsx b/packages/remix/src/client/errors.tsx index a6afefbc0ef7..c2214bd283df 100644 --- a/packages/remix/src/client/errors.tsx +++ b/packages/remix/src/client/errors.tsx @@ -23,13 +23,14 @@ export function captureRemixErrorBoundaryError(error: unknown): string | undefin const eventData = isRemixErrorResponse ? { function: 'ErrorResponse', - ...error.data, + ...getErrorData(error), } : { function: 'ReactError', }; const actualError = isRemixErrorResponse ? getExceptionToCapture(error) : error; + eventId = captureException(actualError, { mechanism: { type: 'instrument', @@ -42,10 +43,21 @@ export function captureRemixErrorBoundaryError(error: unknown): string | undefin return eventId; } +function getErrorData(error: ErrorResponse): object { + if (isString(error.data)) { + return { + error: error.data, + }; + } + + return error.data; +} + function getExceptionToCapture(error: ErrorResponse): string | ErrorResponse { if (isString(error.data)) { return error.data; } + if (error.statusText) { return error.statusText; } diff --git a/packages/remix/src/client/performance.tsx b/packages/remix/src/client/performance.tsx index 97c455a80a94..2e597d10fa2b 100644 --- a/packages/remix/src/client/performance.tsx +++ b/packages/remix/src/client/performance.tsx @@ -4,6 +4,7 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import { isNodeEnv, logger } from '@sentry/utils'; import * as React from 'react'; +import { DEBUG_BUILD } from '../utils/debug-build'; import { getFutureFlagsBrowser, readRemixVersionFromLoader } from '../utils/futureFlags'; const DEFAULT_TAGS = { @@ -108,7 +109,7 @@ export function withSentry

, R extends React.Co const SentryRoot: React.FC

= (props: P) => { // Early return when any of the required functions is not available. if (!_useEffect || !_useLocation || !_useMatches || !_customStartTransaction) { - __DEBUG_BUILD__ && + DEBUG_BUILD && !isNodeEnv() && logger.warn('Remix SDK was unable to wrap your root because of one or more missing parameters.'); diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 80c6602e4938..747634603bc0 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -3,6 +3,7 @@ import type { NodeOptions } from '@sentry/node'; import { configureScope, getCurrentHub, init as nodeInit } from '@sentry/node'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './utils/debug-build'; import { instrumentServer } from './utils/instrumentServer'; import { buildMetadata } from './utils/metadata'; import type { RemixOptions } from './utils/remixOptions'; @@ -75,7 +76,7 @@ export function init(options: RemixOptions): void { buildMetadata(options, ['remix', 'node']); if (sdkAlreadyInitialized()) { - __DEBUG_BUILD__ && logger.log('SDK already initialized'); + DEBUG_BUILD && logger.log('SDK already initialized'); return; } diff --git a/packages/remix/src/utils/debug-build.ts b/packages/remix/src/utils/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/remix/src/utils/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/remix/src/utils/instrumentServer.ts b/packages/remix/src/utils/instrumentServer.ts index 714b6b51e09f..47d48f4a9d9c 100644 --- a/packages/remix/src/utils/instrumentServer.ts +++ b/packages/remix/src/utils/instrumentServer.ts @@ -13,6 +13,7 @@ import { tracingContextFromHeaders, } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { getFutureFlagsServer, getRemixVersionFromBuild } from './futureFlags'; import { extractData, @@ -92,7 +93,7 @@ export async function captureRemixServerException(err: unknown, name: string, re // Skip capturing if the request is aborted as Remix docs suggest // Ref: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror if (request.signal.aborted) { - __DEBUG_BUILD__ && logger.warn('Skipping capture of aborted request'); + DEBUG_BUILD && logger.warn('Skipping capture of aborted request'); return; } @@ -103,7 +104,7 @@ export async function captureRemixServerException(err: unknown, name: string, re // eslint-disable-next-line @typescript-eslint/no-explicit-any normalizedRequest = normalizeRemixRequest(request as unknown as any); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Failed to normalize Remix request'); + DEBUG_BUILD && logger.warn('Failed to normalize Remix request'); } captureException(isResponse(err) ? await extractResponseError(err) : err, scope => { @@ -278,8 +279,7 @@ function makeWrappedRootLoader(remixVersion: number) { // We skip injection of trace and baggage in those cases. // For `redirect`, a valid internal redirection target will have the trace and baggage injected. if (isRedirectResponse(res) || isCatchResponse(res)) { - __DEBUG_BUILD__ && - logger.warn('Skipping injection of trace and baggage as the response does not have a body'); + DEBUG_BUILD && logger.warn('Skipping injection of trace and baggage as the response does not have a body'); return res; } else { const data = await extractData(res); @@ -290,8 +290,7 @@ function makeWrappedRootLoader(remixVersion: number) { { headers: res.headers, statusText: res.statusText, status: res.status }, ); } else { - __DEBUG_BUILD__ && - logger.warn('Skipping injection of trace and baggage as the response body is not an object'); + DEBUG_BUILD && logger.warn('Skipping injection of trace and baggage as the response body is not an object'); return res; } } @@ -388,7 +387,7 @@ function wrapRequestHandler(origRequestHandler: RequestHandler, build: ServerBui try { normalizedRequest = normalizeRemixRequest(request); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Failed to normalize Remix request'); + DEBUG_BUILD && logger.warn('Failed to normalize Remix request'); } const url = new URL(request.url); @@ -502,7 +501,7 @@ export function instrumentServer(): void { const pkg = loadModule<{ createRequestHandler: CreateRequestHandlerFunction }>('@remix-run/server-runtime'); if (!pkg) { - __DEBUG_BUILD__ && logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); + DEBUG_BUILD && logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); return; } diff --git a/packages/remix/src/utils/serverAdapters/express.ts b/packages/remix/src/utils/serverAdapters/express.ts index 78affeaaa9ac..ab638866ffd4 100644 --- a/packages/remix/src/utils/serverAdapters/express.ts +++ b/packages/remix/src/utils/serverAdapters/express.ts @@ -4,6 +4,7 @@ import type { Transaction } from '@sentry/types'; import { extractRequestData, isString, logger } from '@sentry/utils'; import { cwd } from 'process'; +import { DEBUG_BUILD } from '../debug-build'; import { createRoutes, getTransactionName, @@ -48,7 +49,7 @@ function wrapExpressRequestHandler( pkg = await import(`${cwd()}/node_modules/react-router-dom`); } finally { if (!pkg) { - __DEBUG_BUILD__ && logger.error('Could not find `react-router-dom` package.'); + DEBUG_BUILD && logger.error('Could not find `react-router-dom` package.'); } } } @@ -151,10 +152,10 @@ async function finishSentryProcessing(res: AugmentedExpressResponse): Promise (handlerData: Handl handleClick( replay.clickDetector, result as Breadcrumb & { timestamp: number; data: { nodeId: number } }, - getClickTargetNode(handlerData.event) as HTMLElement, + getClickTargetNode(handlerData.event as Event) as HTMLElement, ); } @@ -97,7 +97,7 @@ function getDomTarget(handlerData: HandlerDataDom): { target: Node | null; messa // Accessing event.target can throw (see getsentry/raven-js#838, #768) try { - target = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event); + target = isClick ? getClickTargetNode(handlerData.event as Event) : getTargetNode(handlerData.event as Event); message = htmlTreeAsString(target, { maxStringLength: 200 }) || ''; } catch (e) { message = ''; diff --git a/packages/replay/src/coreHandlers/handleGlobalEvent.ts b/packages/replay/src/coreHandlers/handleGlobalEvent.ts index b9fc329796f4..16cc9d9f8750 100644 --- a/packages/replay/src/coreHandlers/handleGlobalEvent.ts +++ b/packages/replay/src/coreHandlers/handleGlobalEvent.ts @@ -1,6 +1,7 @@ import type { Event, EventHint } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { ReplayContainer } from '../types'; import { isErrorEvent, isFeedbackEvent, isReplayEvent, isTransactionEvent } from '../util/eventUtils'; import { isRrwebError } from '../util/isRrwebError'; @@ -53,7 +54,7 @@ export function handleGlobalEventListener( // Unless `captureExceptions` is enabled, we want to ignore errors coming from rrweb // As there can be a bunch of stuff going wrong in internals there, that we don't want to bubble up to users if (isRrwebError(event, hint) && !replay.getOptions()._experiments.captureExceptions) { - __DEBUG_BUILD__ && logger.log('[Replay] Ignoring error from rrweb internals', event); + DEBUG_BUILD && logger.log('[Replay] Ignoring error from rrweb internals', event); return null; } diff --git a/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts b/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts index 8fa2e1c7acb1..1ee12c7f5fe0 100644 --- a/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts +++ b/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts @@ -8,6 +8,7 @@ import type { } from '@sentry/types'; import { addFetchInstrumentationHandler, addXhrInstrumentationHandler, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { FetchHint, ReplayContainer, ReplayNetworkOptions, XhrHint } from '../types'; import { handleFetchSpanListener } from './handleFetch'; import { handleXhrSpanListener } from './handleXhr'; @@ -90,7 +91,7 @@ export function beforeAddNetworkBreadcrumb( void captureFetchBreadcrumbToReplay(breadcrumb, hint, options); } } catch (e) { - __DEBUG_BUILD__ && logger.warn('Error when enriching network breadcrumb'); + DEBUG_BUILD && logger.warn('Error when enriching network breadcrumb'); } } diff --git a/packages/replay/src/coreHandlers/util/domUtils.ts b/packages/replay/src/coreHandlers/util/domUtils.ts index 83f34dc19f31..889ccd0c6052 100644 --- a/packages/replay/src/coreHandlers/util/domUtils.ts +++ b/packages/replay/src/coreHandlers/util/domUtils.ts @@ -1,5 +1,4 @@ import type { INode } from '@sentry-internal/rrweb-snapshot'; -import type { HandlerDataDom } from '@sentry/types'; const INTERACTIVE_SELECTOR = 'button,a'; @@ -15,7 +14,7 @@ export function getClosestInteractive(element: Element): Element { * This is useful because if you click on the image in , * The target will be the image, not the button, which we don't want here */ -export function getClickTargetNode(event: HandlerDataDom['event'] | MouseEvent | Node): Node | INode | null { +export function getClickTargetNode(event: Event | MouseEvent | Node): Node | INode | null { const target = getTargetNode(event); if (!target || !(target instanceof Element)) { diff --git a/packages/replay/src/coreHandlers/util/fetchUtils.ts b/packages/replay/src/coreHandlers/util/fetchUtils.ts index 9e0ac27c7d38..5b569b659f9d 100644 --- a/packages/replay/src/coreHandlers/util/fetchUtils.ts +++ b/packages/replay/src/coreHandlers/util/fetchUtils.ts @@ -1,6 +1,7 @@ import type { Breadcrumb, FetchBreadcrumbData, TextEncoderInternal } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../debug-build'; import type { FetchHint, NetworkMetaWarning, @@ -41,7 +42,7 @@ export async function captureFetchBreadcrumbToReplay( const result = makeNetworkReplayBreadcrumb('resource.fetch', data); addNetworkBreadcrumb(options.replay, result); } catch (error) { - __DEBUG_BUILD__ && logger.error('[Replay] Failed to capture fetch breadcrumb', error); + DEBUG_BUILD && logger.error('[Replay] Failed to capture fetch breadcrumb', error); } } @@ -201,7 +202,7 @@ function getResponseData( return buildNetworkRequestOrResponse(headers, size, undefined); } catch (error) { - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to serialize response body', error); + DEBUG_BUILD && logger.warn('[Replay] Failed to serialize response body', error); // fallback return buildNetworkRequestOrResponse(headers, responseBodySize, undefined); } @@ -218,7 +219,7 @@ async function _parseFetchResponseBody(response: Response): Promise<[string | un const text = await _tryGetResponseText(res); return [text]; } catch (error) { - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to get text body from response', error); + DEBUG_BUILD && logger.warn('[Replay] Failed to get text body from response', error); return [undefined, 'BODY_PARSE_ERROR']; } } @@ -288,7 +289,7 @@ function _tryCloneResponse(response: Response): Response | void { return response.clone(); } catch (error) { // this can throw if the response was already consumed before - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to clone response body', error); + DEBUG_BUILD && logger.warn('[Replay] Failed to clone response body', error); } } diff --git a/packages/replay/src/coreHandlers/util/networkUtils.ts b/packages/replay/src/coreHandlers/util/networkUtils.ts index ac11f652fb40..5037d5a6769c 100644 --- a/packages/replay/src/coreHandlers/util/networkUtils.ts +++ b/packages/replay/src/coreHandlers/util/networkUtils.ts @@ -2,6 +2,7 @@ import type { TextEncoderInternal } from '@sentry/types'; import { dropUndefinedKeys, logger, stringMatchesSomePattern } from '@sentry/utils'; import { NETWORK_BODY_MAX_SIZE, WINDOW } from '../../constants'; +import { DEBUG_BUILD } from '../../debug-build'; import type { NetworkBody, NetworkMetaWarning, @@ -75,11 +76,11 @@ export function getBodyString(body: unknown): [string | undefined, NetworkMetaWa return [_serializeFormData(body)]; } } catch { - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to serialize body', body); + DEBUG_BUILD && logger.warn('[Replay] Failed to serialize body', body); return [undefined, 'BODY_PARSE_ERROR']; } - __DEBUG_BUILD__ && logger.info('[Replay] Skipping network body because of body type', body); + DEBUG_BUILD && logger.info('[Replay] Skipping network body because of body type', body); return [undefined]; } diff --git a/packages/replay/src/coreHandlers/util/xhrUtils.ts b/packages/replay/src/coreHandlers/util/xhrUtils.ts index 38195f045ed4..db3e8eab7d93 100644 --- a/packages/replay/src/coreHandlers/util/xhrUtils.ts +++ b/packages/replay/src/coreHandlers/util/xhrUtils.ts @@ -1,6 +1,7 @@ import type { Breadcrumb, TextEncoderInternal, XhrBreadcrumbData } from '@sentry/types'; import { logger, SENTRY_XHR_DATA_KEY } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../debug-build'; import type { NetworkMetaWarning, ReplayContainer, @@ -37,7 +38,7 @@ export async function captureXhrBreadcrumbToReplay( const result = makeNetworkReplayBreadcrumb('resource.xhr', data); addNetworkBreadcrumb(options.replay, result); } catch (error) { - __DEBUG_BUILD__ && logger.error('[Replay] Failed to capture xhr breadcrumb', error); + DEBUG_BUILD && logger.error('[Replay] Failed to capture xhr breadcrumb', error); } } @@ -159,7 +160,7 @@ function _getXhrResponseBody(xhr: XMLHttpRequest): [string | undefined, NetworkM errors.push(e); } - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to get xhr response body', ...errors); + DEBUG_BUILD && logger.warn('[Replay] Failed to get xhr response body', ...errors); return [undefined]; } diff --git a/packages/replay/src/debug-build.ts b/packages/replay/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/replay/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/replay/src/eventBuffer/EventBufferProxy.ts b/packages/replay/src/eventBuffer/EventBufferProxy.ts index eb49b7229c58..af6645a89e69 100644 --- a/packages/replay/src/eventBuffer/EventBufferProxy.ts +++ b/packages/replay/src/eventBuffer/EventBufferProxy.ts @@ -1,6 +1,7 @@ import type { ReplayRecordingData } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { AddEventResult, EventBuffer, EventBufferType, RecordingEvent } from '../types'; import { logInfo } from '../util/log'; import { EventBufferArray } from './EventBufferArray'; @@ -116,7 +117,7 @@ export class EventBufferProxy implements EventBuffer { try { await Promise.all(addEventPromises); } catch (error) { - __DEBUG_BUILD__ && logger.warn('[Replay] Failed to add events when switching buffers.', error); + DEBUG_BUILD && logger.warn('[Replay] Failed to add events when switching buffers.', error); } } } diff --git a/packages/replay/src/eventBuffer/WorkerHandler.ts b/packages/replay/src/eventBuffer/WorkerHandler.ts index f9a84c6bdbf1..1014521e652f 100644 --- a/packages/replay/src/eventBuffer/WorkerHandler.ts +++ b/packages/replay/src/eventBuffer/WorkerHandler.ts @@ -1,5 +1,6 @@ import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { WorkerRequest, WorkerResponse } from '../types'; import { logInfo } from '../util/log'; @@ -84,7 +85,7 @@ export class WorkerHandler { if (!response.success) { // TODO: Do some error handling, not sure what - __DEBUG_BUILD__ && logger.error('[Replay]', response.response); + DEBUG_BUILD && logger.error('[Replay]', response.response); reject(new Error('Error in compression worker')); return; diff --git a/packages/replay/src/integration.ts b/packages/replay/src/integration.ts index b94907d44938..80bbeca5fdf3 100644 --- a/packages/replay/src/integration.ts +++ b/packages/replay/src/integration.ts @@ -1,6 +1,6 @@ import { getClient } from '@sentry/core'; import type { BrowserClientReplayOptions, Integration } from '@sentry/types'; -import { dropUndefinedKeys, isBrowser } from '@sentry/utils'; +import { consoleSandbox, dropUndefinedKeys, isBrowser } from '@sentry/utils'; import { DEFAULT_FLUSH_MAX_DELAY, @@ -349,8 +349,10 @@ function loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions) const finalOptions = { sessionSampleRate: 0, errorSampleRate: 0, ...dropUndefinedKeys(initialOptions) }; if (!opt) { - // eslint-disable-next-line no-console - console.warn('SDK client is not available.'); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn('SDK client is not available.'); + }); return finalOptions; } @@ -360,10 +362,12 @@ function loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions) opt.replaysSessionSampleRate == null && opt.replaysOnErrorSampleRate == null ) { - // eslint-disable-next-line no-console - console.warn( - 'Replay is disabled because neither `replaysSessionSampleRate` nor `replaysOnErrorSampleRate` are set.', - ); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + 'Replay is disabled because neither `replaysSessionSampleRate` nor `replaysOnErrorSampleRate` are set.', + ); + }); } if (typeof opt.replaysSessionSampleRate === 'number') { diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index f4368c1d0930..9501db156c82 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -15,6 +15,7 @@ import { import { ClickDetector } from './coreHandlers/handleClick'; import { handleKeyboardEvent } from './coreHandlers/handleKeyboardEvent'; import { setupPerformanceObserver } from './coreHandlers/performanceObserver'; +import { DEBUG_BUILD } from './debug-build'; import { createEventBuffer } from './eventBuffer'; import { clearSession } from './session/clearSession'; import { loadOrCreateSession } from './session/loadOrCreateSession'; @@ -726,9 +727,9 @@ export class ReplayContainer implements ReplayContainerInterface { /** A wrapper to conditionally capture exceptions. */ private _handleException(error: unknown): void { - __DEBUG_BUILD__ && logger.error('[Replay]', error); + DEBUG_BUILD && logger.error('[Replay]', error); - if (__DEBUG_BUILD__ && this._options._experiments && this._options._experiments.captureExceptions) { + if (DEBUG_BUILD && this._options._experiments && this._options._experiments.captureExceptions) { captureException(error); } } @@ -1045,7 +1046,7 @@ export class ReplayContainer implements ReplayContainerInterface { const replayId = this.getSessionId(); if (!this.session || !this.eventBuffer || !replayId) { - __DEBUG_BUILD__ && logger.error('[Replay] No session or eventBuffer found to flush.'); + DEBUG_BUILD && logger.error('[Replay] No session or eventBuffer found to flush.'); return; } @@ -1135,7 +1136,7 @@ export class ReplayContainer implements ReplayContainerInterface { } if (!this.checkAndHandleExpiredSession()) { - __DEBUG_BUILD__ && logger.error('[Replay] Attempting to finish replay event after session expired.'); + DEBUG_BUILD && logger.error('[Replay] Attempting to finish replay event after session expired.'); return; } @@ -1193,7 +1194,7 @@ export class ReplayContainer implements ReplayContainerInterface { try { await this._flushLock; } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); } finally { this._debouncedFlush(); } diff --git a/packages/replay/src/util/addEvent.ts b/packages/replay/src/util/addEvent.ts index fcfd13b3a10e..7ea5d165eac5 100644 --- a/packages/replay/src/util/addEvent.ts +++ b/packages/replay/src/util/addEvent.ts @@ -2,6 +2,7 @@ import { EventType } from '@sentry-internal/rrweb'; import { getClient } from '@sentry/core'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { EventBufferSizeExceededError } from '../eventBuffer/error'; import type { AddEventResult, RecordingEvent, ReplayContainer, ReplayFrameEvent, ReplayPluginOptions } from '../types'; import { logInfo } from './log'; @@ -77,7 +78,7 @@ async function _addEvent( } catch (error) { const reason = error && error instanceof EventBufferSizeExceededError ? 'addEventSizeExceeded' : 'addEvent'; - __DEBUG_BUILD__ && logger.error(error); + DEBUG_BUILD && logger.error(error); await replay.stop({ reason }); const client = getClient(); @@ -125,7 +126,7 @@ function maybeApplyCallback( return callback(event); } } catch (error) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error('[Replay] An error occured in the `beforeAddRecordingEvent` callback, skipping the event...', error); return null; } diff --git a/packages/replay/src/util/getPrivacyOptions.ts b/packages/replay/src/util/getPrivacyOptions.ts index c37075923d90..7d0584b7ba7b 100644 --- a/packages/replay/src/util/getPrivacyOptions.ts +++ b/packages/replay/src/util/getPrivacyOptions.ts @@ -1,3 +1,5 @@ +import { consoleSandbox } from '@sentry/utils'; + import type { DeprecatedPrivacyOptions, ReplayIntegrationPrivacyOptions } from '../types'; type GetPrivacyOptions = Required> & @@ -37,10 +39,12 @@ function getOption( allSelectors.push(`.${deprecatedClassOption}`); } - // eslint-disable-next-line no-console - console.warn( - '[Replay] You are using a deprecated configuration item for privacy. Read the documentation on how to use the new privacy configuration.', - ); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[Replay] You are using a deprecated configuration item for privacy. Read the documentation on how to use the new privacy configuration.', + ); + }); } return allSelectors.join(','); diff --git a/packages/replay/src/util/handleRecordingEmit.ts b/packages/replay/src/util/handleRecordingEmit.ts index ac7d098825b4..3ab420a717b1 100644 --- a/packages/replay/src/util/handleRecordingEmit.ts +++ b/packages/replay/src/util/handleRecordingEmit.ts @@ -2,6 +2,7 @@ import { EventType } from '@sentry-internal/rrweb'; import { logger } from '@sentry/utils'; import { updateClickDetectorForRecordingEvent } from '../coreHandlers/handleClick'; +import { DEBUG_BUILD } from '../debug-build'; import { saveSession } from '../session/saveSession'; import type { RecordingEvent, ReplayContainer, ReplayOptionFrameEvent } from '../types'; import { addEventSync } from './addEvent'; @@ -20,7 +21,7 @@ export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCa return (event: RecordingEvent, _isCheckout?: boolean) => { // If this is false, it means session is expired, create and a new session and wait for checkout if (!replay.checkAndHandleExpiredSession()) { - __DEBUG_BUILD__ && logger.warn('[Replay] Received replay event after session expired.'); + DEBUG_BUILD && logger.warn('[Replay] Received replay event after session expired.'); return; } diff --git a/packages/replay/src/util/log.ts b/packages/replay/src/util/log.ts index 9aa650a81264..96b6e76dc498 100644 --- a/packages/replay/src/util/log.ts +++ b/packages/replay/src/util/log.ts @@ -1,11 +1,13 @@ import { getCurrentHub } from '@sentry/core'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** * Log a message in debug mode, and add a breadcrumb when _experiment.traceInternals is enabled. */ export function logInfo(message: string, shouldAddBreadcrumb?: boolean): void { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return; } @@ -21,7 +23,7 @@ export function logInfo(message: string, shouldAddBreadcrumb?: boolean): void { * This is necessary when the breadcrumb may be added before the replay is initialized. */ export function logInfoNextTick(message: string, shouldAddBreadcrumb?: boolean): void { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return; } diff --git a/packages/replay/src/util/sendReplay.ts b/packages/replay/src/util/sendReplay.ts index 645a6573e727..9aea14be4a16 100644 --- a/packages/replay/src/util/sendReplay.ts +++ b/packages/replay/src/util/sendReplay.ts @@ -1,6 +1,7 @@ import { captureException, setContext } from '@sentry/core'; import { RETRY_BASE_INTERVAL, RETRY_MAX_COUNT, UNABLE_TO_SEND_REPLAY } from '../constants'; +import { DEBUG_BUILD } from '../debug-build'; import type { SendReplayData } from '../types'; import { RateLimitError, sendReplayRequest, TransportStatusCodeError } from './sendReplayRequest'; @@ -34,7 +35,7 @@ export async function sendReplay( _retryCount: retryConfig.count, }); - if (__DEBUG_BUILD__ && options._experiments && options._experiments.captureExceptions) { + if (DEBUG_BUILD && options._experiments && options._experiments.captureExceptions) { captureException(err); } diff --git a/packages/replay/src/util/shouldFilterRequest.ts b/packages/replay/src/util/shouldFilterRequest.ts index fcfd75b1b048..274ad4ee488a 100644 --- a/packages/replay/src/util/shouldFilterRequest.ts +++ b/packages/replay/src/util/shouldFilterRequest.ts @@ -1,5 +1,6 @@ import { getCurrentHub, isSentryRequestUrl } from '@sentry/core'; +import { DEBUG_BUILD } from '../debug-build'; import type { ReplayContainer } from '../types'; /** @@ -8,7 +9,7 @@ import type { ReplayContainer } from '../types'; */ export function shouldFilterRequest(replay: ReplayContainer, url: string): boolean { // If we enabled the `traceInternals` experiment, we want to trace everything - if (__DEBUG_BUILD__ && replay.getOptions()._experiments.traceInternals) { + if (DEBUG_BUILD && replay.getOptions()._experiments.traceInternals) { return false; } diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 78578083ee72..97dec35a6113 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -14,6 +14,7 @@ import { performance } from 'perf_hooks'; import { types } from 'util'; import { AWSServices } from './awsservices'; +import { DEBUG_BUILD } from './debug-build'; import { markEventUnhandled } from './utils'; export * from '@sentry/node'; @@ -131,7 +132,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDesc = basename(handlerPath); const match = handlerDesc.match(/^([^.]*)\.(.*)$/); if (!match) { - __DEBUG_BUILD__ && logger.error(`Bad handler ${handlerDesc}`); + DEBUG_BUILD && logger.error(`Bad handler ${handlerDesc}`); return; } @@ -142,7 +143,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDir = handlerPath.substring(0, handlerPath.indexOf(handlerDesc)); obj = tryRequire(taskRoot, handlerDir, handlerMod); } catch (e) { - __DEBUG_BUILD__ && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); + DEBUG_BUILD && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); return; } @@ -154,11 +155,11 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { functionName = name; }); if (!obj) { - __DEBUG_BUILD__ && logger.error(`${handlerPath} is undefined or not exported`); + DEBUG_BUILD && logger.error(`${handlerPath} is undefined or not exported`); return; } if (typeof obj !== 'function') { - __DEBUG_BUILD__ && logger.error(`${handlerPath} is not a function`); + DEBUG_BUILD && logger.error(`${handlerPath} is not a function`); return; } @@ -345,7 +346,7 @@ export function wrapHandler( transaction?.finish(); hub.popScope(); await flush(options.flushTimeout).catch(e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }); } return rv; diff --git a/packages/serverless/src/debug-build.ts b/packages/serverless/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/serverless/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/serverless/src/gcpfunction/cloud_events.ts b/packages/serverless/src/gcpfunction/cloud_events.ts index a0d843e71abe..05595867c191 100644 --- a/packages/serverless/src/gcpfunction/cloud_events.ts +++ b/packages/serverless/src/gcpfunction/cloud_events.ts @@ -1,6 +1,7 @@ import { captureException, flush, getCurrentHub } from '@sentry/node'; import { isThenable, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from '../utils'; import type { CloudEventFunction, CloudEventFunctionWithCallback, WrapperOptions } from './general'; @@ -56,7 +57,7 @@ function _wrapCloudEventFunction( void flush(options.flushTimeout) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { callback(...args); diff --git a/packages/serverless/src/gcpfunction/events.ts b/packages/serverless/src/gcpfunction/events.ts index 9c98fcb8c485..c3be42c6a6c2 100644 --- a/packages/serverless/src/gcpfunction/events.ts +++ b/packages/serverless/src/gcpfunction/events.ts @@ -1,6 +1,7 @@ import { captureException, flush, getCurrentHub } from '@sentry/node'; import { isThenable, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from '../utils'; import type { EventFunction, EventFunctionWithCallback, WrapperOptions } from './general'; @@ -58,7 +59,7 @@ function _wrapEventFunction void flush(options.flushTimeout) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { if (typeof callback === 'function') { diff --git a/packages/serverless/src/gcpfunction/http.ts b/packages/serverless/src/gcpfunction/http.ts index eea492bb8dab..8f4a77099696 100644 --- a/packages/serverless/src/gcpfunction/http.ts +++ b/packages/serverless/src/gcpfunction/http.ts @@ -2,6 +2,7 @@ import type { AddRequestDataToEventOptions } from '@sentry/node'; import { captureException, flush, getCurrentHub } from '@sentry/node'; import { isString, isThenable, logger, stripUrlQueryAndFragment, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from './../utils'; import type { HttpFunction, WrapperOptions } from './general'; @@ -111,7 +112,7 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { _end.call(this, chunk, encoding, cb); diff --git a/packages/sveltekit/src/client/handleError.ts b/packages/sveltekit/src/client/handleError.ts index 6c8a30fb1e03..6c16cee0ebbd 100644 --- a/packages/sveltekit/src/client/handleError.ts +++ b/packages/sveltekit/src/client/handleError.ts @@ -1,4 +1,5 @@ import { captureException } from '@sentry/svelte'; +import { consoleSandbox } from '@sentry/utils'; // For now disable the import/no-unresolved rule, because we don't have a way to // tell eslint that we are only importing types from the @sveltejs/kit package without // adding a custom resolver, which will take too much time. @@ -8,8 +9,10 @@ import type { HandleClientError, NavigationEvent } from '@sveltejs/kit'; // The SvelteKit default error handler just logs the error to the console // see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/core/sync/write_client_manifest.js#LL127C2-L127C2 function defaultErrorHandler({ error }: Parameters[0]): ReturnType { - // eslint-disable-next-line no-console - console.error(error); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error(error); + }); } /** diff --git a/packages/sveltekit/src/common/debug-build.ts b/packages/sveltekit/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/sveltekit/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/sveltekit/src/server/utils.ts b/packages/sveltekit/src/server/utils.ts index cf591568486b..719771d50c57 100644 --- a/packages/sveltekit/src/server/utils.ts +++ b/packages/sveltekit/src/server/utils.ts @@ -3,6 +3,7 @@ import type { StackFrame } from '@sentry/types'; import { basename, escapeStringForRegex, GLOBAL_OBJ, join, logger, tracingContextFromHeaders } from '@sentry/utils'; import type { RequestEvent } from '@sveltejs/kit'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WRAPPED_MODULE_SUFFIX } from '../vite/autoInstrument'; import type { GlobalWithSentryValues } from '../vite/injectGlobalValues'; @@ -76,11 +77,11 @@ export async function flushIfServerless(): Promise { if (!platformSupportsStreaming) { try { - __DEBUG_BUILD__ && logger.log('Flushing events...'); + DEBUG_BUILD && logger.log('Flushing events...'); await flush(2000); - __DEBUG_BUILD__ && logger.log('Done flushing events'); + DEBUG_BUILD && logger.log('Done flushing events'); } catch (e) { - __DEBUG_BUILD__ && logger.log('Error while flushing events:\n', e); + DEBUG_BUILD && logger.log('Error while flushing events:\n', e); } } } diff --git a/packages/tracing-internal/src/browser/backgroundtab.ts b/packages/tracing-internal/src/browser/backgroundtab.ts index e061f39925a1..7d65941c8d43 100644 --- a/packages/tracing-internal/src/browser/backgroundtab.ts +++ b/packages/tracing-internal/src/browser/backgroundtab.ts @@ -2,6 +2,7 @@ import type { IdleTransaction, SpanStatusType } from '@sentry/core'; import { getActiveTransaction } from '@sentry/core'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WINDOW } from './types'; /** @@ -15,7 +16,7 @@ export function registerBackgroundTabDetection(): void { if (WINDOW.document.hidden && activeTransaction) { const statusType: SpanStatusType = 'cancelled'; - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Transaction: ${statusType} -> since tab moved to the background, op: ${activeTransaction.op}`, ); @@ -29,7 +30,6 @@ export function registerBackgroundTabDetection(): void { } }); } else { - __DEBUG_BUILD__ && - logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); + DEBUG_BUILD && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); } } diff --git a/packages/tracing-internal/src/browser/browsertracing.ts b/packages/tracing-internal/src/browser/browsertracing.ts index a11ea7ff2cf2..f1ee79c39679 100644 --- a/packages/tracing-internal/src/browser/browsertracing.ts +++ b/packages/tracing-internal/src/browser/browsertracing.ts @@ -4,6 +4,7 @@ import { addTracingExtensions, getActiveTransaction, startIdleTransaction, TRACI import type { EventProcessor, Integration, Transaction, TransactionContext, TransactionSource } from '@sentry/types'; import { getDomElement, logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { registerBackgroundTabDetection } from './backgroundtab'; import { addPerformanceEntries, @@ -179,7 +180,7 @@ export class BrowserTracing implements Integration { addTracingExtensions(); - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { this._hasSetTracePropagationTargets = !!( _options && // eslint-disable-next-line deprecation/deprecation @@ -250,7 +251,7 @@ export class BrowserTracing implements Integration { // If both 1 and either one of 2 or 3 are set (from above), we log out a warning. // eslint-disable-next-line deprecation/deprecation const tracePropagationTargets = clientOptionsTracePropagationTargets || this.options.tracePropagationTargets; - if (__DEBUG_BUILD__ && this._hasSetTracePropagationTargets && clientOptionsTracePropagationTargets) { + if (DEBUG_BUILD && this._hasSetTracePropagationTargets && clientOptionsTracePropagationTargets) { logger.warn( '[Tracing] The `tracePropagationTargets` option was set in the BrowserTracing integration and top level `Sentry.init`. The top level `Sentry.init` value is being used.', ); @@ -289,7 +290,7 @@ export class BrowserTracing implements Integration { /** Create routing idle transaction. */ private _createRouteTransaction(context: TransactionContext): Transaction | undefined { if (!this._getCurrentHub) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`); return undefined; } @@ -333,11 +334,10 @@ export class BrowserTracing implements Integration { this._latestRouteSource = finalContext.metadata && finalContext.metadata.source; if (finalContext.sampled === false) { - __DEBUG_BUILD__ && - logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); + DEBUG_BUILD && logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); } - __DEBUG_BUILD__ && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); + DEBUG_BUILD && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); const { location } = WINDOW; @@ -385,7 +385,7 @@ export class BrowserTracing implements Integration { const currentTransaction = getActiveTransaction(); if (currentTransaction && currentTransaction.op && ['navigation', 'pageload'].includes(currentTransaction.op)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Did not create ${op} transaction because a pageload or navigation transaction is in progress.`, ); @@ -399,13 +399,12 @@ export class BrowserTracing implements Integration { } if (!this._getCurrentHub) { - __DEBUG_BUILD__ && logger.warn(`[Tracing] Did not create ${op} transaction because _getCurrentHub is invalid.`); + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _getCurrentHub is invalid.`); return undefined; } if (!this._latestRouteName) { - __DEBUG_BUILD__ && - logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`); + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`); return undefined; } diff --git a/packages/tracing-internal/src/browser/instrument.ts b/packages/tracing-internal/src/browser/instrument.ts index 85c2aeccb43e..ae4532259f94 100644 --- a/packages/tracing-internal/src/browser/instrument.ts +++ b/packages/tracing-internal/src/browser/instrument.ts @@ -1,5 +1,6 @@ import { getFunctionName, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { onCLS } from './web-vitals/getCLS'; import { onFID } from './web-vitals/getFID'; import { onLCP } from './web-vitals/getLCP'; @@ -148,7 +149,7 @@ function triggerHandlers(type: InstrumentHandlerType, data: unknown): void { try { handler(data); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, diff --git a/packages/tracing-internal/src/browser/metrics/index.ts b/packages/tracing-internal/src/browser/metrics/index.ts index 4d28f6102cde..c7a37a210d80 100644 --- a/packages/tracing-internal/src/browser/metrics/index.ts +++ b/packages/tracing-internal/src/browser/metrics/index.ts @@ -4,6 +4,7 @@ import { getActiveTransaction } from '@sentry/core'; import type { Measurements } from '@sentry/types'; import { browserPerformanceTimeOrigin, htmlTreeAsString, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import { addClsInstrumentationHandler, addFidInstrumentationHandler, @@ -121,7 +122,7 @@ function _trackCLS(): () => void { return; } - __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS'); + DEBUG_BUILD && logger.log('[Measurements] Adding CLS'); _measurements['cls'] = { value: metric.value, unit: '' }; _clsEntry = entry as LayoutShift; }); @@ -135,7 +136,7 @@ function _trackLCP(): () => void { return; } - __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP'); + DEBUG_BUILD && logger.log('[Measurements] Adding LCP'); _measurements['lcp'] = { value: metric.value, unit: 'millisecond' }; _lcpEntry = entry as LargestContentfulPaint; }); @@ -151,7 +152,7 @@ function _trackFID(): () => void { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FID'); + DEBUG_BUILD && logger.log('[Measurements] Adding FID'); _measurements['fid'] = { value: metric.value, unit: 'millisecond' }; _measurements['mark.fid'] = { value: timeOrigin + startTime, unit: 'second' }; }); @@ -165,7 +166,7 @@ export function addPerformanceEntries(transaction: Transaction): void { return; } - __DEBUG_BUILD__ && logger.log('[Tracing] Adding & adjusting spans using Performance API'); + DEBUG_BUILD && logger.log('[Tracing] Adding & adjusting spans using Performance API'); const timeOrigin = msToSec(browserPerformanceTimeOrigin); const performanceEntries = performance.getEntries(); @@ -200,11 +201,11 @@ export function addPerformanceEntries(transaction: Transaction): void { const shouldRecord = entry.startTime < firstHidden.firstHiddenTime; if (entry.name === 'first-paint' && shouldRecord) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FP'); + DEBUG_BUILD && logger.log('[Measurements] Adding FP'); _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' }; } if (entry.name === 'first-contentful-paint' && shouldRecord) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FCP'); + DEBUG_BUILD && logger.log('[Measurements] Adding FCP'); _measurements['fcp'] = { value: entry.startTime, unit: 'millisecond' }; } break; @@ -228,7 +229,7 @@ export function addPerformanceEntries(transaction: Transaction): void { // Generate TTFB (Time to First Byte), which measured as the time between the beginning of the transaction and the // start of the response in milliseconds if (typeof responseStartTimestamp === 'number') { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding TTFB'); + DEBUG_BUILD && logger.log('[Measurements] Adding TTFB'); _measurements['ttfb'] = { value: (responseStartTimestamp - transaction.startTimestamp) * 1000, unit: 'millisecond', @@ -258,8 +259,7 @@ export function addPerformanceEntries(transaction: Transaction): void { const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000); const delta = normalizedValue - oldValue; - __DEBUG_BUILD__ && - logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); + DEBUG_BUILD && logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); _measurements[name].value = normalizedValue; }); @@ -461,7 +461,7 @@ function _trackNavigator(transaction: Transaction): void { /** Add LCP / CLS data to transaction to allow debugging */ function _tagMetricInfo(transaction: Transaction): void { if (_lcpEntry) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP Data'); + DEBUG_BUILD && logger.log('[Measurements] Adding LCP Data'); // Capture Properties of the LCP element that contributes to the LCP. @@ -483,7 +483,7 @@ function _tagMetricInfo(transaction: Transaction): void { // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift if (_clsEntry && _clsEntry.sources) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS Data'); + DEBUG_BUILD && logger.log('[Measurements] Adding CLS Data'); _clsEntry.sources.forEach((source, index) => transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), ); diff --git a/packages/tracing-internal/src/browser/router.ts b/packages/tracing-internal/src/browser/router.ts index 98656d4d3f2a..472c2e9fec05 100644 --- a/packages/tracing-internal/src/browser/router.ts +++ b/packages/tracing-internal/src/browser/router.ts @@ -1,6 +1,7 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import { addHistoryInstrumentationHandler, browserPerformanceTimeOrigin, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WINDOW } from './types'; /** @@ -12,7 +13,7 @@ export function instrumentRoutingWithDefaults( startTransactionOnLocationChange: boolean = true, ): void { if (!WINDOW || !WINDOW.location) { - __DEBUG_BUILD__ && logger.warn('Could not initialize routing instrumentation due to invalid location'); + DEBUG_BUILD && logger.warn('Could not initialize routing instrumentation due to invalid location'); return; } @@ -49,7 +50,7 @@ export function instrumentRoutingWithDefaults( if (from !== to) { startingUrl = undefined; if (activeTransaction) { - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); // If there's an open transaction on the scope, we need to finish it before creating an new one. activeTransaction.finish(); } diff --git a/packages/tracing-internal/src/common/debug-build.ts b/packages/tracing-internal/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/tracing-internal/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/tracing-internal/src/node/integrations/apollo.ts b/packages/tracing-internal/src/node/integrations/apollo.ts index e4c64a299925..033e0648d624 100644 --- a/packages/tracing-internal/src/node/integrations/apollo.ts +++ b/packages/tracing-internal/src/node/integrations/apollo.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { arrayify, fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -77,7 +78,7 @@ export class Apollo implements LazyLoadedIntegration void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Apollo Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Apollo Integration is skipped because of instrumenter configuration.'); return; } @@ -85,7 +86,7 @@ export class Apollo implements LazyLoadedIntegration Hub): void { if (!this._router) { - __DEBUG_BUILD__ && logger.error('ExpressIntegration is missing an Express instance'); + DEBUG_BUILD && logger.error('ExpressIntegration is missing an Express instance'); return; } if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Express Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Express Integration is skipped because of instrumenter configuration.'); return; } @@ -293,8 +294,8 @@ function instrumentRouter(appOrRouter: ExpressRouter): void { TODO: Proper Express 5 support */ - __DEBUG_BUILD__ && logger.debug('Cannot instrument router for URL Parameterization (did not find a valid router).'); - __DEBUG_BUILD__ && logger.debug('Routing instrumentation is currently only supported in Express 4.'); + DEBUG_BUILD && logger.debug('Cannot instrument router for URL Parameterization (did not find a valid router).'); + DEBUG_BUILD && logger.debug('Routing instrumentation is currently only supported in Express 4.'); return; } diff --git a/packages/tracing-internal/src/node/integrations/graphql.ts b/packages/tracing-internal/src/node/integrations/graphql.ts index 3fdf6e8ede4c..1fafae134ad7 100644 --- a/packages/tracing-internal/src/node/integrations/graphql.ts +++ b/packages/tracing-internal/src/node/integrations/graphql.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -37,14 +38,14 @@ export class GraphQL implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('GraphQL Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('GraphQL Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('GraphQL Integration was unable to require graphql/execution package.'); + DEBUG_BUILD && logger.error('GraphQL Integration was unable to require graphql/execution package.'); return; } diff --git a/packages/tracing-internal/src/node/integrations/mongo.ts b/packages/tracing-internal/src/node/integrations/mongo.ts index a3bc810be7a3..fe6bc971d72e 100644 --- a/packages/tracing-internal/src/node/integrations/mongo.ts +++ b/packages/tracing-internal/src/node/integrations/mongo.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor, SpanContext } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -140,7 +141,7 @@ export class Mongo implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Mongo Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Mongo Integration is skipped because of instrumenter configuration.'); return; } @@ -148,7 +149,7 @@ export class Mongo implements LazyLoadedIntegration { if (!pkg) { const moduleName = this._useMongoose ? 'mongoose' : 'mongodb'; - __DEBUG_BUILD__ && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); + DEBUG_BUILD && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); return; } diff --git a/packages/tracing-internal/src/node/integrations/mysql.ts b/packages/tracing-internal/src/node/integrations/mysql.ts index d176730f5847..18038982c03d 100644 --- a/packages/tracing-internal/src/node/integrations/mysql.ts +++ b/packages/tracing-internal/src/node/integrations/mysql.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor, Span } from '@sentry/types'; import { fill, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -46,14 +47,14 @@ export class Mysql implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Mysql Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Mysql Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('Mysql Integration was unable to require `mysql` package.'); + DEBUG_BUILD && logger.error('Mysql Integration was unable to require `mysql` package.'); return; } @@ -69,7 +70,7 @@ export class Mysql implements LazyLoadedIntegration { }, }); } catch (e) { - __DEBUG_BUILD__ && logger.error('Mysql Integration was unable to instrument `mysql` config.'); + DEBUG_BUILD && logger.error('Mysql Integration was unable to instrument `mysql` config.'); } function spanDataFromConfig(): Record { diff --git a/packages/tracing-internal/src/node/integrations/postgres.ts b/packages/tracing-internal/src/node/integrations/postgres.ts index a3d94653477f..918f20664b92 100644 --- a/packages/tracing-internal/src/node/integrations/postgres.ts +++ b/packages/tracing-internal/src/node/integrations/postgres.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -76,21 +77,21 @@ export class Postgres implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Postgres Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Postgres Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('Postgres Integration was unable to require `pg` package.'); + DEBUG_BUILD && logger.error('Postgres Integration was unable to require `pg` package.'); return; } const Client = this._usePgNative ? pkg.native?.Client : pkg.Client; if (!Client) { - __DEBUG_BUILD__ && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); + DEBUG_BUILD && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); return; } diff --git a/packages/tracing-internal/src/node/integrations/prisma.ts b/packages/tracing-internal/src/node/integrations/prisma.ts index df43ec441391..b13fa2af7f53 100644 --- a/packages/tracing-internal/src/node/integrations/prisma.ts +++ b/packages/tracing-internal/src/node/integrations/prisma.ts @@ -2,6 +2,7 @@ import { getCurrentHub, trace } from '@sentry/core'; import type { Integration } from '@sentry/types'; import { addNonEnumerableProperty, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; type PrismaAction = @@ -109,7 +110,7 @@ export class Prisma implements Integration { ); }); } else { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Unsupported Prisma client provided to PrismaIntegration. Provided client:', options.client); } } diff --git a/packages/types/src/globals.ts b/packages/types/src/globals.ts deleted file mode 100644 index 4a3e239f8a2f..000000000000 --- a/packages/types/src/globals.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file adds variables to the global namespace when it's loaded. We do this in order to be able to use flags and - * constants to facilitate tree shaking for users without having to import them, since the imports can confuse some - * tree-shaking algorithms. - * - * "Magic strings" like `__DEBUG_BUILD__` are declared here, but only replaced with actual values during our build - * process. - * - * See https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html and - * the Debug Build Flags section in CONTRIBUTING.md. - */ - -declare global { - const __DEBUG_BUILD__: boolean; -} - -// We need this empty export because of --isolatedModules -export type {}; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index cf7d801dee8b..627879493365 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -48,10 +48,6 @@ export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from ' export type { EventProcessor } from './eventprocessor'; export type { Exception } from './exception'; export type { Extra, Extras } from './extra'; -// This is a dummy export, purely for the purpose of loading `globals.ts`, in order to take advantage of its side effect -// of putting variables into the global namespace. See -// https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html. -export type {} from './globals'; export type { Hub } from './hub'; export type { Integration, IntegrationClass } from './integration'; export type { Mechanism } from './mechanism'; diff --git a/packages/types/src/instrument.ts b/packages/types/src/instrument.ts index 16ec5a3b75b7..5c42c8cebf27 100644 --- a/packages/types/src/instrument.ts +++ b/packages/types/src/instrument.ts @@ -63,7 +63,8 @@ export interface HandlerDataFetch { } export interface HandlerDataDom { - event: Event | { target: EventTarget }; + // TODO: Replace `object` here with a vendored type for browser Events. We can't depend on the `DOM` or `react` TS types package here. + event: object | { target: object }; name: string; global?: boolean; } @@ -82,7 +83,8 @@ export interface HandlerDataError { column?: number; error?: Error; line?: number; - msg: string | Event; + // TODO: Replace `object` here with a vendored type for browser Events. We can't depend on the `DOM` or `react` TS types package here. + msg: string | object; url?: string; } diff --git a/packages/utils/src/baggage.ts b/packages/utils/src/baggage.ts index 674e7f60f7ef..0202f0ec00f5 100644 --- a/packages/utils/src/baggage.ts +++ b/packages/utils/src/baggage.ts @@ -1,5 +1,6 @@ import type { DynamicSamplingContext } from '@sentry/types'; +import { DEBUG_BUILD } from './debug-build'; import { isString } from './is'; import { logger } from './logger'; @@ -136,7 +137,7 @@ function objectToBaggageHeader(object: Record): string | undefin const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`; const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`; if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`, ); diff --git a/packages/utils/src/debug-build.ts b/packages/utils/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/utils/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/utils/src/dsn.ts b/packages/utils/src/dsn.ts index f149b67a9386..7bf735c10780 100644 --- a/packages/utils/src/dsn.ts +++ b/packages/utils/src/dsn.ts @@ -1,6 +1,7 @@ import type { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types'; -import { logger } from './logger'; +import { DEBUG_BUILD } from './debug-build'; +import { consoleSandbox, logger } from './logger'; /** Regular expression used to parse a Dsn. */ const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/; @@ -37,8 +38,10 @@ export function dsnFromString(str: string): DsnComponents | undefined { if (!match) { // This should be logged to the console - // eslint-disable-next-line no-console - console.error(`Invalid Sentry Dsn: ${str}`); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error(`Invalid Sentry Dsn: ${str}`); + }); return undefined; } @@ -75,7 +78,7 @@ function dsnFromComponents(components: DsnComponents): DsnComponents { } function validateDsn(dsn: DsnComponents): boolean { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return true; } diff --git a/packages/utils/src/instrument/_handlers.ts b/packages/utils/src/instrument/_handlers.ts index e86ab677ed39..520d258ae1ac 100644 --- a/packages/utils/src/instrument/_handlers.ts +++ b/packages/utils/src/instrument/_handlers.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from '../debug-build'; import { logger } from '../logger'; import { getFunctionName } from '../stacktrace'; @@ -44,7 +45,7 @@ export function triggerHandlers(type: InstrumentHandlerType, data: unknown): voi try { handler(data); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, diff --git a/packages/utils/src/instrument/dom.ts b/packages/utils/src/instrument/dom.ts index 71f64e43ebc5..aab64c8c149b 100644 --- a/packages/utils/src/instrument/dom.ts +++ b/packages/utils/src/instrument/dom.ts @@ -1,3 +1,5 @@ +// TODO(v8): Move everything in this file into the browser package. Nothing here is generic and we run risk of leaking browser types into non-browser packages. + /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import type { HandlerDataDom } from '@sentry/types'; diff --git a/packages/utils/src/instrument/history.ts b/packages/utils/src/instrument/history.ts index b13eabf99e3b..dc144c0e5818 100644 --- a/packages/utils/src/instrument/history.ts +++ b/packages/utils/src/instrument/history.ts @@ -1,3 +1,5 @@ +// TODO(v8): Move everything in this file into the browser package. Nothing here is generic and we run risk of leaking browser types into non-browser packages. + /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import type { HandlerDataHistory } from '@sentry/types'; diff --git a/packages/utils/src/instrument/index.ts b/packages/utils/src/instrument/index.ts index 800f2ec6540d..2e2255496dd2 100644 --- a/packages/utils/src/instrument/index.ts +++ b/packages/utils/src/instrument/index.ts @@ -1,3 +1,6 @@ +// TODO(v8): Consider moving this file (or at least parts of it) into the browser package. The registered handlers are mostly non-generic and we risk leaking runtime specific code into generic packages. + +import { DEBUG_BUILD } from '../debug-build'; import type { InstrumentHandlerCallback as _InstrumentHandlerCallback, InstrumentHandlerType as _InstrumentHandlerType, @@ -35,7 +38,7 @@ export function addInstrumentationHandler(type: _InstrumentHandlerType, callback case 'unhandledrejection': return addGlobalUnhandledRejectionInstrumentationHandler(callback); default: - __DEBUG_BUILD__ && logger.warn('unknown instrumentation type:', type); + DEBUG_BUILD && logger.warn('unknown instrumentation type:', type); } } diff --git a/packages/utils/src/instrument/xhr.ts b/packages/utils/src/instrument/xhr.ts index d0245dcdd2ee..eb3ec8e158d5 100644 --- a/packages/utils/src/instrument/xhr.ts +++ b/packages/utils/src/instrument/xhr.ts @@ -1,3 +1,5 @@ +// TODO(v8): Move everything in this file into the browser package. Nothing here is generic and we run risk of leaking browser types into non-browser packages. + /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import type { HandlerDataXhr, SentryWrappedXMLHttpRequest, WrappedFunction } from '@sentry/types'; diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 1784aa179bb1..e996d87202b2 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,5 +1,6 @@ import type { ConsoleLevel } from '@sentry/types'; +import { DEBUG_BUILD } from './debug-build'; import { GLOBAL_OBJ } from './worldwide'; /** Prefix for logging strings */ @@ -76,7 +77,7 @@ function makeLogger(): Logger { isEnabled: () => enabled, }; - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { CONSOLE_LEVELS.forEach(name => { // eslint-disable-next-line @typescript-eslint/no-explicit-any logger[name] = (...args: any[]) => { diff --git a/packages/utils/src/object.ts b/packages/utils/src/object.ts index e4e866bf2763..f6dd9a1a7166 100644 --- a/packages/utils/src/object.ts +++ b/packages/utils/src/object.ts @@ -3,6 +3,7 @@ import type { WrappedFunction } from '@sentry/types'; import { htmlTreeAsString } from './browser'; +import { DEBUG_BUILD } from './debug-build'; import { isElement, isError, isEvent, isInstanceOf, isPlainObject, isPrimitive } from './is'; import { logger } from './logger'; import { truncate } from './string'; @@ -51,7 +52,7 @@ export function addNonEnumerableProperty(obj: object, name: string, value: unkno configurable: true, }); } catch (o_O) { - __DEBUG_BUILD__ && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj); + DEBUG_BUILD && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj); } } diff --git a/packages/utils/src/requestdata.ts b/packages/utils/src/requestdata.ts index a138ecf3141b..7106a42a5a60 100644 --- a/packages/utils/src/requestdata.ts +++ b/packages/utils/src/requestdata.ts @@ -9,6 +9,7 @@ import type { } from '@sentry/types'; import { parseCookie } from './cookie'; +import { DEBUG_BUILD } from './debug-build'; import { isPlainObject, isString } from './is'; import { logger } from './logger'; import { normalize } from './normalize'; @@ -379,7 +380,7 @@ export function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record< } }); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.'); } diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index 2e555ee2efb5..01d4627d2892 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from './debug-build'; import { logger } from './logger'; import { getGlobalObject } from './worldwide'; @@ -121,7 +122,7 @@ export function supportsNativeFetch(): boolean { } doc.head.removeChild(sandbox); } catch (err) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err); } } diff --git a/packages/utils/test/dsn.test.ts b/packages/utils/test/dsn.test.ts index 3de435bf5fcf..e1aadb893e8e 100644 --- a/packages/utils/test/dsn.test.ts +++ b/packages/utils/test/dsn.test.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from '../src/debug-build'; import { dsnToString, makeDsn } from '../src/dsn'; import { logger } from '../src/logger'; @@ -48,7 +49,7 @@ describe('Dsn', () => { expect(dsn?.projectId).toBe('123'); }); - testIf(__DEBUG_BUILD__)('returns `undefined` for missing components', () => { + testIf(DEBUG_BUILD)('returns `undefined` for missing components', () => { expect( makeDsn({ host: '', @@ -85,7 +86,7 @@ describe('Dsn', () => { expect(loggerErrorSpy).toHaveBeenCalledTimes(4); }); - testIf(__DEBUG_BUILD__)('returns `undefined` if components are invalid', () => { + testIf(DEBUG_BUILD)('returns `undefined` if components are invalid', () => { expect( makeDsn({ host: 'sentry.io', @@ -164,12 +165,12 @@ describe('Dsn', () => { expect(dsn?.projectId).toBe('321'); }); - testIf(__DEBUG_BUILD__)('returns undefined when provided invalid Dsn', () => { + testIf(DEBUG_BUILD)('returns undefined when provided invalid Dsn', () => { expect(makeDsn('some@random.dsn')).toBeUndefined(); expect(consoleErrorSpy).toHaveBeenCalledTimes(1); }); - testIf(__DEBUG_BUILD__)('returns undefined if mandatory fields are missing', () => { + testIf(DEBUG_BUILD)('returns undefined if mandatory fields are missing', () => { expect(makeDsn('://abc@sentry.io/123')).toBeUndefined(); expect(makeDsn('https://@sentry.io/123')).toBeUndefined(); expect(makeDsn('https://abc@123')).toBeUndefined(); @@ -177,7 +178,7 @@ describe('Dsn', () => { expect(consoleErrorSpy).toHaveBeenCalledTimes(4); }); - testIf(__DEBUG_BUILD__)('returns undefined if fields are invalid', () => { + testIf(DEBUG_BUILD)('returns undefined if fields are invalid', () => { expect(makeDsn('httpx://abc@sentry.io/123')).toBeUndefined(); expect(makeDsn('httpx://abc@sentry.io:xxx/123')).toBeUndefined(); expect(makeDsn('http://abc@sentry.io/abc')).toBeUndefined(); diff --git a/packages/vercel-edge/src/async.ts b/packages/vercel-edge/src/async.ts index 36c6317248b4..336494dfbf3e 100644 --- a/packages/vercel-edge/src/async.ts +++ b/packages/vercel-edge/src/async.ts @@ -2,6 +2,8 @@ import type { Carrier, Hub, RunWithAsyncContextOptions } from '@sentry/core'; import { ensureHubOnCarrier, getHubFromCarrier, setAsyncContextStrategy } from '@sentry/core'; import { GLOBAL_OBJ, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + interface AsyncLocalStorage { getStore(): T | undefined; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -18,7 +20,7 @@ let asyncStorage: AsyncLocalStorage; */ export function setAsyncLocalStorageAsyncContextStrategy(): void { if (!MaybeGlobalAsyncLocalStorage) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( "Tried to register AsyncLocalStorage async context strategy in a runtime that doesn't support AsyncLocalStorage.", ); diff --git a/packages/vercel-edge/src/debug-build.ts b/packages/vercel-edge/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/vercel-edge/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/vue/src/debug-build.ts b/packages/vue/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/vue/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/vue/src/errorhandler.ts b/packages/vue/src/errorhandler.ts index 40a950ae9374..9d09bdf8c181 100644 --- a/packages/vue/src/errorhandler.ts +++ b/packages/vue/src/errorhandler.ts @@ -1,4 +1,5 @@ import { getCurrentHub } from '@sentry/browser'; +import { consoleSandbox } from '@sentry/utils'; import type { ViewModel, Vue, VueOptions } from './types'; import { formatComponentName, generateComponentTrace } from './vendor/components'; @@ -46,8 +47,10 @@ export const attachErrorHandler = (app: Vue, options: VueOptions): void => { if (warnHandler) { (warnHandler as UnknownFunc).call(null, message, vm, trace); } else if (hasConsole && !silent) { - // eslint-disable-next-line no-console - console.error(`[Vue warn]: ${message}${trace}`); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.error(`[Vue warn]: ${message}${trace}`); + }); } } }; diff --git a/packages/vue/src/integration.ts b/packages/vue/src/integration.ts index 9a3969f5c415..3f35c66fe554 100644 --- a/packages/vue/src/integration.ts +++ b/packages/vue/src/integration.ts @@ -1,6 +1,6 @@ import { hasTracingEnabled } from '@sentry/core'; import type { Hub, Integration } from '@sentry/types'; -import { arrayify, GLOBAL_OBJ } from '@sentry/utils'; +import { arrayify, consoleSandbox, GLOBAL_OBJ } from '@sentry/utils'; import { DEFAULT_HOOKS } from './constants'; import { attachErrorHandler } from './errorhandler'; @@ -50,12 +50,14 @@ export class VueIntegration implements Integration { const options: Options = { ...DEFAULT_CONFIG, ...(client && client.getOptions()), ...this._options }; if (!options.Vue && !options.app) { - // eslint-disable-next-line no-console - console.warn( - `[@sentry/vue]: Misconfigured SDK. Vue specific errors will not be captured. + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + `[@sentry/vue]: Misconfigured SDK. Vue specific errors will not be captured. Update your \`Sentry.init\` call with an appropriate config option: \`app\` (Application Instance - Vue 3) or \`Vue\` (Vue Constructor - Vue 2).`, - ); + ); + }); return; } @@ -80,10 +82,12 @@ const vueInit = (app: Vue, options: Options): void => { const isMounted = appWithInstance._instance && appWithInstance._instance.isMounted; if (isMounted === true) { - // eslint-disable-next-line no-console - console.warn( - '[@sentry/vue]: Misconfigured SDK. Vue app is already mounted. Make sure to call `app.mount()` after `Sentry.init()`.', - ); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[@sentry/vue]: Misconfigured SDK. Vue app is already mounted. Make sure to call `app.mount()` after `Sentry.init()`.', + ); + }); } attachErrorHandler(app, options); diff --git a/packages/vue/src/tracing.ts b/packages/vue/src/tracing.ts index 312ee076ba25..82000b9799a4 100644 --- a/packages/vue/src/tracing.ts +++ b/packages/vue/src/tracing.ts @@ -3,6 +3,7 @@ import type { Span, Transaction } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; import { DEFAULT_HOOKS } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import type { Hook, Operation, TracingOptions, ViewModel, Vue } from './types'; import { formatComponentName } from './vendor/components'; @@ -63,7 +64,7 @@ export const createTracingMixins = (options: TracingOptions): Mixins => { // eg. mount => ['beforeMount', 'mounted'] const internalHooks = HOOKS[operation]; if (!internalHooks) { - __DEBUG_BUILD__ && logger.warn(`Unknown hook: ${operation}`); + DEBUG_BUILD && logger.warn(`Unknown hook: ${operation}`); continue; } diff --git a/scenarios/browser/basic-capture-exception/index.js b/scenarios/browser/basic-capture-exception/index.js deleted file mode 100644 index d8f49c6e8f91..000000000000 --- a/scenarios/browser/basic-capture-exception/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { init, captureException } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", -}); - -captureException(new Error("error here!")); diff --git a/scenarios/browser/basic-capture-exception/package.json b/scenarios/browser/basic-capture-exception/package.json deleted file mode 100644 index 648f2811682c..000000000000 --- a/scenarios/browser/basic-capture-exception/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-capture-exception", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-capture-message/index.js b/scenarios/browser/basic-capture-message/index.js deleted file mode 100644 index cc1c36996db1..000000000000 --- a/scenarios/browser/basic-capture-message/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { init, captureMessage } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", -}); - -captureMessage("this is a message"); diff --git a/scenarios/browser/basic-capture-message/package.json b/scenarios/browser/basic-capture-message/package.json deleted file mode 100644 index 8ef15e0872fe..000000000000 --- a/scenarios/browser/basic-capture-message/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-capture-message", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-custom-integration/index.js b/scenarios/browser/basic-custom-integration/index.js deleted file mode 100644 index 2ef4864e2c78..000000000000 --- a/scenarios/browser/basic-custom-integration/index.js +++ /dev/null @@ -1,23 +0,0 @@ -import { init } from "@sentry/browser"; - -class CustomIntegration { - static id = 'CustomIntegration'; - - name = CustomIntegration.id; - options = undefined; - - constructor(options) { - this.options = options; - } - - setupOnce(addGlobalEventProcessor, getCurrentHub) { - addGlobalEventProcessor(event => event); - const hub = getCurrentHub(); - hub.captureMessage(options.name); - } -} - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - integrations: [new CustomIntegration()], -}); diff --git a/scenarios/browser/basic-custom-integration/package.json b/scenarios/browser/basic-custom-integration/package.json deleted file mode 100644 index 0d65cdf1fd85..000000000000 --- a/scenarios/browser/basic-custom-integration/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-custom-integration", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-custom-transport/index.js b/scenarios/browser/basic-custom-transport/index.js deleted file mode 100644 index 7e453b13259d..000000000000 --- a/scenarios/browser/basic-custom-transport/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import { init, Transports } from "@sentry/browser"; - -class CustomTransport extends Transports.BaseTransport { - constructor(options) { - super(options); - } - - sendEvent(event) { - console.log("Sending Event"); - return super.sendEvent(event); - } - - sendSession(session) { - console.log("Sending Session"); - return super.sendSession(session); - } -} - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - transport: CustomTransport -}); diff --git a/scenarios/browser/basic-custom-transport/package.json b/scenarios/browser/basic-custom-transport/package.json deleted file mode 100644 index 55293071b717..000000000000 --- a/scenarios/browser/basic-custom-transport/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-custom-transport", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-no-client-reports/index.js b/scenarios/browser/basic-no-client-reports/index.js deleted file mode 100644 index 5c52e71e2518..000000000000 --- a/scenarios/browser/basic-no-client-reports/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - sendClientReports: false, -}); diff --git a/scenarios/browser/basic-no-client-reports/package.json b/scenarios/browser/basic-no-client-reports/package.json deleted file mode 100644 index a43e8f57ee5e..000000000000 --- a/scenarios/browser/basic-no-client-reports/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-no-client-reports", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-no-default-integrations/index.js b/scenarios/browser/basic-no-default-integrations/index.js deleted file mode 100644 index fa0d50153682..000000000000 --- a/scenarios/browser/basic-no-default-integrations/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - defaultIntegrations: false, -}); diff --git a/scenarios/browser/basic-no-default-integrations/package.json b/scenarios/browser/basic-no-default-integrations/package.json deleted file mode 100644 index cbbf97445002..000000000000 --- a/scenarios/browser/basic-no-default-integrations/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-no-default-integrations", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-no-dsn/index.js b/scenarios/browser/basic-no-dsn/index.js deleted file mode 100644 index b1e65a541bc6..000000000000 --- a/scenarios/browser/basic-no-dsn/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { init } from "@sentry/browser"; - -init(); diff --git a/scenarios/browser/basic-no-dsn/package.json b/scenarios/browser/basic-no-dsn/package.json deleted file mode 100644 index 0d6d42459880..000000000000 --- a/scenarios/browser/basic-no-dsn/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-no-dsn", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-no-sessions/index.js b/scenarios/browser/basic-no-sessions/index.js deleted file mode 100644 index 6152ed8f4332..000000000000 --- a/scenarios/browser/basic-no-sessions/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - release: "my-app@1.2.3", - autoSessionTracking: false, -}); diff --git a/scenarios/browser/basic-no-sessions/package.json b/scenarios/browser/basic-no-sessions/package.json deleted file mode 100644 index 0aa83cd2012b..000000000000 --- a/scenarios/browser/basic-no-sessions/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-no-sessions", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-with-debug/index.js b/scenarios/browser/basic-with-debug/index.js deleted file mode 100644 index feb43c4afbee..000000000000 --- a/scenarios/browser/basic-with-debug/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - debug: true, -}); diff --git a/scenarios/browser/basic-with-debug/package.json b/scenarios/browser/basic-with-debug/package.json deleted file mode 100644 index 11adf6b8d51e..000000000000 --- a/scenarios/browser/basic-with-debug/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-with-debug", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-with-sessions/index.js b/scenarios/browser/basic-with-sessions/index.js deleted file mode 100644 index 9a346cf1be3a..000000000000 --- a/scenarios/browser/basic-with-sessions/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - release: "my-app@1.2.3", -}); diff --git a/scenarios/browser/basic-with-sessions/package.json b/scenarios/browser/basic-with-sessions/package.json deleted file mode 100644 index d8012e78fb3e..000000000000 --- a/scenarios/browser/basic-with-sessions/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-with-sessions", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic-with-tunnel/index.js b/scenarios/browser/basic-with-tunnel/index.js deleted file mode 100644 index 2716574cc3d1..000000000000 --- a/scenarios/browser/basic-with-tunnel/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - tunnel: "/errors", -}); diff --git a/scenarios/browser/basic-with-tunnel/package.json b/scenarios/browser/basic-with-tunnel/package.json deleted file mode 100644 index 9d35d8e664f6..000000000000 --- a/scenarios/browser/basic-with-tunnel/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic-with-tunnel", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/basic/index.js b/scenarios/browser/basic/index.js deleted file mode 100644 index 4a17f885a9ed..000000000000 --- a/scenarios/browser/basic/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { init } from "@sentry/browser"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", -}); diff --git a/scenarios/browser/basic/package.json b/scenarios/browser/basic/package.json deleted file mode 100644 index da52f2cfdf84..000000000000 --- a/scenarios/browser/basic/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "basic", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/nextjs-client/index.js b/scenarios/browser/nextjs-client/index.js deleted file mode 100644 index 2e1d4645c8dc..000000000000 --- a/scenarios/browser/nextjs-client/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { init } from "@sentry/nextjs/esm/index.client"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", -}); diff --git a/scenarios/browser/nextjs-client/package.json b/scenarios/browser/nextjs-client/package.json deleted file mode 100644 index 638d816e2e70..000000000000 --- a/scenarios/browser/nextjs-client/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "nextjs-client", - "private": true, - "version": "0.0.0", - "dependencies": { - "next": "12" - } -} diff --git a/scenarios/browser/package.json b/scenarios/browser/package.json deleted file mode 100644 index 305641c25f9e..000000000000 --- a/scenarios/browser/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "scenarios-browser", - "main": "webpack.js", - "private": true, - "version": "0.0.0", - "devDependencies": { - "html-webpack-plugin": "^5.5.0", - "webpack": "^5.76.0", - "webpack-bundle-analyzer": "^4.5.0", - "inquirer": "^8.2.0" - } -} diff --git a/scenarios/browser/perf-auto/index.js b/scenarios/browser/perf-auto/index.js deleted file mode 100644 index ae46d8d7fb26..000000000000 --- a/scenarios/browser/perf-auto/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import { init } from "@sentry/browser"; -import { Integrations } from "@sentry/tracing"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - integrations: [new Integrations.BrowserTracing()], - tracesSampleRate: 1.0, -}); diff --git a/scenarios/browser/perf-auto/package.json b/scenarios/browser/perf-auto/package.json deleted file mode 100644 index 83d2c54e9e99..000000000000 --- a/scenarios/browser/perf-auto/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "perf-auto", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/perf-manual/index.js b/scenarios/browser/perf-manual/index.js deleted file mode 100644 index ce0ecfe73746..000000000000 --- a/scenarios/browser/perf-manual/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import { init, startTransaction } from "@sentry/browser"; -import "@sentry/tracing"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", - tracesSampleRate: 1.0, -}); - -const transaction = startTransaction({ op: "task", name: "Important Stuff" }); - -setTimeout(() => { - transaction.finish(); -}, 1000); diff --git a/scenarios/browser/perf-manual/package.json b/scenarios/browser/perf-manual/package.json deleted file mode 100644 index e8e94f0dd61d..000000000000 --- a/scenarios/browser/perf-manual/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "perf-manual", - "private": true, - "version": "0.0.0" -} diff --git a/scenarios/browser/react/index.js b/scenarios/browser/react/index.js deleted file mode 100644 index 199a160d26a6..000000000000 --- a/scenarios/browser/react/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom" -import { init } from "@sentry/react"; - -init({ - dsn: "https://00000000000000000000000000000000@o000000.ingest.sentry.io/0000000", -}); - -class Hello extends React.Component { - render() { - return React.createElement('div', null, `Hello ${this.props.toWhat}`); - } -} - -ReactDOM.render( - React.createElement(Hello, { toWhat: 'World' }, null), - // eslint-disable-next-line no-undef - document.getElementById('root') -); diff --git a/scenarios/browser/react/package.json b/scenarios/browser/react/package.json deleted file mode 100644 index 068e2fd2e168..000000000000 --- a/scenarios/browser/react/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "react", - "private": true, - "version": "0.0.0", - "dependencies": { - "react": "17", - "react-dom": "17" - } -} diff --git a/scenarios/browser/webpack.js b/scenarios/browser/webpack.js deleted file mode 100644 index 9bbb24c48a10..000000000000 --- a/scenarios/browser/webpack.js +++ /dev/null @@ -1,82 +0,0 @@ -const path = require('path'); -const { promises } = require('fs'); - -const inquirer = require('inquirer'); -const webpack = require('webpack'); -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -async function init() { - const scenarios = await getScenariosFromDirectories(); - - const answers = await inquirer.prompt([ - { - type: 'rawlist', - name: 'scenario', - message: 'Which scenario you want to run?', - choices: scenarios, - pageSize: scenarios.length, - loop: false, - }, - ]); - - console.log(`Bundling scenario: ${answers.scenario}`); - - await runWebpack(answers.scenario); -} - -async function runWebpack(scenario) { - const alias = await generateAlias(); - - webpack( - { - mode: 'production', - entry: path.resolve(__dirname, scenario), - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'dist', scenario), - }, - plugins: [new BundleAnalyzerPlugin({ analyzerMode: 'static' }), new HtmlWebpackPlugin()], - resolve: { - alias, - }, - }, - (err, stats) => { - if (err || stats.hasErrors()) { - console.log(err); - } - console.log('DONE', stats); - }, - ); -} - -const PACKAGE_PATH = '../../packages'; - -/** - * Generate webpack aliases based on packages in monorepo - * Example of an alias: '@sentry/serverless': 'path/to/sentry-javascript/packages/serverless', - */ -async function generateAlias() { - const dirents = await promises.readdir(PACKAGE_PATH); - - return Object.fromEntries( - await Promise.all( - dirents.map(async d => { - const packageJSON = JSON.parse(await promises.readFile(path.resolve(PACKAGE_PATH, d, 'package.json'))); - return [packageJSON['name'], path.resolve(PACKAGE_PATH, d)]; - }), - ), - ); -} - -/** - * Generates an array of available scenarios - */ -async function getScenariosFromDirectories() { - const exclude = ['node_modules', 'dist', '~', 'package.json', 'yarn.lock', 'webpack.js']; - - const dirents = await promises.readdir(__dirname, { withFileTypes: true }); - return dirents.map(dirent => dirent.name).filter(mape => !exclude.includes(mape)); -} - -init(); diff --git a/scenarios/browser/yarn.lock b/scenarios/browser/yarn.lock deleted file mode 100644 index 05a2d184cab2..000000000000 --- a/scenarios/browser/yarn.lock +++ /dev/null @@ -1,1123 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== - -"@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "7.28.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.2.tgz#0ff2947cdd305897c52d5372294e8c76f351db68" - integrity sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== - -"@types/html-minifier-terser@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" - integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== - -"@types/json-schema@*", "@types/json-schema@^7.0.8": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - -"@types/node@*": - version "16.11.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" - integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== - -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== - -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-walk@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -browserslist@^4.14.5: - version "4.17.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.6.tgz#c76be33e7786b497f66cad25a73756c8b938985d" - integrity sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw== - dependencies: - caniuse-lite "^1.0.30001274" - electron-to-chromium "^1.3.886" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -caniuse-lite@^1.0.30001274: - version "1.0.30001278" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz#51cafc858df77d966b17f59b5839250b24417fff" - integrity sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg== - -chalk@^4.1.0, chalk@^4.1.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -clean-css@^5.1.5: - version "5.2.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" - integrity sha512-/eR8ru5zyxKzpBLv9YZvMXgTSSQn7AdkMItMYynsFgGwTveCRVam9IUPFloE85B4vAIj05IuKmmEoV7/AQjT0w== - dependencies: - source-map "~0.6.0" - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" - integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== - dependencies: - boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" - -css-what@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.5.2, domutils@^2.6.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -electron-to-chromium@^1.3.886: - version "1.3.891" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.891.tgz#51d7224e64157656276f152a0b3361708fde1bf9" - integrity sha512-3cpwR82QkIS01CN/dup/4Yr3BiOiRLlZlcAFn/5FbNCunMO9ojqDgEP9JEo1QNLflu3pEnPWve50gHOEKc7r6w== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -html-minifier-terser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.0.2.tgz#14059ad64b69bf9f8b8a33f25b53411d8321e75d" - integrity sha512-AgYO3UGhMYQx2S/FBJT3EM0ZYcKmH6m9XL9c1v77BeK/tYJxGPxT1/AtsdUi4FcP8kZGmqqnItCcjFPcX9hk6A== - dependencies: - camel-case "^4.1.2" - clean-css "^5.1.5" - commander "^8.1.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.7.2" - -html-webpack-plugin@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== - dependencies: - "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -inherits@^2.0.3, inherits@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inquirer@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" - integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.1" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^5.4.1" - run-async "^2.4.0" - rxjs "^7.2.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -jest-worker@^27.0.6: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.3.1.tgz#0def7feae5b8042be38479799aeb7b5facac24b2" - integrity sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -mime-db@1.50.0: - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== - -mime-types@^2.1.27: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== - dependencies: - mime-db "1.50.0" - -mime@^2.3.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== - -nth-check@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readable-stream@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -rxjs@^7.2.0: - version "7.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.2.tgz#11e4a3a1dfad85dbf7fb6e33cbba17668497490b" - integrity sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w== - dependencies: - tslib "^2.1.0" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -signal-exit@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -sirv@^1.0.7: - version "1.0.18" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899" - integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA== - dependencies: - "@polka/url" "^1.0.0-next.20" - mime "^2.3.1" - totalist "^1.0.0" - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -string-width@^4.1.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.1.3: - version "5.2.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz#ce65b9880a0c36872555c4874f45bbdb02ee32c9" - integrity sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g== - dependencies: - jest-worker "^27.0.6" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.7.2: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== - dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - -tslib@^2.0.3, tslib@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - -webpack-bundle-analyzer@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.76.0: - version "5.76.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" - integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - -ws@^7.3.1: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==