diff --git a/packages/angular/src/sdk.ts b/packages/angular/src/sdk.ts index 344ba91183df..f8481a110887 100755 --- a/packages/angular/src/sdk.ts +++ b/packages/angular/src/sdk.ts @@ -13,7 +13,7 @@ import { functionToStringIntegration, inboundFiltersIntegration, } from '@sentry/core'; -import type { Integration } from '@sentry/types'; +import type { Client, Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; import { IS_DEBUG_BUILD } from './flags'; @@ -44,7 +44,7 @@ export function getDefaultIntegrations(): Integration[] { /** * Inits the Angular SDK */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { defaultIntegrations: getDefaultIntegrations(), ...options, @@ -53,7 +53,7 @@ export function init(options: BrowserOptions): void { applySdkMetadata(opts, 'angular'); checkAndSetAngularVersion(); - browserInit(opts); + return browserInit(opts); } function checkAndSetAngularVersion(): void { diff --git a/packages/angular/test/sdk.test.ts b/packages/angular/test/sdk.test.ts index 54756fba72fe..d3d41df6f5bf 100644 --- a/packages/angular/test/sdk.test.ts +++ b/packages/angular/test/sdk.test.ts @@ -26,4 +26,8 @@ describe('init', () => { expect(angularDefaultIntegrations).toEqual(browserDefaultIntegrationsWithoutBrowserApiErrors); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); diff --git a/packages/astro/src/client/sdk.ts b/packages/astro/src/client/sdk.ts index b23edc27f54a..a43c4211f047 100644 --- a/packages/astro/src/client/sdk.ts +++ b/packages/astro/src/client/sdk.ts @@ -6,7 +6,7 @@ import { setTag, } from '@sentry/browser'; import { applySdkMetadata, hasTracingEnabled } from '@sentry/core'; -import type { Integration } from '@sentry/types'; +import type { Client, Integration } from '@sentry/types'; // Tree-shakable guard to remove all code related to tracing declare const __SENTRY_TRACING__: boolean; @@ -16,7 +16,7 @@ declare const __SENTRY_TRACING__: boolean; * * @param options Configuration options for the SDK. */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { defaultIntegrations: getDefaultIntegrations(options), ...options, @@ -24,9 +24,11 @@ export function init(options: BrowserOptions): void { applySdkMetadata(opts, 'astro', ['astro', 'browser']); - initBrowserSdk(opts); + const client = initBrowserSdk(opts); setTag('runtime', 'browser'); + + return client; } function getDefaultIntegrations(options: BrowserOptions): Integration[] | undefined { diff --git a/packages/astro/src/server/sdk.ts b/packages/astro/src/server/sdk.ts index 503557d6d7cd..cb2cec03f982 100644 --- a/packages/astro/src/server/sdk.ts +++ b/packages/astro/src/server/sdk.ts @@ -1,19 +1,21 @@ import { applySdkMetadata } from '@sentry/core'; -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { init as initNodeSdk, setTag } from '@sentry/node'; /** * * @param options */ -export function init(options: NodeOptions): void { +export function init(options: NodeOptions): NodeClient | undefined { const opts = { ...options, }; applySdkMetadata(opts, 'astro', ['astro', 'node']); - initNodeSdk(opts); + const client = initNodeSdk(opts); setTag('runtime', 'node'); + + return client; } diff --git a/packages/astro/test/client/sdk.test.ts b/packages/astro/test/client/sdk.test.ts index 23078dec65f5..4e7882b33e32 100644 --- a/packages/astro/test/client/sdk.test.ts +++ b/packages/astro/test/client/sdk.test.ts @@ -122,5 +122,9 @@ describe('Sentry client SDK', () => { expect(getActiveSpan()).toBeUndefined(); }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); }); diff --git a/packages/astro/test/server/sdk.test.ts b/packages/astro/test/server/sdk.test.ts index 1b042ee5331a..b1f9c3854b77 100644 --- a/packages/astro/test/server/sdk.test.ts +++ b/packages/astro/test/server/sdk.test.ts @@ -46,5 +46,9 @@ describe('Sentry server SDK', () => { expect(SentryNode.getIsolationScope().getScopeData().tags).toEqual({ runtime: 'node' }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); }); diff --git a/packages/aws-serverless/src/sdk.ts b/packages/aws-serverless/src/sdk.ts index 30fdbc19635f..8ed86d9f23d4 100644 --- a/packages/aws-serverless/src/sdk.ts +++ b/packages/aws-serverless/src/sdk.ts @@ -2,7 +2,7 @@ import { existsSync } from 'fs'; import { hostname } from 'os'; import { basename, resolve } from 'path'; import { types } from 'util'; -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { SDK_VERSION, captureException, @@ -74,7 +74,7 @@ export function getDefaultIntegrations(_options: Options): Integration[] { * * @param options Configuration options for the SDK, @see {@link AWSLambdaOptions}. */ -export function init(options: NodeOptions = {}): void { +export function init(options: NodeOptions = {}): NodeClient | undefined { const opts = { _metadata: {} as SdkMetadata, defaultIntegrations: getDefaultIntegrations(options), @@ -93,7 +93,7 @@ export function init(options: NodeOptions = {}): void { version: SDK_VERSION, }; - initWithoutDefaultIntegrations(opts); + return initWithoutDefaultIntegrations(opts); } /** */ diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index ea24a475d959..522f87e33d8b 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -9,7 +9,7 @@ import { lastEventId, startSession, } from '@sentry/core'; -import type { DsnLike, Integration, Options, UserFeedback } from '@sentry/types'; +import type { Client, DsnLike, Integration, Options, UserFeedback } from '@sentry/types'; import { consoleSandbox, logger, stackParserFromStackParserOptions, supportsFetch } from '@sentry/utils'; import { addHistoryInstrumentationHandler } from '@sentry-internal/browser-utils'; @@ -139,7 +139,7 @@ declare const __SENTRY_RELEASE__: string | undefined; * * @see {@link BrowserOptions} for documentation on configuration options. */ -export function init(browserOptions: BrowserOptions = {}): void { +export function init(browserOptions: BrowserOptions = {}): Client | undefined { const options = applyDefaultOptions(browserOptions); if (shouldShowBrowserExtensionError()) { @@ -166,11 +166,13 @@ export function init(browserOptions: BrowserOptions = {}): void { transport: options.transport || makeFetchTransport, }; - initAndBind(BrowserClient, clientOptions); + const client = initAndBind(BrowserClient, clientOptions); if (options.autoSessionTracking) { startSessionTracking(); } + + return client; } /** diff --git a/packages/browser/test/unit/sdk.test.ts b/packages/browser/test/unit/sdk.test.ts index 22c220e7d0f1..dad7e37af0ce 100644 --- a/packages/browser/test/unit/sdk.test.ts +++ b/packages/browser/test/unit/sdk.test.ts @@ -209,5 +209,25 @@ describe('init', () => { consoleErrorSpy.mockRestore(); }); + + it("doesn't return a client on initialization error", () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + Object.defineProperty(WINDOW, 'chrome', { + value: { runtime: { id: 'mock-extension-id' } }, + writable: true, + }); + + const client = init(options); + + expect(client).toBeUndefined(); + + consoleErrorSpy.mockRestore(); + }); + }); + + it('returns a client from init', () => { + const client = init(); + expect(client).not.toBeUndefined(); }); }); diff --git a/packages/bun/src/sdk.ts b/packages/bun/src/sdk.ts index f299c8119985..534592a9ebb9 100644 --- a/packages/bun/src/sdk.ts +++ b/packages/bun/src/sdk.ts @@ -4,6 +4,7 @@ import { linkedErrorsIntegration, requestDataIntegration, } from '@sentry/core'; +import type { NodeClient } from '@sentry/node'; import { consoleIntegration, contextLinesIntegration, @@ -91,7 +92,7 @@ export function getDefaultIntegrations(_options: Options): Integration[] { * * @see {@link BunOptions} for documentation on configuration options. */ -export function init(options: BunOptions = {}): void { +export function init(options: BunOptions = {}): NodeClient | undefined { options.clientClass = BunClient; options.transport = options.transport || makeFetchTransport; @@ -99,5 +100,5 @@ export function init(options: BunOptions = {}): void { options.defaultIntegrations = getDefaultIntegrations(options); } - initNode(options); + return initNode(options); } diff --git a/packages/bun/test/sdk.test.ts b/packages/bun/test/sdk.test.ts index 6eb562c0c4e1..acef85f55eb5 100644 --- a/packages/bun/test/sdk.test.ts +++ b/packages/bun/test/sdk.test.ts @@ -8,3 +8,7 @@ test("calling init shouldn't fail", () => { }); expect(true).toBe(true); }); + +test('shuold return client from init', () => { + expect(init({})).not.toBeUndefined(); +}); diff --git a/packages/core/src/sdk.ts b/packages/core/src/sdk.ts index d4c974242e1b..d78f8f253186 100644 --- a/packages/core/src/sdk.ts +++ b/packages/core/src/sdk.ts @@ -17,7 +17,7 @@ export type ClientClass = new (option export function initAndBind( clientClass: ClientClass, options: O, -): void { +): Client { if (options.debug === true) { if (DEBUG_BUILD) { logger.enable(); @@ -35,6 +35,7 @@ export function initAndBind( const client = new clientClass(options); setCurrentClient(client); client.init(); + return client; } /** diff --git a/packages/core/test/lib/sdk.test.ts b/packages/core/test/lib/sdk.test.ts index 3d0604c436de..74213cd8d99f 100644 --- a/packages/core/test/lib/sdk.test.ts +++ b/packages/core/test/lib/sdk.test.ts @@ -82,6 +82,12 @@ describe('SDK', () => { 'afterAllSetup2', ]); }); + + test('returns client from init', () => { + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); + const client = initAndBind(TestClient, options); + expect(client).not.toBeUndefined(); + }); }); }); diff --git a/packages/deno/src/sdk.ts b/packages/deno/src/sdk.ts index 9ce7761bcea9..c2a459b4db33 100644 --- a/packages/deno/src/sdk.ts +++ b/packages/deno/src/sdk.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/consistent-type-imports */ import type { ServerRuntimeClientOptions } from '@sentry/core'; import { dedupeIntegration, @@ -6,7 +7,7 @@ import { linkedErrorsIntegration, } from '@sentry/core'; import { getIntegrationsToSetup, initAndBind } from '@sentry/core'; -import type { Integration, Options, StackParser } from '@sentry/types'; +import type { Client, Integration, Options, StackParser } from '@sentry/types'; import { createStackParser, nodeStackLineParser, stackParserFromStackParserOptions } from '@sentry/utils'; import { DenoClient } from './client'; @@ -82,7 +83,7 @@ const defaultStackParser: StackParser = createStackParser(nodeStackLineParser()) * * @see {@link DenoOptions} for documentation on configuration options. */ -export function init(options: DenoOptions = {}): void { +export function init(options: DenoOptions = {}): Client { if (options.defaultIntegrations === undefined) { options.defaultIntegrations = getDefaultIntegrations(options); } @@ -94,5 +95,5 @@ export function init(options: DenoOptions = {}): void { transport: options.transport || makeFetchTransport, }; - initAndBind(DenoClient, clientOptions); + return initAndBind(DenoClient, clientOptions); } diff --git a/packages/deno/test/sdk.test.ts b/packages/deno/test/sdk.test.ts new file mode 100644 index 000000000000..508ef983762a --- /dev/null +++ b/packages/deno/test/sdk.test.ts @@ -0,0 +1,6 @@ +import { assertNotEquals } from 'https://deno.land/std@0.202.0/assert/assert_not_equals.ts'; +import { init } from '../build/index.mjs'; + +Deno.test('init() should return client', () => { + assertNotEquals(init({}), undefined); +}); diff --git a/packages/ember/addon/index.ts b/packages/ember/addon/index.ts index 33ba495e5acc..341d74763634 100644 --- a/packages/ember/addon/index.ts +++ b/packages/ember/addon/index.ts @@ -9,7 +9,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, app import { GLOBAL_OBJ } from '@sentry/utils'; import Ember from 'ember'; -import type { TransactionSource } from '@sentry/types'; +import type { Client, TransactionSource } from '@sentry/types'; import type { EmberSentryConfig, GlobalConfig, OwnConfig } from './types'; function _getSentryInitConfig(): EmberSentryConfig['sentry'] { @@ -21,7 +21,7 @@ function _getSentryInitConfig(): EmberSentryConfig['sentry'] { /** * Initialize the Sentry SDK for Ember. */ -export function init(_runtimeConfig?: BrowserOptions): void { +export function init(_runtimeConfig?: BrowserOptions): Client | undefined { const environmentConfig = getOwnConfig().sentryConfig; assert('Missing configuration.', environmentConfig); @@ -42,11 +42,11 @@ export function init(_runtimeConfig?: BrowserOptions): void { const sentryInitConfig = _getSentryInitConfig(); Object.assign(sentryInitConfig, initConfig); - Sentry.init(initConfig); + const client = Sentry.init(initConfig); if (macroCondition(isDevelopingApp())) { if (environmentConfig.ignoreEmberOnErrorWarning) { - return; + return client; } next(null, function () { warn( @@ -58,6 +58,8 @@ export function init(_runtimeConfig?: BrowserOptions): void { ); }); } + + return client; } type RouteConstructor = new (...args: ConstructorParameters) => Route; diff --git a/packages/gatsby/src/sdk.ts b/packages/gatsby/src/sdk.ts index 48dfd5bb0b31..93e9ee7617e4 100644 --- a/packages/gatsby/src/sdk.ts +++ b/packages/gatsby/src/sdk.ts @@ -1,14 +1,15 @@ import { applySdkMetadata } from '@sentry/core'; import { init as reactInit } from '@sentry/react'; +import type { Client } from '@sentry/types'; import type { GatsbyOptions } from './utils/types'; /** * Inits the Sentry Gatsby SDK. */ -export function init(options: GatsbyOptions): void { +export function init(options: GatsbyOptions): Client | undefined { applySdkMetadata(options, 'gatsby'); - reactInit({ + return reactInit({ ...options, }); } diff --git a/packages/google-cloud-serverless/src/sdk.ts b/packages/google-cloud-serverless/src/sdk.ts index 96ccd938f66a..2f6f6162a9b5 100644 --- a/packages/google-cloud-serverless/src/sdk.ts +++ b/packages/google-cloud-serverless/src/sdk.ts @@ -1,4 +1,4 @@ -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { SDK_VERSION, getDefaultIntegrationsWithoutPerformance, init as initNode } from '@sentry/node'; import type { Integration, Options, SdkMetadata } from '@sentry/types'; @@ -26,7 +26,7 @@ export function getDefaultIntegrations(_options: Options): Integration[] { /** * @see {@link Sentry.init} */ -export function init(options: NodeOptions = {}): void { +export function init(options: NodeOptions = {}): NodeClient | undefined { const opts = { _metadata: {} as SdkMetadata, defaultIntegrations: getDefaultIntegrations(options), @@ -44,5 +44,5 @@ export function init(options: NodeOptions = {}): void { version: SDK_VERSION, }; - initNode(opts); + return initNode(opts); } diff --git a/packages/nextjs/src/client/index.ts b/packages/nextjs/src/client/index.ts index 157e2cf70560..49a8fefb22d9 100644 --- a/packages/nextjs/src/client/index.ts +++ b/packages/nextjs/src/client/index.ts @@ -1,7 +1,7 @@ import { addEventProcessor, applySdkMetadata, hasTracingEnabled, setTag } from '@sentry/core'; import type { BrowserOptions } from '@sentry/react'; import { getDefaultIntegrations as getReactDefaultIntegrations, init as reactInit } from '@sentry/react'; -import type { EventProcessor, Integration } from '@sentry/types'; +import type { Client, EventProcessor, Integration } from '@sentry/types'; import { GLOBAL_OBJ } from '@sentry/utils'; import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor'; @@ -22,7 +22,7 @@ const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & { declare const __SENTRY_TRACING__: boolean; /** Inits the Sentry NextJS SDK on the browser with the React SDK. */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { environment: getVercelEnv(true) || process.env.NODE_ENV, defaultIntegrations: getDefaultIntegrations(options), @@ -32,7 +32,7 @@ export function init(options: BrowserOptions): void { applyTunnelRouteOption(opts); applySdkMetadata(opts, 'nextjs', ['nextjs', 'react']); - reactInit(opts); + const client = reactInit(opts); setTag('runtime', 'browser'); const filterTransactions: EventProcessor = event => @@ -43,6 +43,8 @@ export function init(options: BrowserOptions): void { if (process.env.NODE_ENV === 'development') { addEventProcessor(devErrorSymbolicationEventProcessor); } + + return client; } function getDefaultIntegrations(options: BrowserOptions): Integration[] { diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 9ffdcfdc6225..741c4092c61b 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -1,6 +1,6 @@ import { applySdkMetadata, getClient, getGlobalScope } from '@sentry/core'; import { getDefaultIntegrations, init as nodeInit } from '@sentry/node'; -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { GLOBAL_OBJ, logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build'; @@ -81,7 +81,7 @@ export function showReportDialog(): void { } /** Inits the Sentry NextJS SDK on node. */ -export function init(options: NodeOptions): void { +export function init(options: NodeOptions): NodeClient | undefined { if (isBuild()) { return; } @@ -127,9 +127,8 @@ export function init(options: NodeOptions): void { applySdkMetadata(opts, 'nextjs', ['nextjs', 'node']); - nodeInit(opts); + const client = nodeInit(opts); - const client = getClient(); client?.on('beforeSampling', ({ spanAttributes, spanName, parentSampled, parentContext }, samplingDecision) => { // If we encounter a span emitted by Next.js, we do not want to sample it // The reason for this is that the data quality of the spans varies, it is different per version of Next, @@ -221,6 +220,8 @@ export function init(options: NodeOptions): void { } DEBUG_BUILD && logger.log('SDK successfully initialized'); + + return client; } function sdkAlreadyInitialized(): boolean { diff --git a/packages/nextjs/test/clientSdk.test.ts b/packages/nextjs/test/clientSdk.test.ts index 67e6804f1a1b..1749a3b824d4 100644 --- a/packages/nextjs/test/clientSdk.test.ts +++ b/packages/nextjs/test/clientSdk.test.ts @@ -1,6 +1,5 @@ import { getGlobalScope, getIsolationScope } from '@sentry/core'; import * as SentryReact from '@sentry/react'; -import type { BrowserClient } from '@sentry/react'; import { WINDOW, getClient, getCurrentScope } from '@sentry/react'; import type { Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; @@ -114,67 +113,63 @@ describe('Client init()', () => { it('forces correct router instrumentation if user provides `browserTracingIntegration` in an array', () => { const providedBrowserTracingInstance = browserTracingIntegration(); - init({ + const client = init({ dsn: TEST_DSN, tracesSampleRate: 1.0, integrations: [providedBrowserTracingInstance], }); - const client = getClient()!; - - const integration = client.getIntegrationByName('BrowserTracing'); + const integration = client?.getIntegrationByName('BrowserTracing'); expect(integration).toBe(providedBrowserTracingInstance); }); it('forces correct router instrumentation if user provides `BrowserTracing` in a function', () => { const providedBrowserTracingInstance = browserTracingIntegration(); - init({ + const client = init({ dsn: TEST_DSN, tracesSampleRate: 1.0, integrations: defaults => [...defaults, providedBrowserTracingInstance], }); - const client = getClient()!; - - const integration = client.getIntegrationByName('BrowserTracing'); + const integration = client?.getIntegrationByName('BrowserTracing'); expect(integration).toBe(providedBrowserTracingInstance); }); describe('browserTracingIntegration()', () => { it('adds `browserTracingIntegration()` integration if `tracesSampleRate` is set', () => { - init({ + const client = init({ dsn: TEST_DSN, tracesSampleRate: 1.0, }); - const client = getClient()!; - const browserTracingIntegration = client.getIntegrationByName('BrowserTracing'); + const browserTracingIntegration = client?.getIntegrationByName('BrowserTracing'); expect(browserTracingIntegration?.name).toBe('BrowserTracing'); }); it('adds `browserTracingIntegration()` integration if `tracesSampler` is set', () => { - init({ + const client = init({ dsn: TEST_DSN, tracesSampler: () => true, }); - const client = getClient()!; - const browserTracingIntegration = client.getIntegrationByName('BrowserTracing'); + const browserTracingIntegration = client?.getIntegrationByName('BrowserTracing'); expect(browserTracingIntegration?.name).toBe('BrowserTracing'); }); it('does not add `browserTracingIntegration()` integration if tracing not enabled in SDK', () => { - init({ + const client = init({ dsn: TEST_DSN, }); - const client = getClient()!; - - const browserTracingIntegration = client.getIntegrationByName('BrowserTracing'); + const browserTracingIntegration = client?.getIntegrationByName('BrowserTracing'); expect(browserTracingIntegration).toBeUndefined(); }); }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); diff --git a/packages/nextjs/test/serverSdk.test.ts b/packages/nextjs/test/serverSdk.test.ts index fa17327b22f5..27230874d457 100644 --- a/packages/nextjs/test/serverSdk.test.ts +++ b/packages/nextjs/test/serverSdk.test.ts @@ -112,4 +112,8 @@ describe('Server init()', () => { expect(consoleIntegration).toBeDefined(); }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index 490826c3953b..746136c03022 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -98,14 +98,14 @@ function shouldAddPerformanceIntegrations(options: Options): boolean { /** * Initialize Sentry for Node. */ -export function init(options: NodeOptions | undefined = {}): void { +export function init(options: NodeOptions | undefined = {}): NodeClient | undefined { return _init(options, getDefaultIntegrations); } /** * Initialize Sentry for Node, without any integrations added by default. */ -export function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): void { +export function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient { return _init(options, () => []); } @@ -115,7 +115,7 @@ export function initWithoutDefaultIntegrations(options: NodeOptions | undefined function _init( options: NodeOptions | undefined = {}, getDefaultIntegrationsImpl: (options: Options) => Integration[], -): void { +): NodeClient { const clientOptions = getClientOptions(options, getDefaultIntegrationsImpl); if (clientOptions.debug === true) { @@ -178,6 +178,8 @@ function _init( enhanceDscWithOpenTelemetryRootSpanName(client); setupEventContextTrace(client); + + return client; } /** diff --git a/packages/node/test/sdk/init.test.ts b/packages/node/test/sdk/init.test.ts index 50a0fec7c2d6..235cb8d23b86 100644 --- a/packages/node/test/sdk/init.test.ts +++ b/packages/node/test/sdk/init.test.ts @@ -3,7 +3,7 @@ import type { Integration } from '@sentry/types'; import { getClient } from '../../src/'; import * as auto from '../../src/integrations/tracing'; import { init } from '../../src/sdk'; -import type { NodeClient } from '../../src/sdk/client'; +import { NodeClient } from '../../src/sdk/client'; import { cleanupOtel } from '../helpers/mockSdkInit'; // eslint-disable-next-line no-var @@ -136,4 +136,10 @@ describe('init()', () => { expect(client?.traceProvider).not.toBeDefined(); }); + + it('returns intiated client', () => { + const client = init({ dsn: PUBLIC_DSN, skipOpenTelemetrySetup: true }); + + expect(client).toBeInstanceOf(NodeClient); + }); }); diff --git a/packages/react/src/sdk.ts b/packages/react/src/sdk.ts index b2963b8c1f5e..952b1d3c3927 100644 --- a/packages/react/src/sdk.ts +++ b/packages/react/src/sdk.ts @@ -1,18 +1,19 @@ import type { BrowserOptions } from '@sentry/browser'; import { init as browserInit, setContext } from '@sentry/browser'; import { applySdkMetadata } from '@sentry/core'; +import type { Client } from '@sentry/types'; import { version } from 'react'; /** * Inits the React SDK */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { ...options, }; applySdkMetadata(opts, 'react'); setContext('react', { version }); - browserInit(opts); + return browserInit(opts); } diff --git a/packages/react/test/sdk.test.ts b/packages/react/test/sdk.test.ts index ce1b7f174f0d..50e9b485cd3e 100644 --- a/packages/react/test/sdk.test.ts +++ b/packages/react/test/sdk.test.ts @@ -11,4 +11,8 @@ describe('init', () => { expect(setContextSpy).toHaveBeenCalledTimes(1); expect(setContextSpy).toHaveBeenCalledWith('react', { version }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); diff --git a/packages/remix/src/index.client.tsx b/packages/remix/src/index.client.tsx index 2ff8e1a222a5..4f0c9ab662ad 100644 --- a/packages/remix/src/index.client.tsx +++ b/packages/remix/src/index.client.tsx @@ -1,5 +1,6 @@ import { applySdkMetadata, setTag } from '@sentry/core'; import { init as reactInit } from '@sentry/react'; +import type { Client } from '@sentry/types'; import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from './utils/debug-build'; import type { RemixOptions } from './utils/remixOptions'; @@ -28,7 +29,7 @@ export async function captureRemixServerException( export * from '@sentry/react'; -export function init(options: RemixOptions): void { +export function init(options: RemixOptions): Client | undefined { const opts = { ...options, environment: options.environment || process.env.NODE_ENV, @@ -36,7 +37,9 @@ export function init(options: RemixOptions): void { applySdkMetadata(opts, 'remix', ['remix', 'react']); - reactInit(opts); + const client = reactInit(opts); setTag('runtime', 'browser'); + + return client; } diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index bb2a0a125fd4..978a4a5c15d9 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -1,5 +1,5 @@ import { applySdkMetadata } from '@sentry/core'; -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { getDefaultIntegrations as getDefaultNodeIntegrations, init as nodeInit, @@ -179,7 +179,7 @@ export function wrapExpressCreateRequestHandler(createRequestHandlerFn: unknown) } /** Initializes Sentry Remix SDK on Node. */ -export function init(options: RemixOptions): void { +export function init(options: RemixOptions): NodeClient | undefined { applySdkMetadata(options, 'remix', ['remix', 'node']); if (isInitialized()) { @@ -190,9 +190,11 @@ export function init(options: RemixOptions): void { options.defaultIntegrations = getRemixDefaultIntegrations(options as NodeOptions); - nodeInit(options as NodeOptions); + const client = nodeInit(options as NodeOptions); instrumentServer(options); setTag('runtime', 'node'); + + return client; } diff --git a/packages/remix/test/index.client.test.ts b/packages/remix/test/index.client.test.ts index cfa0561ec43b..6b04a7ccd800 100644 --- a/packages/remix/test/index.client.test.ts +++ b/packages/remix/test/index.client.test.ts @@ -40,6 +40,10 @@ describe('Client init()', () => { ); }); + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); + it('sets runtime on scope', () => { expect(SentryReact.getIsolationScope().getScopeData().tags).toEqual({}); diff --git a/packages/remix/test/index.server.test.ts b/packages/remix/test/index.server.test.ts index 20953ad32507..6ee76317a366 100644 --- a/packages/remix/test/index.server.test.ts +++ b/packages/remix/test/index.server.test.ts @@ -55,4 +55,8 @@ describe('Server init()', () => { expect(SentryNode.getIsolationScope().getScopeData().tags).toEqual({ runtime: 'node' }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); diff --git a/packages/solid/src/sdk.ts b/packages/solid/src/sdk.ts index 83a14a30bc2a..2a08964b1b67 100644 --- a/packages/solid/src/sdk.ts +++ b/packages/solid/src/sdk.ts @@ -1,16 +1,17 @@ import type { BrowserOptions } from '@sentry/browser'; import { init as browserInit } from '@sentry/browser'; import { applySdkMetadata } from '@sentry/core'; +import type { Client } from '@sentry/types'; /** * Initializes the Solid SDK */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { ...options, }; applySdkMetadata(opts, 'solid'); - browserInit(opts); + return browserInit(opts); } diff --git a/packages/solid/test/sdk.test.ts b/packages/solid/test/sdk.test.ts index 1fa704f5cc2c..2b5547091ff7 100644 --- a/packages/solid/test/sdk.test.ts +++ b/packages/solid/test/sdk.test.ts @@ -12,7 +12,7 @@ describe('Initialize Solid SDk', () => { }); it('has the correct metadata', () => { - solidInit({ + const client = solidInit({ dsn: 'https://public@dsn.ingest.sentry.io/1337', }); @@ -26,6 +26,7 @@ describe('Initialize Solid SDk', () => { }, }; + expect(client).not.toBeUndefined(); expect(browserInit).toHaveBeenCalledTimes(1); expect(browserInit).toHaveBeenLastCalledWith(expect.objectContaining(expectedMetadata)); }); diff --git a/packages/svelte/src/sdk.ts b/packages/svelte/src/sdk.ts index 30d35d7963f4..721051fc2418 100644 --- a/packages/svelte/src/sdk.ts +++ b/packages/svelte/src/sdk.ts @@ -1,21 +1,23 @@ import type { BrowserOptions } from '@sentry/browser'; import { addEventProcessor, init as browserInit } from '@sentry/browser'; import { applySdkMetadata } from '@sentry/core'; -import type { EventProcessor } from '@sentry/types'; +import type { Client, EventProcessor } from '@sentry/types'; import { getDomElement } from '@sentry/utils'; /** * Inits the Svelte SDK */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { ...options, }; applySdkMetadata(opts, 'svelte'); - browserInit(opts); + const client = browserInit(opts); detectAndReportSvelteKit(); + + return client; } /** diff --git a/packages/svelte/test/sdk.test.ts b/packages/svelte/test/sdk.test.ts index 9ccf5d7a4638..1b38e7652398 100644 --- a/packages/svelte/test/sdk.test.ts +++ b/packages/svelte/test/sdk.test.ts @@ -70,6 +70,14 @@ describe('Initialize Svelte SDk', () => { }), ); }); + + it('returns client from init', () => { + const client = svelteInit({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + }); + + expect(client).not.toBeUndefined(); + }); }); describe('detectAndReportSvelteKit()', () => { diff --git a/packages/sveltekit/src/client/sdk.ts b/packages/sveltekit/src/client/sdk.ts index 86b869af65d3..65c7ffb8deab 100644 --- a/packages/sveltekit/src/client/sdk.ts +++ b/packages/sveltekit/src/client/sdk.ts @@ -2,7 +2,7 @@ import { applySdkMetadata, hasTracingEnabled, setTag } from '@sentry/core'; import type { BrowserOptions } from '@sentry/svelte'; import { getDefaultIntegrations as getDefaultSvelteIntegrations } from '@sentry/svelte'; import { WINDOW, init as initSvelteSdk } from '@sentry/svelte'; -import type { Integration } from '@sentry/types'; +import type { Client, Integration } from '@sentry/types'; import { browserTracingIntegration as svelteKitBrowserTracingIntegration } from './browserTracingIntegration'; @@ -18,7 +18,7 @@ declare const __SENTRY_TRACING__: boolean; * * @param options Configuration options for the SDK. */ -export function init(options: BrowserOptions): void { +export function init(options: BrowserOptions): Client | undefined { const opts = { defaultIntegrations: getDefaultIntegrations(options), ...options, @@ -30,7 +30,7 @@ export function init(options: BrowserOptions): void { const actualFetch = switchToFetchProxy(); // 2. Initialize the SDK which will instrument our proxy - initSvelteSdk(opts); + const client = initSvelteSdk(opts); // 3. Restore the original fetch now that our proxy is instrumented if (actualFetch) { @@ -38,6 +38,8 @@ export function init(options: BrowserOptions): void { } setTag('runtime', 'browser'); + + return client; } function getDefaultIntegrations(options: BrowserOptions): Integration[] | undefined { diff --git a/packages/sveltekit/src/server/sdk.ts b/packages/sveltekit/src/server/sdk.ts index f16220775d3a..889a60c14e57 100644 --- a/packages/sveltekit/src/server/sdk.ts +++ b/packages/sveltekit/src/server/sdk.ts @@ -1,5 +1,5 @@ import { applySdkMetadata, setTag } from '@sentry/core'; -import type { NodeOptions } from '@sentry/node'; +import type { NodeClient, NodeOptions } from '@sentry/node'; import { getDefaultIntegrations as getDefaultNodeIntegrations } from '@sentry/node'; import { init as initNodeSdk } from '@sentry/node'; @@ -9,7 +9,7 @@ import { rewriteFramesIntegration } from './rewriteFramesIntegration'; * * @param options */ -export function init(options: NodeOptions): void { +export function init(options: NodeOptions): NodeClient | undefined { const opts = { defaultIntegrations: [...getDefaultNodeIntegrations(options), rewriteFramesIntegration()], ...options, @@ -17,7 +17,9 @@ export function init(options: NodeOptions): void { applySdkMetadata(opts, 'sveltekit', ['sveltekit', 'node']); - initNodeSdk(opts); + const client = initNodeSdk(opts); setTag('runtime', 'node'); + + return client; } diff --git a/packages/sveltekit/test/client/sdk.test.ts b/packages/sveltekit/test/client/sdk.test.ts index 162ccd72852d..340a3852d04b 100644 --- a/packages/sveltekit/test/client/sdk.test.ts +++ b/packages/sveltekit/test/client/sdk.test.ts @@ -93,5 +93,9 @@ describe('Sentry client SDK', () => { delete globalThis.__SENTRY_TRACING__; }); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); }); diff --git a/packages/sveltekit/test/server/sdk.test.ts b/packages/sveltekit/test/server/sdk.test.ts index 90168e3d2b54..131e4185a3c7 100644 --- a/packages/sveltekit/test/server/sdk.test.ts +++ b/packages/sveltekit/test/server/sdk.test.ts @@ -56,5 +56,9 @@ describe('Sentry server SDK', () => { const rewriteFramesIntegration = getClient()?.getIntegrationByName('RewriteFrames'); expect(rewriteFramesIntegration).toBeDefined(); }); + + it('returns client from init', () => { + expect(init({})).not.toBeUndefined(); + }); }); }); diff --git a/packages/vercel-edge/src/sdk.ts b/packages/vercel-edge/src/sdk.ts index 9dd6a685a239..537990ecda13 100644 --- a/packages/vercel-edge/src/sdk.ts +++ b/packages/vercel-edge/src/sdk.ts @@ -6,7 +6,7 @@ import { linkedErrorsIntegration, requestDataIntegration, } from '@sentry/core'; -import type { Integration, Options } from '@sentry/types'; +import type { Client, Integration, Options } from '@sentry/types'; import { GLOBAL_OBJ, createStackParser, nodeStackLineParser, stackParserFromStackParserOptions } from '@sentry/utils'; import { setAsyncLocalStorageAsyncContextStrategy } from './async'; @@ -34,7 +34,7 @@ export function getDefaultIntegrations(options: Options): Integration[] { } /** Inits the Sentry NextJS SDK on the Edge Runtime. */ -export function init(options: VercelEdgeOptions = {}): void { +export function init(options: VercelEdgeOptions = {}): Client | undefined { setAsyncLocalStorageAsyncContextStrategy(); if (options.defaultIntegrations === undefined) { @@ -76,7 +76,7 @@ export function init(options: VercelEdgeOptions = {}): void { transport: options.transport || makeEdgeTransport, }; - initAndBind(VercelEdgeClient, clientOptions); + return initAndBind(VercelEdgeClient, clientOptions); } /** diff --git a/packages/vercel-edge/test/sdk.test.ts b/packages/vercel-edge/test/sdk.test.ts new file mode 100644 index 000000000000..f693e2777d99 --- /dev/null +++ b/packages/vercel-edge/test/sdk.test.ts @@ -0,0 +1,11 @@ +import * as SentryCore from '@sentry/core'; +import { init } from '../src/sdk'; + +describe('init', () => { + it('initializes and returns client', () => { + const initSpy = jest.spyOn(SentryCore, 'initAndBind'); + + expect(init({})).not.toBeUndefined(); + expect(initSpy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/vue/src/sdk.ts b/packages/vue/src/sdk.ts index bc307955fa17..54025ea052ee 100644 --- a/packages/vue/src/sdk.ts +++ b/packages/vue/src/sdk.ts @@ -1,5 +1,6 @@ import { SDK_VERSION, getDefaultIntegrations, init as browserInit } from '@sentry/browser'; +import type { Client } from '@sentry/types'; import { vueIntegration } from './integration'; import type { Options, TracingOptions } from './types'; @@ -8,7 +9,7 @@ import type { Options, TracingOptions } from './types'; */ export function init( config: Partial & { tracingOptions: Partial }> = {}, -): void { +): Client | undefined { const options = { _metadata: { sdk: { @@ -26,5 +27,5 @@ export function init( ...config, }; - browserInit(options); + return browserInit(options); } diff --git a/packages/vue/test/integration/init.test.ts b/packages/vue/test/integration/init.test.ts index c0652ad37485..c611900ed3b0 100644 --- a/packages/vue/test/integration/init.test.ts +++ b/packages/vue/test/integration/init.test.ts @@ -1,5 +1,6 @@ import { createApp } from 'vue'; +import type { Client } from '@sentry/types'; import type { Options } from '../../src/types'; import * as Sentry from './../../src'; @@ -100,12 +101,16 @@ Update your \`Sentry.init\` call with an appropriate config option: expect(warnings).toEqual([]); }); + + it('returns client from init', () => { + expect(runInit({})).not.toBeUndefined(); + }); }); -function runInit(options: Partial): void { +function runInit(options: Partial): Client | undefined { const integration = Sentry.vueIntegration(); - Sentry.init({ + return Sentry.init({ dsn: PUBLIC_DSN, defaultIntegrations: false, integrations: [integration],