From 5af4173aa2567dec88a035f1bbd7711e9a3ff18e Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 6 May 2024 16:27:04 +0200 Subject: [PATCH] feat(node): Warn if ESM mode is detected --- .../suites/esm/warn-esm/server.js | 21 ++++++++++++++++ .../suites/esm/warn-esm/server.mjs | 21 ++++++++++++++++ .../suites/esm/warn-esm/test.ts | 24 +++++++++++++++++++ .../node-integration-tests/utils/runner.ts | 18 ++++++++++---- packages/node/src/sdk/init.ts | 18 ++++++++++++-- 5 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/esm/warn-esm/server.js create mode 100644 dev-packages/node-integration-tests/suites/esm/warn-esm/server.mjs create mode 100644 dev-packages/node-integration-tests/suites/esm/warn-esm/test.ts diff --git a/dev-packages/node-integration-tests/suites/esm/warn-esm/server.js b/dev-packages/node-integration-tests/suites/esm/warn-esm/server.js new file mode 100644 index 000000000000..6f1773fa1129 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/esm/warn-esm/server.js @@ -0,0 +1,21 @@ +const { loggingTransport } = require('@sentry-internal/node-integration-tests'); +const Sentry = require('@sentry/node'); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + transport: loggingTransport, +}); + +const { startExpressServerAndSendPortToRunner } = require('@sentry-internal/node-integration-tests'); +const express = require('express'); + +const app = express(); + +app.get('/test/success', (req, res) => { + res.send({ response: 'response 3' }); +}); + +Sentry.setupExpressErrorHandler(app); + +startExpressServerAndSendPortToRunner(app); diff --git a/dev-packages/node-integration-tests/suites/esm/warn-esm/server.mjs b/dev-packages/node-integration-tests/suites/esm/warn-esm/server.mjs new file mode 100644 index 000000000000..fa486c9ddac8 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/esm/warn-esm/server.mjs @@ -0,0 +1,21 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + transport: loggingTransport, +}); + +import { startExpressServerAndSendPortToRunner } from '@sentry-internal/node-integration-tests'; +import express from 'express'; + +const app = express(); + +app.get('/test/success', (req, res) => { + res.send({ response: 'response 3' }); +}); + +Sentry.setupExpressErrorHandler(app); + +startExpressServerAndSendPortToRunner(app); diff --git a/dev-packages/node-integration-tests/suites/esm/warn-esm/test.ts b/dev-packages/node-integration-tests/suites/esm/warn-esm/test.ts new file mode 100644 index 000000000000..fa369a12db28 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/esm/warn-esm/test.ts @@ -0,0 +1,24 @@ +import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; + +afterAll(() => { + cleanupChildProcesses(); +}); + +const esmWarning = + '[Sentry] You are using the Sentry SDK with an ESM build. This version of the SDK is not compatible with ESM. Please either build your application with CommonJS, or use v7 of the SDK.'; + +test('warns if using ESM', async () => { + const runner = createRunner(__dirname, 'server.mjs').ignore('session', 'sessions', 'event').start(); + + await runner.makeRequest('get', '/test/success'); + + expect(runner.getLogs()).toContain(esmWarning); +}); + +test('does not warn if using CJS', async () => { + const runner = createRunner(__dirname, 'server.js').ignore('session', 'sessions', 'event').start(); + + await runner.makeRequest('get', '/test/success'); + + expect(runner.getLogs()).not.toContain(esmWarning); +}); diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index 98d2e6283687..bcbbf90417d1 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -159,6 +159,7 @@ export function createRunner(...paths: string[]) { let dockerOptions: DockerOptions | undefined; let ensureNoErrorOutput = false; let expectError = false; + const logs: string[] = []; if (testPath.endsWith('.ts')) { flags.push('-r', 'ts-node/register'); @@ -335,12 +336,14 @@ export function createRunner(...paths: string[]) { child?.kill(); }); - if (ensureNoErrorOutput) { - child.stderr?.on('data', (data: Buffer) => { - const output = data.toString(); + child.stderr?.on('data', (data: Buffer) => { + const output = data.toString(); + logs.push(output.trim()); + + if (ensureNoErrorOutput) { complete(new Error(`Expected no error output but got: '${output}'`)); - }); - } + } + }); child.on('close', () => { hasExited = true; @@ -389,6 +392,8 @@ export function createRunner(...paths: string[]) { let splitIndex = -1; while ((splitIndex = buffer.indexOf(0xa)) >= 0) { const line = buffer.subarray(0, splitIndex).toString(); + logs.push(line.trim()); + buffer = Buffer.from(buffer.subarray(splitIndex + 1)); // eslint-disable-next-line no-console if (process.env.DEBUG) console.log('line', line); @@ -402,6 +407,9 @@ export function createRunner(...paths: string[]) { childHasExited: function (): boolean { return hasExited; }, + getLogs(): string[] { + return logs; + }, makeRequest: async function ( method: 'get' | 'post', path: string, diff --git a/packages/node/src/sdk/init.ts b/packages/node/src/sdk/init.ts index e57fbd9cb4e0..07bb72208f59 100644 --- a/packages/node/src/sdk/init.ts +++ b/packages/node/src/sdk/init.ts @@ -39,8 +39,12 @@ import { defaultStackParser, getSentryRelease } from './api'; import { NodeClient } from './client'; import { initOpenTelemetry } from './initOtel'; -function getCjsOnlyIntegrations(isCjs = typeof require !== 'undefined'): Integration[] { - return isCjs ? [modulesIntegration()] : []; +function isCjs(): boolean { + return typeof require !== 'undefined'; +} + +function getCjsOnlyIntegrations(): Integration[] { + return isCjs() ? [modulesIntegration()] : []; } /** Get the default integrations for the Node Experimental SDK. */ @@ -85,6 +89,16 @@ export function init(options: NodeOptions | undefined = {}): void { } } + if (!isCjs()) { + // We want to make sure users see this warning + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[Sentry] You are using the Sentry SDK with an ESM build. This version of the SDK is not compatible with ESM. Please either build your application with CommonJS, or use v7 of the SDK.', + ); + }); + } + setOpenTelemetryContextAsyncContextStrategy(); const scope = getCurrentScope();