From 97501001cc94f15ca12b50014717aca37e015cc6 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 16 Dec 2024 11:02:18 +0100 Subject: [PATCH 1/3] ref(core)!: Remove `Scope` type interface in favor of using `Scope` class --- docs/migration/v8-to-v9.md | 8 + .../core/src/asyncContext/stackStrategy.ts | 24 +- packages/core/src/asyncContext/types.ts | 2 +- packages/core/src/carrier.ts | 3 +- packages/core/src/currentScopes.ts | 9 +- packages/core/src/defaultScopes.ts | 7 +- packages/core/src/exports.ts | 2 +- packages/core/src/fetch.ts | 3 +- packages/core/src/index.ts | 1 + .../core/src/integrations/captureconsole.ts | 3 +- packages/core/src/scope.ts | 167 +++++++---- .../src/tracing/dynamicSamplingContext.ts | 3 +- packages/core/src/tracing/trace.ts | 3 +- packages/core/src/tracing/utils.ts | 2 +- packages/core/src/types-hoist/client.ts | 2 +- packages/core/src/types-hoist/event.ts | 2 +- packages/core/src/types-hoist/hub.ts | 2 +- packages/core/src/types-hoist/index.ts | 1 - packages/core/src/types-hoist/options.ts | 2 +- packages/core/src/types-hoist/scope.ts | 277 ------------------ .../core/src/types-hoist/startSpanOptions.ts | 2 +- .../core/src/utils/applyScopeDataToEvent.ts | 3 +- packages/core/src/utils/prepareEvent.ts | 25 +- packages/core/src/utils/spanOnScope.ts | 3 +- packages/core/src/utils/traceData.ts | 3 +- packages/core/test/lib/prepareEvent.test.ts | 2 +- .../lib/utils/applyScopeDataToEvent.test.ts | 3 +- .../core/test/utils-hoist/requestdata.test.ts | 2 +- packages/deno/package.json | 2 +- 29 files changed, 179 insertions(+), 389 deletions(-) delete mode 100644 packages/core/src/types-hoist/scope.ts diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 8dc83876e024..56ebd37f8bed 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -105,6 +105,14 @@ Object.defineProperty(exports, '__esModule', { value: true }); The SDK no longer contains these statements. Let us know if this is causing issues in your setup by opening an issue on GitHub. +## 6. Type Changes + +In v8, types have been exported from `@sentry/types`, while implementations have been exported from other classes. +This lead to some duplication, where we had to keep an interface in `@sentry/types`, while the implementation mirroring that interface was kept e.g. in `@sentry/core`. +Since in v9 the types have been merged into `@sentry/core`, we can get rid of some of this duplication. This means that certain things that used to be a separate interface, will not expect an actual instance of the class/concrete implementation. This should not affect most users, unless you relied on passing things with a similar shape to internal methods. The following types are affected: + +- `Scope` now always expects the `Scope` class + # No Version Support Timeline Version support timelines are stressful for anybody using the SDK, so we won't be defining one. diff --git a/packages/core/src/asyncContext/stackStrategy.ts b/packages/core/src/asyncContext/stackStrategy.ts index 68c72fb8e92d..6fe836ea3734 100644 --- a/packages/core/src/asyncContext/stackStrategy.ts +++ b/packages/core/src/asyncContext/stackStrategy.ts @@ -1,13 +1,13 @@ import { getDefaultCurrentScope, getDefaultIsolationScope } from '../defaultScopes'; import { Scope } from '../scope'; -import type { Client, Scope as ScopeInterface } from '../types-hoist'; +import type { Client } from '../types-hoist'; import { isThenable } from '../utils-hoist/is'; import { getMainCarrier, getSentryCarrier } from './../carrier'; import type { AsyncContextStrategy } from './types'; interface Layer { client?: Client; - scope: ScopeInterface; + scope: Scope; } /** @@ -15,9 +15,9 @@ interface Layer { */ export class AsyncContextStack { private readonly _stack: [Layer, ...Layer[]]; - private _isolationScope: ScopeInterface; + private _isolationScope: Scope; - public constructor(scope?: ScopeInterface, isolationScope?: ScopeInterface) { + public constructor(scope?: Scope, isolationScope?: Scope) { let assignedScope; if (!scope) { assignedScope = new Scope(); @@ -40,7 +40,7 @@ export class AsyncContextStack { /** * Fork a scope for the stack. */ - public withScope(callback: (scope: ScopeInterface) => T): T { + public withScope(callback: (scope: Scope) => T): T { const scope = this._pushScope(); let maybePromiseResult: T; @@ -79,14 +79,14 @@ export class AsyncContextStack { /** * Returns the scope of the top stack. */ - public getScope(): ScopeInterface { + public getScope(): Scope { return this.getStackTop().scope; } /** * Get the isolation scope for the stack. */ - public getIsolationScope(): ScopeInterface { + public getIsolationScope(): Scope { return this._isolationScope; } @@ -100,7 +100,7 @@ export class AsyncContextStack { /** * Push a scope to the stack. */ - private _pushScope(): ScopeInterface { + private _pushScope(): Scope { // We want to clone the content of prev scope const scope = this.getScope().clone(); this._stack.push({ @@ -130,11 +130,11 @@ function getAsyncContextStack(): AsyncContextStack { return (sentry.stack = sentry.stack || new AsyncContextStack(getDefaultCurrentScope(), getDefaultIsolationScope())); } -function withScope(callback: (scope: ScopeInterface) => T): T { +function withScope(callback: (scope: Scope) => T): T { return getAsyncContextStack().withScope(callback); } -function withSetScope(scope: ScopeInterface, callback: (scope: ScopeInterface) => T): T { +function withSetScope(scope: Scope, callback: (scope: Scope) => T): T { const stack = getAsyncContextStack() as AsyncContextStack; return stack.withScope(() => { stack.getStackTop().scope = scope; @@ -142,7 +142,7 @@ function withSetScope(scope: ScopeInterface, callback: (scope: ScopeInterface }); } -function withIsolationScope(callback: (isolationScope: ScopeInterface) => T): T { +function withIsolationScope(callback: (isolationScope: Scope) => T): T { return getAsyncContextStack().withScope(() => { return callback(getAsyncContextStack().getIsolationScope()); }); @@ -156,7 +156,7 @@ export function getStackAsyncContextStrategy(): AsyncContextStrategy { withIsolationScope, withScope, withSetScope, - withSetIsolationScope: (_isolationScope: ScopeInterface, callback: (isolationScope: ScopeInterface) => T) => { + withSetIsolationScope: (_isolationScope: Scope, callback: (isolationScope: Scope) => T) => { return withIsolationScope(callback); }, getCurrentScope: () => getAsyncContextStack().getScope(), diff --git a/packages/core/src/asyncContext/types.ts b/packages/core/src/asyncContext/types.ts index 7b5bf8acc54c..d5d03bbec1ff 100644 --- a/packages/core/src/asyncContext/types.ts +++ b/packages/core/src/asyncContext/types.ts @@ -1,4 +1,4 @@ -import type { Scope } from '../types-hoist'; +import type { Scope } from '../scope'; import type { getTraceData } from '../utils/traceData'; import type { startInactiveSpan, diff --git a/packages/core/src/carrier.ts b/packages/core/src/carrier.ts index 1879dc47f2d4..e8bffa63b660 100644 --- a/packages/core/src/carrier.ts +++ b/packages/core/src/carrier.ts @@ -1,6 +1,7 @@ import type { AsyncContextStack } from './asyncContext/stackStrategy'; import type { AsyncContextStrategy } from './asyncContext/types'; -import type { Client, MetricsAggregator, Scope } from './types-hoist'; +import type { Scope } from './scope'; +import type { Client, MetricsAggregator } from './types-hoist'; import type { Logger } from './utils-hoist/logger'; import { SDK_VERSION } from './utils-hoist/version'; import { GLOBAL_OBJ } from './utils-hoist/worldwide'; diff --git a/packages/core/src/currentScopes.ts b/packages/core/src/currentScopes.ts index b339a9f6d4cf..d921524c6c1b 100644 --- a/packages/core/src/currentScopes.ts +++ b/packages/core/src/currentScopes.ts @@ -1,8 +1,7 @@ import { getAsyncContextStrategy } from './asyncContext'; -import { getMainCarrier } from './carrier'; -import { getGlobalSingleton } from './carrier'; -import { Scope as ScopeClass } from './scope'; -import type { Client, Scope, TraceContext } from './types-hoist'; +import { getGlobalSingleton, getMainCarrier } from './carrier'; +import { Scope } from './scope'; +import type { Client, TraceContext } from './types-hoist'; import { dropUndefinedKeys } from './utils-hoist/object'; /** @@ -29,7 +28,7 @@ export function getIsolationScope(): Scope { * This scope is applied to _all_ events. */ export function getGlobalScope(): Scope { - return getGlobalSingleton('globalScope', () => new ScopeClass()); + return getGlobalSingleton('globalScope', () => new Scope()); } /** diff --git a/packages/core/src/defaultScopes.ts b/packages/core/src/defaultScopes.ts index 581eef68aff1..cf8701e57e37 100644 --- a/packages/core/src/defaultScopes.ts +++ b/packages/core/src/defaultScopes.ts @@ -1,13 +1,12 @@ import { getGlobalSingleton } from './carrier'; -import { Scope as ScopeClass } from './scope'; -import type { Scope } from './types-hoist'; +import { Scope } from './scope'; /** Get the default current scope. */ export function getDefaultCurrentScope(): Scope { - return getGlobalSingleton('defaultCurrentScope', () => new ScopeClass()); + return getGlobalSingleton('defaultCurrentScope', () => new Scope()); } /** Get the default isolation scope. */ export function getDefaultIsolationScope(): Scope { - return getGlobalSingleton('defaultIsolationScope', () => new ScopeClass()); + return getGlobalSingleton('defaultIsolationScope', () => new Scope()); } diff --git a/packages/core/src/exports.ts b/packages/core/src/exports.ts index cf7e872fb001..02ae30058b04 100644 --- a/packages/core/src/exports.ts +++ b/packages/core/src/exports.ts @@ -1,5 +1,4 @@ import type { - CaptureContext, CheckIn, Event, EventHint, @@ -18,6 +17,7 @@ import type { import { DEFAULT_ENVIRONMENT } from './constants'; import { getClient, getCurrentScope, getIsolationScope, withIsolationScope } from './currentScopes'; import { DEBUG_BUILD } from './debug-build'; +import type { CaptureContext } from './scope'; import { closeSession, makeSession, updateSession } from './session'; import { isThenable } from './utils-hoist/is'; import { logger } from './utils-hoist/logger'; diff --git a/packages/core/src/fetch.ts b/packages/core/src/fetch.ts index 55ea867a763a..c55a18dacdc1 100644 --- a/packages/core/src/fetch.ts +++ b/packages/core/src/fetch.ts @@ -1,7 +1,8 @@ +import type { Scope } from './scope'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from './semanticAttributes'; import { SPAN_STATUS_ERROR, setHttpStatus, startInactiveSpan } from './tracing'; import { SentryNonRecordingSpan } from './tracing/sentryNonRecordingSpan'; -import type { Client, HandlerDataFetch, Scope, Span, SpanOrigin } from './types-hoist'; +import type { Client, HandlerDataFetch, Span, SpanOrigin } from './types-hoist'; import { SENTRY_BAGGAGE_KEY_PREFIX } from './utils-hoist/baggage'; import { isInstanceOf } from './utils-hoist/is'; import { parseUrl } from './utils-hoist/url'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 322084ae590a..3681b0b7ccee 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -50,6 +50,7 @@ export { makeSession, closeSession, updateSession } from './session'; // eslint-disable-next-line deprecation/deprecation export { SessionFlusher } from './sessionflusher'; export { Scope } from './scope'; +export type { CaptureContext, ScopeContext, ScopeData } from './scope'; export { notifyEventProcessors } from './eventProcessors'; export { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from './api'; export { BaseClient } from './baseclient'; diff --git a/packages/core/src/integrations/captureconsole.ts b/packages/core/src/integrations/captureconsole.ts index 3b027f985e66..203b54180b25 100644 --- a/packages/core/src/integrations/captureconsole.ts +++ b/packages/core/src/integrations/captureconsole.ts @@ -1,7 +1,8 @@ import { getClient, withScope } from '../currentScopes'; import { captureException, captureMessage } from '../exports'; import { defineIntegration } from '../integration'; -import type { CaptureContext, IntegrationFn } from '../types-hoist'; +import type { CaptureContext } from '../scope'; +import type { IntegrationFn } from '../types-hoist'; import { addConsoleInstrumentationHandler } from '../utils-hoist/instrument/console'; import { CONSOLE_LEVELS } from '../utils-hoist/logger'; import { addExceptionMechanism } from '../utils-hoist/misc'; diff --git a/packages/core/src/scope.ts b/packages/core/src/scope.ts index 5bba8615e876..775944abf898 100644 --- a/packages/core/src/scope.ts +++ b/packages/core/src/scope.ts @@ -2,7 +2,6 @@ import type { Attachment, Breadcrumb, - CaptureContext, Client, Context, Contexts, @@ -14,11 +13,9 @@ import type { Primitive, PropagationContext, RequestSession, - Scope as ScopeInterface, - ScopeContext, - ScopeData, Session, SeverityLevel, + Span, User, } from './types-hoist'; @@ -36,10 +33,51 @@ import { _getSpanForScope, _setSpanForScope } from './utils/spanOnScope'; */ const DEFAULT_MAX_BREADCRUMBS = 100; +/** + * A context to be used for capturing an event. + * This can either be a Scope, or a partial ScopeContext, + * or a callback that receives the current scope and returns a new scope to use. + */ +export type CaptureContext = Scope | Partial | ((scope: Scope) => Scope); + +/** + * Data that can be converted to a Scope. + */ +export interface ScopeContext { + user: User; + level: SeverityLevel; + extra: Extras; + contexts: Contexts; + tags: { [key: string]: Primitive }; + fingerprint: string[]; + // eslint-disable-next-line deprecation/deprecation + requestSession: RequestSession; + propagationContext: PropagationContext; +} + +/** + * Normalized data of the Scope, ready to be used. + */ +export interface ScopeData { + eventProcessors: EventProcessor[]; + breadcrumbs: Breadcrumb[]; + user: User; + tags: { [key: string]: Primitive }; + extra: Extras; + contexts: Contexts; + attachments: Attachment[]; + propagationContext: PropagationContext; + sdkProcessingMetadata: { [key: string]: unknown }; + fingerprint: string[]; + level?: SeverityLevel; + transactionName?: string; + span?: Span; +} + /** * Holds additional event information. */ -class ScopeClass implements ScopeInterface { +export class Scope { /** Flag if notifying is happening. */ protected _notifyingListeners: boolean; @@ -123,10 +161,10 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Clone all data from this scope into a new scope. */ - public clone(): ScopeClass { - const newScope = new ScopeClass(); + public clone(): Scope { + const newScope = new Scope(); newScope._breadcrumbs = [...this._breadcrumbs]; newScope._tags = { ...this._tags }; newScope._extra = { ...this._extra }; @@ -158,28 +196,32 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Update the client assigned to this scope. + * Note that not every scope will have a client assigned - isolation scopes & the global scope will generally not have a client, + * as well as manually created scopes. */ public setClient(client: Client | undefined): void { this._client = client; } /** - * @inheritDoc + * Set the ID of the last captured error event. + * This is generally only captured on the isolation scope. */ public setLastEventId(lastEventId: string | undefined): void { this._lastEventId = lastEventId; } /** - * @inheritDoc + * Get the client assigned to this scope. */ public getClient(): C | undefined { return this._client as C | undefined; } /** - * @inheritDoc + * Get the ID of the last captured error event. + * This is generally only available on the isolation scope. */ public lastEventId(): string | undefined { return this._lastEventId; @@ -193,7 +235,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Add an event processor that will be called before an event is sent. */ public addEventProcessor(callback: EventProcessor): this { this._eventProcessors.push(callback); @@ -201,7 +243,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set the user for this scope. + * Set to `null` to unset the user. */ public setUser(user: User | null): this { // If null is passed we want to unset everything, but still define keys, @@ -222,14 +265,16 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Get the user from this scope. */ public getUser(): User | undefined { return this._user; } /** - * @inheritDoc + * Get the request session from this scope. + * + * @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`; */ // eslint-disable-next-line deprecation/deprecation public getRequestSession(): RequestSession | undefined { @@ -237,7 +282,9 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set the request session for this scope. + * + * @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`; */ // eslint-disable-next-line deprecation/deprecation public setRequestSession(requestSession?: RequestSession): this { @@ -246,7 +293,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set an object that will be merged into existing tags on the scope, + * and will be sent as tags data with the event. */ public setTags(tags: { [key: string]: Primitive }): this { this._tags = { @@ -258,7 +306,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set a single tag that will be sent as tags data with the event. */ public setTag(key: string, value: Primitive): this { this._tags = { ...this._tags, [key]: value }; @@ -267,7 +315,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set an object that will be merged into existing extra on the scope, + * and will be sent as extra data with the event. */ public setExtras(extras: Extras): this { this._extra = { @@ -279,7 +328,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set a single key:value extra entry that will be sent as extra data with the event. */ public setExtra(key: string, extra: Extra): this { this._extra = { ...this._extra, [key]: extra }; @@ -288,7 +337,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Sets the fingerprint on the scope to send with the events. + * @param {string[]} fingerprint Fingerprint to group events in Sentry. */ public setFingerprint(fingerprint: string[]): this { this._fingerprint = fingerprint; @@ -297,7 +347,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Sets the level on the scope for future events. */ public setLevel(level: SeverityLevel): this { this._level = level; @@ -306,7 +356,15 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Sets the transaction name on the scope so that the name of the transaction + * (e.g. taken server route or page location) is attached to future events. + * + * IMPORTANT: Calling this function does NOT change the name of the currently active + * span. If you want to change the name of the active span, use `span.updateName()` + * instead. + * + * By default, the SDK updates the scope's transaction name automatically on sensible + * occasions, such as a page navigation or when handling a new request on the server. */ public setTransactionName(name?: string): this { this._transactionName = name; @@ -315,7 +373,9 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Sets context data with the given name. + * Data passed as context will be normalized. You can also pass `null` to unset the context. + * Note that context data will not be merged - calling `setContext` will overwrite an existing context with the same key. */ public setContext(key: string, context: Context | null): this { if (context === null) { @@ -330,7 +390,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Set the session for the scope. */ public setSession(session?: Session): this { if (!session) { @@ -343,14 +403,17 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Get the session from the scope. */ public getSession(): Session | undefined { return this._session; } /** - * @inheritDoc + * Updates the scope with provided data. Can work in three variations: + * - plain object containing updatable attributes + * - Scope instance that'll extract the attributes from + * - callback function that'll receive the current scope as an argument and allow for modifications */ public update(captureContext?: CaptureContext): this { if (!captureContext) { @@ -397,7 +460,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Clears the current scope and resets its properties. + * Note: The client will not be cleared. */ public clear(): this { // client is not cleared here on purpose! @@ -420,7 +484,8 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Adds a breadcrumb to the scope. + * By default, the last 100 breadcrumbs are kept. */ public addBreadcrumb(breadcrumb: Breadcrumb, maxBreadcrumbs?: number): this { const maxCrumbs = typeof maxBreadcrumbs === 'number' ? maxBreadcrumbs : DEFAULT_MAX_BREADCRUMBS; @@ -445,14 +510,14 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Get the last breadcrumb of the scope. */ public getLastBreadcrumb(): Breadcrumb | undefined { return this._breadcrumbs[this._breadcrumbs.length - 1]; } /** - * @inheritDoc + * Clear all breadcrumbs from the scope. */ public clearBreadcrumbs(): this { this._breadcrumbs = []; @@ -461,7 +526,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Add an attachment to the scope. */ public addAttachment(attachment: Attachment): this { this._attachments.push(attachment); @@ -469,14 +534,16 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Clear all attachments from the scope. */ public clearAttachments(): this { this._attachments = []; return this; } - /** @inheritDoc */ + /** + * Get the data of this scope, which should be applied to an event during processing. + */ public getScopeData(): ScopeData { return { breadcrumbs: this._breadcrumbs, @@ -496,7 +563,9 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Add data which will be accessible during event processing but won't get sent to Sentry. + * + * TODO(v9): We should type this stricter, so that e.g. `normalizedRequest` is strictly typed. */ public setSDKProcessingMetadata(newData: { [key: string]: unknown }): this { this._sdkProcessingMetadata = merge(this._sdkProcessingMetadata, newData, 2); @@ -504,7 +573,7 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Add propagation context to the scope, used for distributed tracing */ public setPropagationContext( context: Omit & Partial>, @@ -518,14 +587,16 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Get propagation context from the scope, used for distributed tracing */ public getPropagationContext(): PropagationContext { return this._propagationContext; } /** - * @inheritDoc + * Capture an exception for this scope. + * + * @returns {string} The id of the captured Sentry event. */ public captureException(exception: unknown, hint?: EventHint): string { const eventId = hint && hint.event_id ? hint.event_id : uuid4(); @@ -552,7 +623,9 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Capture a message for this scope. + * + * @returns {string} The id of the captured message. */ public captureMessage(message: string, level?: SeverityLevel, hint?: EventHint): string { const eventId = hint && hint.event_id ? hint.event_id : uuid4(); @@ -580,7 +653,9 @@ class ScopeClass implements ScopeInterface { } /** - * @inheritDoc + * Capture a Sentry event for this scope. + * + * @returns {string} The id of the captured event. */ public captureEvent(event: Event, hint?: EventHint): string { const eventId = hint && hint.event_id ? hint.event_id : uuid4(); @@ -611,13 +686,3 @@ class ScopeClass implements ScopeInterface { } } } - -/** - * Holds additional event information. - */ -export const Scope = ScopeClass; - -/** - * Holds additional event information. - */ -export type Scope = ScopeInterface; diff --git a/packages/core/src/tracing/dynamicSamplingContext.ts b/packages/core/src/tracing/dynamicSamplingContext.ts index cdf6951fe95b..824bfd4f7088 100644 --- a/packages/core/src/tracing/dynamicSamplingContext.ts +++ b/packages/core/src/tracing/dynamicSamplingContext.ts @@ -1,7 +1,8 @@ -import type { Client, DynamicSamplingContext, Scope, Span } from '../types-hoist'; +import type { Client, DynamicSamplingContext, Span } from '../types-hoist'; import { DEFAULT_ENVIRONMENT } from '../constants'; import { getClient } from '../currentScopes'; +import type { Scope } from '../scope'; import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes'; import { baggageHeaderToDynamicSamplingContext, diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts index d44d0b216db3..8fb911135fb8 100644 --- a/packages/core/src/tracing/trace.ts +++ b/packages/core/src/tracing/trace.ts @@ -2,12 +2,13 @@ import type { AsyncContextStrategy } from '../asyncContext/types'; import { getMainCarrier } from '../carrier'; -import type { ClientOptions, Scope, SentrySpanArguments, Span, SpanTimeInput, StartSpanOptions } from '../types-hoist'; +import type { ClientOptions, SentrySpanArguments, Span, SpanTimeInput, StartSpanOptions } from '../types-hoist'; import { getClient, getCurrentScope, getIsolationScope, withScope } from '../currentScopes'; import { getAsyncContextStrategy } from '../asyncContext'; import { DEBUG_BUILD } from '../debug-build'; +import type { Scope } from '../scope'; import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes'; import { logger } from '../utils-hoist/logger'; import { generateTraceId } from '../utils-hoist/propagationContext'; diff --git a/packages/core/src/tracing/utils.ts b/packages/core/src/tracing/utils.ts index a0442aa0eeec..61e2dcce2bc1 100644 --- a/packages/core/src/tracing/utils.ts +++ b/packages/core/src/tracing/utils.ts @@ -1,5 +1,5 @@ +import type { Scope } from '../scope'; import type { Span } from '../types-hoist'; -import type { Scope } from '../types-hoist'; import { addNonEnumerableProperty } from '../utils-hoist/object'; const SCOPE_ON_START_SPAN_FIELD = '_sentryScope'; diff --git a/packages/core/src/types-hoist/client.ts b/packages/core/src/types-hoist/client.ts index 06e3109e1e14..6186a188a526 100644 --- a/packages/core/src/types-hoist/client.ts +++ b/packages/core/src/types-hoist/client.ts @@ -1,3 +1,4 @@ +import type { Scope } from '../scope'; import type { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import type { CheckIn, MonitorConfig } from './checkin'; import type { EventDropReason } from './clientreport'; @@ -10,7 +11,6 @@ import type { FeedbackEvent } from './feedback'; import type { Integration } from './integration'; import type { ClientOptions } from './options'; import type { ParameterizedString } from './parameterize'; -import type { Scope } from './scope'; import type { SdkMetadata } from './sdkmetadata'; import type { Session, SessionAggregates } from './session'; import type { SeverityLevel } from './severity'; diff --git a/packages/core/src/types-hoist/event.ts b/packages/core/src/types-hoist/event.ts index ecfa5ad14559..ff7069d2fdc8 100644 --- a/packages/core/src/types-hoist/event.ts +++ b/packages/core/src/types-hoist/event.ts @@ -1,3 +1,4 @@ +import type { CaptureContext, Scope } from '../scope'; import type { Attachment } from './attachment'; import type { Breadcrumb } from './breadcrumb'; import type { Contexts } from './context'; @@ -10,7 +11,6 @@ import type { Mechanism } from './mechanism'; import type { Primitive } from './misc'; import type { PolymorphicRequest } from './polymorphics'; import type { RequestEventData } from './request'; -import type { CaptureContext, Scope } from './scope'; import type { SdkInfo } from './sdkinfo'; import type { SeverityLevel } from './severity'; import type { MetricSummary, SpanJSON } from './span'; diff --git a/packages/core/src/types-hoist/hub.ts b/packages/core/src/types-hoist/hub.ts index 6fa109145146..0e08a487fc0b 100644 --- a/packages/core/src/types-hoist/hub.ts +++ b/packages/core/src/types-hoist/hub.ts @@ -1,10 +1,10 @@ +import type { Scope } from '../scope'; import type { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import type { Client } from './client'; import type { Event, EventHint } from './event'; import type { Extra, Extras } from './extra'; import type { Integration, IntegrationClass } from './integration'; import type { Primitive } from './misc'; -import type { Scope } from './scope'; import type { Session } from './session'; import type { SeverityLevel } from './severity'; import type { User } from './user'; diff --git a/packages/core/src/types-hoist/index.ts b/packages/core/src/types-hoist/index.ts index 3433c17092cf..f9fbf080153a 100644 --- a/packages/core/src/types-hoist/index.ts +++ b/packages/core/src/types-hoist/index.ts @@ -97,7 +97,6 @@ export type { SanitizedRequestData, } from './request'; export type { Runtime } from './runtime'; -export type { CaptureContext, Scope, ScopeContext, ScopeData } from './scope'; export type { SdkInfo } from './sdkinfo'; export type { SdkMetadata } from './sdkmetadata'; export type { diff --git a/packages/core/src/types-hoist/options.ts b/packages/core/src/types-hoist/options.ts index 38748df82fd5..a16e491c0c7a 100644 --- a/packages/core/src/types-hoist/options.ts +++ b/packages/core/src/types-hoist/options.ts @@ -1,8 +1,8 @@ +import type { CaptureContext } from '../scope'; import type { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import type { ErrorEvent, EventHint, TransactionEvent } from './event'; import type { Integration } from './integration'; import type { SamplingContext } from './samplingcontext'; -import type { CaptureContext } from './scope'; import type { SdkMetadata } from './sdkmetadata'; import type { SpanJSON } from './span'; import type { StackLineParser, StackParser } from './stacktrace'; diff --git a/packages/core/src/types-hoist/scope.ts b/packages/core/src/types-hoist/scope.ts deleted file mode 100644 index 57990d310820..000000000000 --- a/packages/core/src/types-hoist/scope.ts +++ /dev/null @@ -1,277 +0,0 @@ -import type { Attachment } from './attachment'; -import type { Breadcrumb } from './breadcrumb'; -import type { Client } from './client'; -import type { Context, Contexts } from './context'; -import type { Event, EventHint } from './event'; -import type { EventProcessor } from './eventprocessor'; -import type { Extra, Extras } from './extra'; -import type { Primitive } from './misc'; -import type { RequestSession, Session } from './session'; -import type { SeverityLevel } from './severity'; -import type { Span } from './span'; -import type { PropagationContext } from './tracing'; -import type { User } from './user'; - -/** JSDocs */ -export type CaptureContext = Scope | Partial | ((scope: Scope) => Scope); - -/** JSDocs */ -export interface ScopeContext { - user: User; - level: SeverityLevel; - extra: Extras; - contexts: Contexts; - tags: { [key: string]: Primitive }; - fingerprint: string[]; - // eslint-disable-next-line deprecation/deprecation - requestSession: RequestSession; - propagationContext: PropagationContext; -} - -export interface ScopeData { - eventProcessors: EventProcessor[]; - breadcrumbs: Breadcrumb[]; - user: User; - tags: { [key: string]: Primitive }; - extra: Extras; - contexts: Contexts; - attachments: Attachment[]; - propagationContext: PropagationContext; - sdkProcessingMetadata: { [key: string]: unknown }; - fingerprint: string[]; - level?: SeverityLevel; - transactionName?: string; - span?: Span; -} - -/** - * Holds additional event information. - */ -export interface Scope { - /** - * Update the client on the scope. - */ - setClient(client: Client | undefined): void; - - /** - * Get the client assigned to this scope. - * - * It is generally recommended to use the global function `Sentry.getClient()` instead, unless you know what you are doing. - */ - getClient(): C | undefined; - - /** - * Sets the last event id on the scope. - * @param lastEventId The last event id of a captured event. - */ - setLastEventId(lastEventId: string | undefined): void; - - /** - * This is the getter for lastEventId. - * @returns The last event id of a captured event. - */ - lastEventId(): string | undefined; - - /** - * Add internal on change listener. Used for sub SDKs that need to store the scope. - * @hidden - */ - addScopeListener(callback: (scope: Scope) => void): void; - - /** Add new event processor that will be called during event processing. */ - addEventProcessor(callback: EventProcessor): this; - - /** Get the data of this scope, which is applied to an event during processing. */ - getScopeData(): ScopeData; - - /** - * Updates user context information for future events. - * - * @param user User context object to be set in the current context. Pass `null` to unset the user. - */ - setUser(user: User | null): this; - - /** - * Returns the `User` if there is one - */ - getUser(): User | undefined; - - /** - * Set an object that will be merged sent as tags data with the event. - * @param tags Tags context object to merge into current context. - */ - setTags(tags: { [key: string]: Primitive }): this; - - /** - * Set key:value that will be sent as tags data with the event. - * - * Can also be used to unset a tag by passing `undefined`. - * - * @param key String key of tag - * @param value Value of tag - */ - setTag(key: string, value: Primitive): this; - - /** - * Set an object that will be merged sent as extra data with the event. - * @param extras Extras object to merge into current context. - */ - setExtras(extras: Extras): this; - - /** - * Set key:value that will be sent as extra data with the event. - * @param key String of extra - * @param extra Any kind of data. This data will be normalized. - */ - setExtra(key: string, extra: Extra): this; - - /** - * Sets the fingerprint on the scope to send with the events. - * @param fingerprint string[] to group events in Sentry. - */ - setFingerprint(fingerprint: string[]): this; - - /** - * Sets the level on the scope for future events. - * @param level string {@link SeverityLevel} - */ - setLevel(level: SeverityLevel): this; - - /** - * Sets the transaction name on the scope so that the name of the transaction - * (e.g. taken server route or page location) is attached to future events. - * - * IMPORTANT: Calling this function does NOT change the name of the currently active - * span. If you want to change the name of the active span, use `span.updateName()` - * instead. - * - * By default, the SDK updates the scope's transaction name automatically on sensible - * occasions, such as a page navigation or when handling a new request on the server. - */ - setTransactionName(name?: string): this; - - /** - * Sets context data with the given name. - * @param name of the context - * @param context an object containing context data. This data will be normalized. Pass `null` to unset the context. - */ - setContext(name: string, context: Context | null): this; - - /** - * Returns the `Session` if there is one - */ - getSession(): Session | undefined; - - /** - * Sets the `Session` on the scope - */ - setSession(session?: Session): this; - - /** - * Returns the `RequestSession` if there is one - * - * @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`; - */ - // eslint-disable-next-line deprecation/deprecation - getRequestSession(): RequestSession | undefined; - - /** - * Sets the `RequestSession` on the scope - * - * @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`; - */ - // eslint-disable-next-line deprecation/deprecation - setRequestSession(requestSession?: RequestSession): this; - - /** - * Updates the scope with provided data. Can work in three variations: - * - plain object containing updatable attributes - * - Scope instance that'll extract the attributes from - * - callback function that'll receive the current scope as an argument and allow for modifications - * @param captureContext scope modifier to be used - */ - update(captureContext?: CaptureContext): this; - - /** Clears the current scope and resets its properties. */ - clear(): this; - - /** - * Adds a breadcrumb to the scope - * @param breadcrumb Breadcrumb - * @param maxBreadcrumbs number of max breadcrumbs to merged into event. - */ - addBreadcrumb(breadcrumb: Breadcrumb, maxBreadcrumbs?: number): this; - - /** - * Get the last breadcrumb. - */ - getLastBreadcrumb(): Breadcrumb | undefined; - - /** - * Clears all breadcrumbs from the scope. - */ - clearBreadcrumbs(): this; - - /** - * Adds an attachment to the scope - * @param attachment Attachment options - */ - addAttachment(attachment: Attachment): this; - - /** - * Clears attachments from the scope - */ - clearAttachments(): this; - - /** - * Add data which will be accessible during event processing but won't get sent to Sentry. - * - * TODO(v9): We should type this stricter, so that e.g. `normalizedRequest` is strictly typed. - */ - setSDKProcessingMetadata(newData: { [key: string]: unknown }): this; - - /** - * Add propagation context to the scope, used for distributed tracing - */ - setPropagationContext( - context: Omit & Partial>, - ): this; - - /** - * Get propagation context from the scope, used for distributed tracing - */ - getPropagationContext(): PropagationContext; - - /** - * Capture an exception for this scope. - * - * @param exception The exception to capture. - * @param hint Optional additional data to attach to the Sentry event. - * @returns the id of the captured Sentry event. - */ - captureException(exception: unknown, hint?: EventHint): string; - - /** - * Capture a message for this scope. - * - * @param message The message to capture. - * @param level An optional severity level to report the message with. - * @param hint Optional additional data to attach to the Sentry event. - * @returns the id of the captured message. - */ - captureMessage(message: string, level?: SeverityLevel, hint?: EventHint): string; - - /** - * Capture a Sentry event for this scope. - * - * @param event The event to capture. - * @param hint Optional additional data to attach to the Sentry event. - * @returns the id of the captured event. - */ - captureEvent(event: Event, hint?: EventHint): string; - - /** - * Clone all data from this scope into a new scope. - */ - clone(): Scope; -} diff --git a/packages/core/src/types-hoist/startSpanOptions.ts b/packages/core/src/types-hoist/startSpanOptions.ts index 35d5326e32f3..5d17cec579dd 100644 --- a/packages/core/src/types-hoist/startSpanOptions.ts +++ b/packages/core/src/types-hoist/startSpanOptions.ts @@ -1,4 +1,4 @@ -import type { Scope } from './scope'; +import type { Scope } from '../scope'; import type { Span, SpanAttributes, SpanTimeInput } from './span'; export interface StartSpanOptions { diff --git a/packages/core/src/utils/applyScopeDataToEvent.ts b/packages/core/src/utils/applyScopeDataToEvent.ts index 22bf7b06e503..93043b632c2d 100644 --- a/packages/core/src/utils/applyScopeDataToEvent.ts +++ b/packages/core/src/utils/applyScopeDataToEvent.ts @@ -1,5 +1,6 @@ +import type { ScopeData } from '../scope'; import { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext'; -import type { Breadcrumb, Event, ScopeData, Span } from '../types-hoist'; +import type { Breadcrumb, Event, Span } from '../types-hoist'; import { dropUndefinedKeys } from '../utils-hoist/object'; import { merge } from './merge'; import { getRootSpan, spanToJSON, spanToTraceContext } from './spanUtils'; diff --git a/packages/core/src/utils/prepareEvent.ts b/packages/core/src/utils/prepareEvent.ts index d38676f40550..d6463b73d9d3 100644 --- a/packages/core/src/utils/prepareEvent.ts +++ b/packages/core/src/utils/prepareEvent.ts @@ -1,17 +1,9 @@ -import type { - CaptureContext, - Client, - ClientOptions, - Event, - EventHint, - Scope as ScopeInterface, - ScopeContext, - StackParser, -} from '../types-hoist'; +import type { Client, ClientOptions, Event, EventHint, StackParser } from '../types-hoist'; import { DEFAULT_ENVIRONMENT } from '../constants'; import { getGlobalScope } from '../currentScopes'; import { notifyEventProcessors } from '../eventProcessors'; +import type { CaptureContext, ScopeContext } from '../scope'; import { Scope } from '../scope'; import { getFilenameToDebugIdMap } from '../utils-hoist/debug-ids'; import { addExceptionMechanism, uuid4 } from '../utils-hoist/misc'; @@ -48,9 +40,9 @@ export function prepareEvent( options: ClientOptions, event: Event, hint: EventHint, - scope?: ScopeInterface, + scope?: Scope, client?: Client, - isolationScope?: ScopeInterface, + isolationScope?: Scope, ): PromiseLike { const { normalizeDepth = 3, normalizeMaxBreadth = 1_000 } = options; const prepared: Event = { @@ -317,10 +309,7 @@ function normalizeEvent(event: Event | null, depth: number, maxBreadth: number): return normalized; } -function getFinalScope( - scope: ScopeInterface | undefined, - captureContext: CaptureContext | undefined, -): ScopeInterface | undefined { +function getFinalScope(scope: Scope | undefined, captureContext: CaptureContext | undefined): Scope | undefined { if (!captureContext) { return scope; } @@ -355,9 +344,7 @@ export function parseEventHintOrCaptureContext( return hint; } -function hintIsScopeOrFunction( - hint: CaptureContext | EventHint, -): hint is ScopeInterface | ((scope: ScopeInterface) => ScopeInterface) { +function hintIsScopeOrFunction(hint: CaptureContext | EventHint): hint is Scope | ((scope: Scope) => Scope) { return hint instanceof Scope || typeof hint === 'function'; } diff --git a/packages/core/src/utils/spanOnScope.ts b/packages/core/src/utils/spanOnScope.ts index bdc47b66d208..33d0ff80dd12 100644 --- a/packages/core/src/utils/spanOnScope.ts +++ b/packages/core/src/utils/spanOnScope.ts @@ -1,4 +1,5 @@ -import type { Scope, Span } from '../types-hoist'; +import type { Scope } from '../scope'; +import type { Span } from '../types-hoist'; import { addNonEnumerableProperty } from '../utils-hoist/object'; const SCOPE_SPAN_FIELD = '_sentrySpan'; diff --git a/packages/core/src/utils/traceData.ts b/packages/core/src/utils/traceData.ts index b73ddf2828bf..833df518295d 100644 --- a/packages/core/src/utils/traceData.ts +++ b/packages/core/src/utils/traceData.ts @@ -2,8 +2,9 @@ import { getAsyncContextStrategy } from '../asyncContext'; import { getMainCarrier } from '../carrier'; import { getClient, getCurrentScope } from '../currentScopes'; import { isEnabled } from '../exports'; +import type { Scope } from '../scope'; import { getDynamicSamplingContextFromScope, getDynamicSamplingContextFromSpan } from '../tracing'; -import type { Scope, SerializedTraceData, Span } from '../types-hoist'; +import type { SerializedTraceData, Span } from '../types-hoist'; import { dynamicSamplingContextToSentryBaggageHeader } from '../utils-hoist/baggage'; import { logger } from '../utils-hoist/logger'; import { TRACEPARENT_REGEXP, generateSentryTraceHeader } from '../utils-hoist/tracing'; diff --git a/packages/core/test/lib/prepareEvent.test.ts b/packages/core/test/lib/prepareEvent.test.ts index bd0798cc0898..5f8be2050a9e 100644 --- a/packages/core/test/lib/prepareEvent.test.ts +++ b/packages/core/test/lib/prepareEvent.test.ts @@ -1,3 +1,4 @@ +import type { ScopeContext } from '../../src'; import { GLOBAL_OBJ, createStackParser, getGlobalScope, getIsolationScope } from '../../src'; import type { Attachment, @@ -7,7 +8,6 @@ import type { Event, EventHint, EventProcessor, - ScopeContext, } from '../../src/types-hoist'; import { Scope } from '../../src/scope'; diff --git a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts index cb2757c95301..f64e91976cc3 100644 --- a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts +++ b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts @@ -1,5 +1,6 @@ +import type { ScopeData } from '../../../src'; import { startInactiveSpan } from '../../../src'; -import type { Attachment, Breadcrumb, Event, EventProcessor, EventType, ScopeData } from '../../../src/types-hoist'; +import type { Attachment, Breadcrumb, Event, EventProcessor, EventType } from '../../../src/types-hoist'; import { applyScopeDataToEvent, mergeAndOverwriteScopeData, diff --git a/packages/core/test/utils-hoist/requestdata.test.ts b/packages/core/test/utils-hoist/requestdata.test.ts index a36a0669dc7b..801aa6c4a296 100644 --- a/packages/core/test/utils-hoist/requestdata.test.ts +++ b/packages/core/test/utils-hoist/requestdata.test.ts @@ -1,6 +1,6 @@ /* eslint-disable deprecation/deprecation */ import type * as net from 'net'; -import { addRequestDataToEvent, extractPathForTransaction, extractRequestData } from '@sentry/core'; +import { addRequestDataToEvent, extractPathForTransaction, extractRequestData } from '../../src'; import type { Event, PolymorphicRequest, TransactionSource, User } from '../../src/types-hoist'; import { getClientIPAddress } from '../../src/utils-hoist/vendor/getIpAddress'; diff --git a/packages/deno/package.json b/packages/deno/package.json index 851252d0435f..15d6c0fde360 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -35,7 +35,7 @@ "deno-types": "node ./scripts/download-deno-types.mjs", "build": "run-s build:transpile build:types", "build:dev": "yarn build", - "build:transpile": "yarn deno-types && rollup -c rollup.config.mjs", + "build:transpile": "yarn rimraf node_modules/.deno && yarn deno-types && rollup -c rollup.config.mjs", "build:types": "run-s deno-types build:types:tsc build:types:bundle", "build:types:tsc": "tsc -p tsconfig.types.json", "build:types:bundle": "rollup -c rollup.types.config.mjs", From 9f4204b8e7d20b65a4354e94866ce9ae57669895 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 16 Dec 2024 17:01:37 +0100 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Sigrid Huemer <32902192+s1gr1d@users.noreply.github.com> --- docs/migration/v8-to-v9.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/migration/v8-to-v9.md b/docs/migration/v8-to-v9.md index 56ebd37f8bed..4bcdfb4127b2 100644 --- a/docs/migration/v8-to-v9.md +++ b/docs/migration/v8-to-v9.md @@ -108,8 +108,8 @@ Let us know if this is causing issues in your setup by opening an issue on GitHu ## 6. Type Changes In v8, types have been exported from `@sentry/types`, while implementations have been exported from other classes. -This lead to some duplication, where we had to keep an interface in `@sentry/types`, while the implementation mirroring that interface was kept e.g. in `@sentry/core`. -Since in v9 the types have been merged into `@sentry/core`, we can get rid of some of this duplication. This means that certain things that used to be a separate interface, will not expect an actual instance of the class/concrete implementation. This should not affect most users, unless you relied on passing things with a similar shape to internal methods. The following types are affected: +This led to some duplication, where we had to keep an interface in `@sentry/types`, while the implementation mirroring that interface was kept e.g. in `@sentry/core`. +Since v9, the types have been merged into `@sentry/core`, which removed some of this duplication. This means that certain things that used to be a separate interface, will not expect an actual instance of the class/concrete implementation. This should not affect most users, unless you relied on passing things with a similar shape to internal methods. The following types are affected: - `Scope` now always expects the `Scope` class From c7a8c700c137a8deb7e311c4d3018ce528bb7854 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 17 Dec 2024 08:33:48 +0100 Subject: [PATCH 3/3] remove deno package change --- packages/deno/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/deno/package.json b/packages/deno/package.json index 15d6c0fde360..851252d0435f 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -35,7 +35,7 @@ "deno-types": "node ./scripts/download-deno-types.mjs", "build": "run-s build:transpile build:types", "build:dev": "yarn build", - "build:transpile": "yarn rimraf node_modules/.deno && yarn deno-types && rollup -c rollup.config.mjs", + "build:transpile": "yarn deno-types && rollup -c rollup.config.mjs", "build:types": "run-s deno-types build:types:tsc build:types:bundle", "build:types:tsc": "tsc -p tsconfig.types.json", "build:types:bundle": "rollup -c rollup.types.config.mjs",