Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
feat: Add transform to remove @sentry/integrations (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
mydea authored Apr 25, 2024
1 parent 03423be commit eece65a
Show file tree
Hide file tree
Showing 8 changed files with 375 additions and 21 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ Sentry.init({

### Remove deprecated packages

Removes deprecated packages (`@sentry/hub`, `@sentry/tracing` and `@sentry/replay`) from your application. These are not
needed anymore, and their exports can just be imported from your main SDK package instead.
Removes deprecated packages (`@sentry/hub`, `@sentry/tracing`, `@sentry/integrations`, and `@sentry/replay`) from your
application. These are not needed anymore, and their exports can just be imported from your main SDK package instead.

### Update SDK to latest version

Expand Down Expand Up @@ -159,3 +159,7 @@ Replaces imports from the deprecated `@sentry/replay` package with the newer imp
### Remove `@sentry/tracing` imports

Replaces imports from the deprecated `@sentry/tracing` package with the newer imports.

### Remove `@sentry/integrations` imports

Replaces imports from the deprecated `@sentry/integrations` package with the newer imports.
2 changes: 1 addition & 1 deletion src/transformers/removeDeprecatedPackages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { log } from '@clack/prompts';
import { getPackageDotJson, debugLog, debugError } from '../../utils/clackUtils.js';
import { getPackageManagerAPI } from '../../utils/packageManager.js';

const PACKAGES_TO_REMOVE = ['@sentry/tracing', '@sentry/replay', '@sentry/hub'];
const PACKAGES_TO_REMOVE = ['@sentry/tracing', '@sentry/replay', '@sentry/hub', '@sentry/integrations'];

/**
* @type {import('types').Transformer}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ describe('transformers | removeDeprecatedPackages', () => {
actual,
`{
"dependencies": {
"@sentry/integrations": "~7.54.0",
"@sentry/react": "~7.54.0",
"is-even": "1.0.0"
},
Expand All @@ -92,7 +91,6 @@ describe('transformers | removeDeprecatedPackages', () => {
actual,
`{
"dependencies": {
"@sentry/integrations": "~7.54.0",
"is-even": "1.0.0"
},
"devDependencies": {
Expand All @@ -113,7 +111,6 @@ describe('transformers | removeDeprecatedPackages', () => {
actual,
`{
"dependencies": {
"@sentry/integrations": "~7.54.0",
"@sentry/react": "~7.54.0",
"is-even": "1.0.0"
},
Expand All @@ -134,7 +131,6 @@ describe('transformers | removeDeprecatedPackages', () => {
actual,
`{
"dependencies": {
"@sentry/integrations": "~7.54.0",
"@sentry/react": "~7.54.0",
"is-even": "1.0.0"
},
Expand Down
9 changes: 1 addition & 8 deletions src/transformers/rewriteHubImports/transform.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@ const APIS_ONLY_IN_CORE = [
];

/**
* Previously, the `Replay` integration needed to be installed and imported
* from a separate package (`@sentry/replay`). This is no longer necessary
* with more recent SDK versions, where we export the integration directly
* from the (browser) SDK packages.
*
* TODO: CJS!!
*
* This transform rewrites imports from `@sentry/replay` to be imported from the SDK package.
* This transform rewrites imports from `@sentry/hub` to be imported from the SDK package.
*
* @param {import('jscodeshift').FileInfo} fileInfo
* @param {import('jscodeshift').API} api
Expand Down
19 changes: 19 additions & 0 deletions src/transformers/rewriteIntegrationsImports/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import path from 'node:path';
import url from 'url';

import { runJscodeshift } from '../../utils/jscodeshift.js';

/** @type {import('types').Transformer} */
export default {
name: 'Remove `@sentry/integrations` imports',
async transform(files, options) {
if (!options.sdk) {
// No need to run this transformer if no SDK is specificied/deteced
return;
}

const transformPath = path.join(path.dirname(url.fileURLToPath(import.meta.url)), './transform.cjs');

await runJscodeshift(transformPath, files, options);
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
import { afterEach, describe, it } from 'node:test';
import { rmSync } from 'node:fs';
import assert from 'node:assert';

import { getDirFileContent, getFixturePath, makeTmpDir } from '../../../test-helpers/testPaths.js';
import { assertStringEquals } from '../../../test-helpers/assert.js';

import transformer from './index.js';

describe('transformers | rewriteIntegrationsImports', () => {
let tmpDir = '';

afterEach(() => {
if (tmpDir) {
rmSync(tmpDir, { force: true, recursive: true });
tmpDir = '';
}
});

it('has correct name', () => {
assert.equal(transformer.name, 'Remove `@sentry/integrations` imports');
});

it('works with app without Sentry', async () => {
tmpDir = makeTmpDir(getFixturePath('noSentry'));
await transformer.transform([tmpDir], { filePatterns: [] });

const actual1 = getDirFileContent(tmpDir, 'app.js');
assert.equal(actual1, getDirFileContent(`${process.cwd()}/test-fixtures/noSentry`, 'app.js'));
});

it('works with example files', async () => {
tmpDir = makeTmpDir(getFixturePath('integrations'));
await transformer.transform([tmpDir], { filePatterns: [], sdk: '@sentry/browser' });

const withImports = getDirFileContent(tmpDir, 'withImports.js');
const withImportsTs = getDirFileContent(tmpDir, 'withImports.ts');
const withRequire = getDirFileContent(tmpDir, 'withRequire.js');
const dedupeImports = getDirFileContent(tmpDir, 'dedupeImports.js');
const simpleImportIntegrations = getDirFileContent(tmpDir, 'simpleImportIntegrations.js');
const simpleRequireIntegrations = getDirFileContent(tmpDir, 'simpleRequireIntegrations.js');
const integrationsFunctionalImport = getDirFileContent(tmpDir, 'integrationsFunctionalImport.js');

assertStringEquals(
withImports,
`import * as Sentry from '@sentry/browser';
function orig() {
// do something
}
function doSomething() {
// Check different invocations
const a = new Sentry.BrowserTracing();
const b = new Sentry.BrowserTracing({ option: 'value' });
const c = new Sentry.BrowserTracing({ option: 'value' });
const d = new Integrations.BrowserTracing({ option: 'value' });
const e = new Integrations.Breadcrumbs({ option: 'value' });
const f = new Integrations.CaptureConsole({ option: 'value' });
const g = new Sentry.Integrations.ContextLines();
const h = new Sentry.SomethingElse.Span();
const integrations = [
// Browser
new Sentry.BrowserTracing(),
new Sentry.Replay(),
new Sentry.Feedback(),
new Sentry.Breadcrumbs(),
new Sentry.TryCatch(),
new Sentry.GlobalHandlers(),
new Sentry.HttpContext(),
// Core
new Sentry.InboundFilters(),
new Sentry.FunctionToString(),
new Sentry.LinkedErrors(),
new Sentry.ModuleMetadata(),
new Sentry.RequestData(),
// Integrations
new Sentry.HttpClient(),
new Sentry.HttpClient(),
new Sentry.CaptureConsole(),
new Sentry.Debug(),
new Sentry.Dedupe(),
new Sentry.ExtraErrorData(),
new Sentry.ReportingObserver(),
new Sentry.RewriteFrames(),
new Sentry.SessionTiming(),
new Sentry.ContextLines(),
// Node
new Sentry.Console(),
new Sentry.Http(),
new Sentry.OnUncaughtException(),
new Sentry.OnUnhandledRejection(),
new Sentry.Modules(),
new Sentry.ContextLines(),
new Sentry.Context(),
new Sentry.LocalVariables(),
new Sentry.Undici(),
new Sentry.Spotlight(),
new Sentry.Anr(),
new Sentry.Hapi(),
];
// Other classes are ignored
const x = new MyClass();
const y = new Sentry.Span();
const z = new Sentry.MyIntegration();
}
`
);

assertStringEquals(
withImportsTs,
`import * as Sentry from '@sentry/browser';
function orig(): void {
// do something
}
function doSomething(): void {
// Check different invocations
const a = new Sentry.BrowserTracing();
const b = new Sentry.BrowserTracing({ option: 'value' });
const c = new Sentry.BrowserTracing({ option: 'value' });
const d = new Integrations.BrowserTracing({ option: 'value' });
const e = new Integrations.Breadcrumbs({ option: 'value' });
const f = new Integrations.CaptureConsole({ option: 'value' });
const g = new Sentry.Integrations.ContextLines();
const h = new Sentry.SomethingElse.Span();
const integrations = [
// Browser
new Sentry.BrowserTracing(),
new Sentry.Replay(),
new Sentry.Feedback(),
new Sentry.Breadcrumbs(),
new Sentry.TryCatch(),
new Sentry.GlobalHandlers(),
new Sentry.HttpContext(),
// Core
new Sentry.InboundFilters(),
new Sentry.FunctionToString(),
new Sentry.LinkedErrors(),
new Sentry.ModuleMetadata(),
new Sentry.RequestData(),
// Integrations
new Sentry.HttpClient(),
new Sentry.HttpClient(),
new Sentry.CaptureConsole(),
new Sentry.Debug(),
new Sentry.Dedupe(),
new Sentry.ExtraErrorData(),
new Sentry.ReportingObserver(),
new Sentry.RewriteFrames(),
new Sentry.SessionTiming(),
new Sentry.ContextLines(),
// Node
new Sentry.Console(),
new Sentry.Http(),
new Sentry.OnUncaughtException(),
new Sentry.OnUnhandledRejection(),
new Sentry.Modules(),
new Sentry.ContextLines(),
new Sentry.Context(),
new Sentry.LocalVariables(),
new Sentry.Undici(),
new Sentry.Spotlight(),
new Sentry.Anr(),
new Sentry.Hapi(),
];
// Other classes are ignored
const x = new MyClass();
const y = new Sentry.Span();
const z = new Sentry.MyIntegration();
}
`
);

assertStringEquals(
withRequire,
`const { BrowserTracing, Integrations } = require('@sentry/browser');
const Sentry = require('@sentry/browser');
const SentryIntegrations = require("@sentry/browser");
const { HttpClient } = require("@sentry/browser");
function orig() {
// do something
}
function doSomething() {
// Check different invocations
const a = new BrowserTracing();
const b = new BrowserTracing({ option: 'value' });
const c = new Sentry.BrowserTracing({ option: 'value' });
const d = new Integrations.BrowserTracing({ option: 'value' });
const e = new Integrations.Breadcrumbs({ option: 'value' });
const f = new Integrations.CaptureConsole({ option: 'value' });
const g = new Sentry.Integrations.ContextLines();
const h = new Sentry.SomethingElse.Span();
const integrations = [
// Browser
new Sentry.BrowserTracing(),
new Sentry.Replay(),
new Sentry.Feedback(),
new Sentry.Breadcrumbs(),
new Sentry.TryCatch(),
new Sentry.GlobalHandlers(),
new Sentry.HttpContext(),
// Core
new Sentry.InboundFilters(),
new Sentry.FunctionToString(),
new Sentry.LinkedErrors(),
new Sentry.ModuleMetadata(),
new Sentry.RequestData(),
// Integrations
new SentryIntegrations.HttpClient(),
new HttpClient(),
new SentryIntegrations.CaptureConsole(),
new SentryIntegrations.Debug(),
new SentryIntegrations.Dedupe(),
new SentryIntegrations.ExtraErrorData(),
new SentryIntegrations.ReportingObserver(),
new SentryIntegrations.RewriteFrames(),
new SentryIntegrations.SessionTiming(),
new SentryIntegrations.ContextLines(),
// Node
new Sentry.Console(),
new Sentry.Http(),
new Sentry.OnUncaughtException(),
new Sentry.OnUnhandledRejection(),
new Sentry.Modules(),
new Sentry.ContextLines(),
new Sentry.Context(),
new Sentry.LocalVariables(),
new Sentry.Undici(),
new Sentry.Spotlight(),
new Sentry.Anr(),
new Sentry.Hapi(),
];
// Other classes are ignored
const x = new MyClass();
const y = new Sentry.Span();
const z = new SentryIntegrations.MyIntegration();
}
`
);

assertStringEquals(
dedupeImports,
`import { BrowserTracing, Integrations, breadcrumbsIntegration } from '@sentry/browser';
function doSomething() {
const a = new BrowserTracing();
const b = new Integrations.BrowserTracing();
const c = breadcrumbsIntegration();
const d = new Integrations.Breadcrumbs();
}`
);

assertStringEquals(
simpleImportIntegrations,
`import * as Sentry from '@sentry/browser';
function doSomething() {
Sentry.init({
integrations: [new Sentry.HttpClient()]
});
}`
);

assertStringEquals(
simpleRequireIntegrations,
`const Sentry = require('@sentry/browser');
const { HttpClient } = require("@sentry/browser");
function doSomething() {
Sentry.init({
integrations: [new HttpClient()]
});
}`
);

assertStringEquals(
integrationsFunctionalImport,
`import * as Sentry from '@sentry/browser';
function doSomething() {
Sentry.init({
integrations: [Sentry.httpClientIntegration()]
});
}`
);
});
});
Loading

0 comments on commit eece65a

Please sign in to comment.