From f6ab8dd7430b88964f28052bbde7b5d0bba7d736 Mon Sep 17 00:00:00 2001 From: Yoann Moinet Date: Tue, 25 Mar 2025 09:09:01 +0100 Subject: [PATCH 1/2] Change how we initialize plugins --- .github/CODEOWNERS | 9 ---- global.d.ts | 8 +-- packages/core/src/types.ts | 2 +- packages/factory/src/index.test.ts | 23 --------- packages/factory/src/index.ts | 30 ++++------- .../plugins/error-tracking/src/index.test.ts | 18 ++++++- packages/plugins/error-tracking/src/index.ts | 20 ++++---- .../plugins/error-tracking/src/validate.ts | 11 ++-- packages/plugins/rum/src/index.test.ts | 19 +++++++ packages/plugins/rum/src/index.ts | 23 ++++----- packages/plugins/rum/src/types.ts | 8 +-- packages/plugins/rum/src/validate.ts | 21 +++----- .../plugins/telemetry/src/common/helpers.ts | 12 ++--- packages/plugins/telemetry/src/index.test.ts | 15 ++++++ packages/plugins/telemetry/src/index.ts | 21 +++----- packages/tests/src/_jest/helpers/mocks.ts | 16 +++--- .../src/commands/create-plugin/index.test.ts | 5 -- .../tools/src/commands/create-plugin/index.ts | 3 -- .../src/commands/create-plugin/templates.ts | 51 +++++++++++++------ .../tools/src/commands/integrity/files.ts | 14 +---- packages/tools/src/helpers.ts | 2 +- 21 files changed, 152 insertions(+), 179 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c7a9eabcf..bdae1550f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,36 +5,27 @@ # Build Report packages/plugins/build-report @yoannmoinet -packages/tests/src/plugins/build-report @yoannmoinet # Bundler Report packages/plugins/bundler-report @yoannmoinet -packages/tests/src/plugins/bundler-report @yoannmoinet # Git packages/plugins/git @yoannmoinet -packages/tests/src/plugins/git @yoannmoinet # Injection packages/plugins/injection @yoannmoinet -packages/tests/src/plugins/injection @yoannmoinet # Telemetry packages/plugins/telemetry @DataDog/frontend-devx @yoannmoinet -packages/tests/src/plugins/telemetry @DataDog/frontend-devx @yoannmoinet # Error Tracking packages/plugins/error-tracking @yoannmoinet -packages/tests/src/plugins/error-tracking @yoannmoinet # Rum packages/plugins/rum @yoannmoinet -packages/tests/src/plugins/rum @yoannmoinet # Analytics packages/plugins/analytics @yoannmoinet -packages/tests/src/plugins/analytics @yoannmoinet # Custom Hooks packages/plugins/custom-hooks @yoannmoinet -packages/tests/src/plugins/custom-hooks @yoannmoinet diff --git a/global.d.ts b/global.d.ts index b90015b98..1be630767 100644 --- a/global.d.ts +++ b/global.d.ts @@ -41,14 +41,14 @@ declare global { * To skip the cleanup of the temporary working dirs where we build `runBundlers()`. */ NO_CLEANUP?: '1'; - /** - * The list of bundlers to use in our tests. - */ - REQUESTED_BUNDLERS?: string; /** * Defined by yarn and targets the root of the project. */ PROJECT_CWD?: string; + /** + * The list of bundlers to use in our tests. + */ + REQUESTED_BUNDLERS?: string; } } // Extend Jest's expect with custom matchers defined diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 22d80eb7b..1cd1d9d80 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -176,7 +176,7 @@ export type CustomPluginOptions = Assign< } >; -export type GetPlugins = (options: T, context: GlobalContext) => PluginOptions[]; +export type GetPlugins = (options: Options, context: GlobalContext) => PluginOptions[]; export type GetCustomPlugins = (options: Options, context: GlobalContext) => CustomPluginOptions[]; export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none'; diff --git a/packages/factory/src/index.test.ts b/packages/factory/src/index.test.ts index e69b7294e..2ca19cce1 100644 --- a/packages/factory/src/index.test.ts +++ b/packages/factory/src/index.test.ts @@ -2,19 +2,6 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import { getPlugins } from '@dd/telemetry-plugin'; -import { BUNDLERS, runBundlers } from '@dd/tests/_jest/helpers/runBundlers'; - -jest.mock('@dd/telemetry-plugin', () => { - const originalModule = jest.requireActual('@dd/telemetry-plugin'); - return { - ...originalModule, - getPlugins: jest.fn(() => []), - }; -}); - -const getPluginsMocked = jest.mocked(getPlugins); - describe('Factory', () => { test('Should not throw with no options', async () => { const { buildPluginFactory } = await import('@dd/factory'); @@ -25,14 +12,4 @@ describe('Factory', () => { factory.vite(); }).not.toThrow(); }); - - test('Should not call a disabled plugin', async () => { - await runBundlers({ telemetry: { disabled: true } }); - expect(getPluginsMocked).not.toHaveBeenCalled(); - }); - - test('Should call an enabled plugin', async () => { - await runBundlers({ telemetry: { disabled: false } }); - expect(getPluginsMocked).toHaveBeenCalledTimes(BUNDLERS.length); - }); }); diff --git a/packages/factory/src/index.ts b/packages/factory/src/index.ts index db597403a..9c203c823 100644 --- a/packages/factory/src/index.ts +++ b/packages/factory/src/index.ts @@ -26,11 +26,8 @@ import chalk from 'chalk'; import { getContext, validateOptions } from './helpers'; // #imports-injection-marker -import type { OptionsWithErrorTracking } from '@dd/error-tracking-plugin/types'; import * as errorTracking from '@dd/error-tracking-plugin'; -import type { OptionsWithRum } from '@dd/rum-plugin/types'; import * as rum from '@dd/rum-plugin'; -import type { OptionsWithTelemetry } from '@dd/telemetry-plugin/types'; import * as telemetry from '@dd/telemetry-plugin'; import { getAnalyticsPlugins } from '@dd/internal-analytics-plugin'; import { getBuildReportPlugins } from '@dd/internal-build-report-plugin'; @@ -100,23 +97,18 @@ export const buildPluginFactory = ({ context.plugins.push(...customPlugins); } - // Based on configuration add corresponding plugin. - // #configs-injection-marker - if ( - options[errorTracking.CONFIG_KEY] && - options[errorTracking.CONFIG_KEY].disabled !== true - ) { - context.plugins.push( - ...errorTracking.getPlugins(options as OptionsWithErrorTracking, context), - ); - } - if (options[rum.CONFIG_KEY] && options[rum.CONFIG_KEY].disabled !== true) { - context.plugins.push(...rum.getPlugins(options as OptionsWithRum, context)); - } - if (options[telemetry.CONFIG_KEY] && options[telemetry.CONFIG_KEY].disabled !== true) { - context.plugins.push(...telemetry.getPlugins(options as OptionsWithTelemetry, context)); + // Add the customer facing plugins. + const productPlugins = [ + // #configs-injection-marker + errorTracking, + rum, + telemetry, + // #configs-injection-marker + ]; + + for (const plugin of productPlugins) { + context.plugins.push(...plugin.getPlugins(options, context)); } - // #configs-injection-marker // List all our plugins in the context. context.pluginNames.push(...context.plugins.map((plugin) => plugin.name)); diff --git a/packages/plugins/error-tracking/src/index.test.ts b/packages/plugins/error-tracking/src/index.test.ts index c619133f2..4bd3565ed 100644 --- a/packages/plugins/error-tracking/src/index.test.ts +++ b/packages/plugins/error-tracking/src/index.test.ts @@ -3,7 +3,8 @@ // Copyright 2019-Present Datadog, Inc. import { uploadSourcemaps } from '@dd/error-tracking-plugin/sourcemaps/index'; -import { getSourcemapsConfiguration } from '@dd/tests/_jest/helpers/mocks'; +import { getPlugins } from '@dd/error-tracking-plugin'; +import { getContextMock, getSourcemapsConfiguration } from '@dd/tests/_jest/helpers/mocks'; import { BUNDLERS, runBundlers } from '@dd/tests/_jest/helpers/runBundlers'; jest.mock('@dd/error-tracking-plugin/sourcemaps/index', () => { @@ -15,6 +16,21 @@ jest.mock('@dd/error-tracking-plugin/sourcemaps/index', () => { const uploadSourcemapsMock = jest.mocked(uploadSourcemaps); describe('Error Tracking Plugin', () => { + describe('getPlugins', () => { + test('Should not initialize the plugin if disabled', async () => { + expect( + getPlugins({ errorTracking: { disabled: true } }, getContextMock()), + ).toHaveLength(0); + expect(getPlugins({}, getContextMock())).toHaveLength(0); + }); + + test('Should initialize the plugin if enabled', async () => { + expect( + getPlugins({ errorTracking: { disabled: false } }, getContextMock()).length, + ).toBeGreaterThan(0); + }); + }); + test('Should process the sourcemaps if enabled.', async () => { await runBundlers({ disableGit: true, diff --git a/packages/plugins/error-tracking/src/index.ts b/packages/plugins/error-tracking/src/index.ts index db69ecdf2..05a2c94d6 100644 --- a/packages/plugins/error-tracking/src/index.ts +++ b/packages/plugins/error-tracking/src/index.ts @@ -2,15 +2,11 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { GlobalContext, GetPlugins } from '@dd/core/types'; +import type { GlobalContext, GetPlugins, Options } from '@dd/core/types'; import { PLUGIN_NAME } from './constants'; import { uploadSourcemaps } from './sourcemaps'; -import type { - OptionsWithErrorTracking, - ErrorTrackingOptions, - ErrorTrackingOptionsWithSourcemaps, -} from './types'; +import type { ErrorTrackingOptions, ErrorTrackingOptionsWithSourcemaps } from './types'; import { validateOptions } from './validate'; export { CONFIG_KEY, PLUGIN_NAME } from './constants'; @@ -18,18 +14,20 @@ export { CONFIG_KEY, PLUGIN_NAME } from './constants'; export type types = { // Add the types you'd like to expose here. ErrorTrackingOptions: ErrorTrackingOptions; - OptionsWithErrorTracking: OptionsWithErrorTracking; }; -export const getPlugins: GetPlugins = ( - opts: OptionsWithErrorTracking, - context: GlobalContext, -) => { +export const getPlugins: GetPlugins = (opts: Options, context: GlobalContext) => { const log = context.getLogger(PLUGIN_NAME); // Verify configuration. const timeOptions = log.time('validate options'); const options = validateOptions(opts, log); timeOptions.end(); + + // If the plugin is disabled, return an empty array. + if (options.disabled) { + return []; + } + return [ { name: PLUGIN_NAME, diff --git a/packages/plugins/error-tracking/src/validate.ts b/packages/plugins/error-tracking/src/validate.ts index ef359c97c..2176dbb41 100644 --- a/packages/plugins/error-tracking/src/validate.ts +++ b/packages/plugins/error-tracking/src/validate.ts @@ -2,12 +2,11 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { Logger } from '@dd/core/types'; +import type { Logger, Options } from '@dd/core/types'; import chalk from 'chalk'; import { CONFIG_KEY, PLUGIN_NAME } from './constants'; import type { - OptionsWithErrorTracking, ErrorTrackingOptions, ErrorTrackingOptionsWithDefaults, SourcemapsOptionsWithDefaults, @@ -16,10 +15,7 @@ import type { export const defaultIntakeUrl = `https://sourcemap-intake.${process.env.DATADOG_SITE || 'datadoghq.com'}/api/v2/srcmap`; // Deal with validation and defaults here. -export const validateOptions = ( - config: Partial, - log: Logger, -): ErrorTrackingOptionsWithDefaults => { +export const validateOptions = (config: Options, log: Logger): ErrorTrackingOptionsWithDefaults => { const errors: string[] = []; // Validate and add defaults sub-options. @@ -34,6 +30,7 @@ export const validateOptions = ( // Build the final configuration. const toReturn: ErrorTrackingOptionsWithDefaults = { + disabled: !config[CONFIG_KEY], ...config[CONFIG_KEY], sourcemaps: undefined, }; @@ -68,7 +65,7 @@ const validateMinifiedPathPrefix = (minifiedPathPrefix: string): boolean => { }; export const validateSourcemapsOptions = ( - config: Partial, + config: Options, ): ToReturn => { const red = chalk.bold.red; const validatedOptions: ErrorTrackingOptions = config[CONFIG_KEY] || {}; diff --git a/packages/plugins/rum/src/index.test.ts b/packages/plugins/rum/src/index.test.ts index 2402d7d09..b4d47c6e4 100644 --- a/packages/plugins/rum/src/index.test.ts +++ b/packages/plugins/rum/src/index.test.ts @@ -35,6 +35,25 @@ describe('RUM Plugin', () => { should: { inject: ['browser-sdk', 'sdk-init'] }, }, ]; + describe('getPlugins', () => { + const injectMock = jest.fn(); + test('Should not initialize the plugin if disabled', async () => { + getPlugins( + { rum: { disabled: true, sdk: { applicationId: 'app-id', clientToken: '123' } } }, + getContextMock({ inject: injectMock }), + ); + getPlugins({}, getContextMock({ inject: injectMock })); + expect(injectMock).not.toHaveBeenCalled(); + }); + + test('Should initialize the plugin if enabled', async () => { + getPlugins( + { rum: { disabled: false, sdk: { applicationId: 'app-id', clientToken: '123' } } }, + getContextMock({ inject: injectMock }), + ); + expect(injectMock).toHaveBeenCalled(); + }); + }); test.each(expectations)( 'Should inject the necessary files with "$type".', diff --git a/packages/plugins/rum/src/index.ts b/packages/plugins/rum/src/index.ts index 93d28ffe8..9a354ecd1 100644 --- a/packages/plugins/rum/src/index.ts +++ b/packages/plugins/rum/src/index.ts @@ -2,19 +2,13 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { PluginOptions, GetPlugins, GlobalContext } from '@dd/core/types'; +import type { PluginOptions, GetPlugins, GlobalContext, Options } from '@dd/core/types'; import { InjectPosition } from '@dd/core/types'; import path from 'path'; import { CONFIG_KEY, PLUGIN_NAME } from './constants'; import { getInjectionValue } from './sdk'; -import type { - OptionsWithRum, - RumOptions, - RumOptionsWithSdk, - RumPublicApi, - RumInitConfiguration, -} from './types'; +import type { RumOptions, RumOptionsWithSdk, RumPublicApi, RumInitConfiguration } from './types'; import { validateOptions } from './validate'; export { CONFIG_KEY, PLUGIN_NAME }; @@ -26,19 +20,20 @@ export const helpers = { export type types = { // Add the types you'd like to expose here. RumOptions: RumOptions; - OptionsWithRum: OptionsWithRum; RumPublicApi: RumPublicApi; RumInitConfiguration: RumInitConfiguration; }; -export const getPlugins: GetPlugins = ( - opts: OptionsWithRum, - context: GlobalContext, -) => { +export const getPlugins: GetPlugins = (opts: Options, context: GlobalContext) => { const log = context.getLogger(PLUGIN_NAME); - const plugins: PluginOptions[] = []; // Verify configuration. const options = validateOptions(opts, log); + const plugins: PluginOptions[] = []; + + // If the plugin is disabled, return an empty array. + if (options.disabled) { + return plugins; + } // NOTE: These files are built from "@dd/tools/rollupConfig.mjs" and available in the distributed package. if (options.sdk) { diff --git a/packages/plugins/rum/src/types.ts b/packages/plugins/rum/src/types.ts index b0fe11bda..047689193 100644 --- a/packages/plugins/rum/src/types.ts +++ b/packages/plugins/rum/src/types.ts @@ -6,9 +6,7 @@ import type { datadogRum, RumInitConfiguration as ExpRumInitConfiguration, } from '@datadog/browser-rum'; -import type { Assign, GetPluginsOptions } from '@dd/core/types'; - -import type { CONFIG_KEY } from './constants'; +import type { Assign } from '@dd/core/types'; export type RumOptions = { disabled?: boolean; @@ -58,7 +56,3 @@ export type RumOptionsWithDefaults = { }; export type RumOptionsWithSdk = Assign; - -export interface OptionsWithRum extends GetPluginsOptions { - [CONFIG_KEY]: RumOptions; -} diff --git a/packages/plugins/rum/src/validate.ts b/packages/plugins/rum/src/validate.ts index 53983c2c9..d9b8826a0 100644 --- a/packages/plugins/rum/src/validate.ts +++ b/packages/plugins/rum/src/validate.ts @@ -2,21 +2,13 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { Logger } from '@dd/core/types'; +import type { Logger, Options } from '@dd/core/types'; import chalk from 'chalk'; import { CONFIG_KEY, PLUGIN_NAME } from './constants'; -import type { - OptionsWithRum, - RumOptions, - RumOptionsWithDefaults, - SDKOptionsWithDefaults, -} from './types'; - -export const validateOptions = ( - options: Partial, - log: Logger, -): RumOptionsWithDefaults => { +import type { RumOptions, RumOptionsWithDefaults, SDKOptionsWithDefaults } from './types'; + +export const validateOptions = (options: Options, log: Logger): RumOptionsWithDefaults => { const errors: string[] = []; // Validate and add defaults sub-options. @@ -32,6 +24,7 @@ export const validateOptions = ( // Build the final configuration. const toReturn: RumOptionsWithDefaults = { + disabled: !options[CONFIG_KEY], ...options[CONFIG_KEY], sdk: undefined, }; @@ -49,9 +42,7 @@ type ToReturn = { config?: T; }; -export const validateSDKOptions = ( - options: Partial, -): ToReturn => { +export const validateSDKOptions = (options: Options): ToReturn => { const red = chalk.bold.red; const validatedOptions: RumOptions = options[CONFIG_KEY] || {}; const toReturn: ToReturn = { diff --git a/packages/plugins/telemetry/src/common/helpers.ts b/packages/plugins/telemetry/src/common/helpers.ts index 7b58ac876..a6d9a9ac1 100644 --- a/packages/plugins/telemetry/src/common/helpers.ts +++ b/packages/plugins/telemetry/src/common/helpers.ts @@ -2,13 +2,12 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. +import type { Options } from '@dd/core/types'; import { CONFIG_KEY } from '@dd/telemetry-plugin/constants'; import type { OptionsDD, Metric, MetricToSend, - TelemetryOptions, - OptionsWithTelemetry, Module, Compilation, ValueContext, @@ -17,17 +16,16 @@ import type { import { defaultFilters } from './filters'; -export const validateOptions = (opts: OptionsWithTelemetry): TelemetryOptionsWithDefaults => { - const options: TelemetryOptions = opts[CONFIG_KEY] || {}; - const endPoint = options.endPoint || 'https://app.datadoghq.com'; +export const validateOptions = (opts: Options): TelemetryOptionsWithDefaults => { + const endPoint = opts[CONFIG_KEY]?.endPoint || 'https://app.datadoghq.com'; return { - disabled: false, + disabled: !opts[CONFIG_KEY], enableTracing: false, filters: defaultFilters, output: false, prefix: '', tags: [], - ...options, + ...opts[CONFIG_KEY], endPoint: endPoint.startsWith('http') ? endPoint : `https://${endPoint}`, }; }; diff --git a/packages/plugins/telemetry/src/index.test.ts b/packages/plugins/telemetry/src/index.test.ts index 5294cfed5..3337bf2bd 100644 --- a/packages/plugins/telemetry/src/index.test.ts +++ b/packages/plugins/telemetry/src/index.test.ts @@ -6,10 +6,12 @@ import { debugFilesPlugins } from '@dd/core/helpers/plugins'; import type { GlobalContext, Options } from '@dd/core/types'; import { addMetrics } from '@dd/telemetry-plugin/common/aggregator'; import type { MetricToSend } from '@dd/telemetry-plugin/types'; +import { getPlugins } from '@dd/telemetry-plugin'; import { FAKE_URL, filterOutParticularities, getComplexBuildOverrides, + getContextMock, } from '@dd/tests/_jest/helpers/mocks'; import { BUNDLERS, runBundlers } from '@dd/tests/_jest/helpers/runBundlers'; import type { Bundler } from '@dd/tests/_jest/helpers/types'; @@ -68,6 +70,19 @@ describe('Telemetry Universal Plugin', () => { nock.cleanAll(); }); + describe('getPlugins', () => { + test('Should not initialize the plugin if disabled', async () => { + expect(getPlugins({ telemetry: { disabled: true } }, getContextMock())).toHaveLength(0); + expect(getPlugins({}, getContextMock())).toHaveLength(0); + }); + + test('Should initialize the plugin if enabled', async () => { + expect( + getPlugins({ telemetry: { disabled: false } }, getContextMock()).length, + ).toBeGreaterThan(0); + }); + }); + describe('With enableTracing', () => { const metrics: Record = {}; // enableTracing is only supported by esbuild and webpack. diff --git a/packages/plugins/telemetry/src/index.ts b/packages/plugins/telemetry/src/index.ts index 9070e4521..6e23b87fd 100644 --- a/packages/plugins/telemetry/src/index.ts +++ b/packages/plugins/telemetry/src/index.ts @@ -2,7 +2,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { GlobalContext, GetPlugins, PluginOptions } from '@dd/core/types'; +import type { GlobalContext, GetPlugins, PluginOptions, Options } from '@dd/core/types'; import { addMetrics } from './common/aggregator'; import { defaultFilters } from './common/filters'; @@ -12,14 +12,7 @@ import { outputTexts } from './common/output/text'; import { sendMetrics } from './common/sender'; import { PLUGIN_NAME, CONFIG_KEY } from './constants'; import { getEsbuildPlugin } from './esbuild-plugin'; -import type { - BundlerContext, - Filter, - Metric, - MetricToSend, - OptionsWithTelemetry, - TelemetryOptions, -} from './types'; +import type { BundlerContext, Filter, Metric, MetricToSend, TelemetryOptions } from './types'; import { getWebpackPlugin } from './webpack-plugin'; export { CONFIG_KEY, PLUGIN_NAME }; @@ -34,10 +27,7 @@ export type types = { TelemetryOptions: TelemetryOptions; }; -export const getPlugins: GetPlugins = ( - options: OptionsWithTelemetry, - context: GlobalContext, -) => { +export const getPlugins: GetPlugins = (options: Options, context: GlobalContext) => { const log = context.getLogger(PLUGIN_NAME); let realBuildEnd: number = 0; const bundlerContext: BundlerContext = { @@ -47,6 +37,11 @@ export const getPlugins: GetPlugins = ( const telemetryOptions = validateOptions(options); const plugins: PluginOptions[] = []; + // If the plugin is disabled, return an empty array. + if (telemetryOptions.disabled) { + return plugins; + } + // Webpack and Esbuild specific plugins. // LEGACY const legacyPlugin: PluginOptions = { diff --git a/packages/tests/src/_jest/helpers/mocks.ts b/packages/tests/src/_jest/helpers/mocks.ts index 11def4837..df655b77b 100644 --- a/packages/tests/src/_jest/helpers/mocks.ts +++ b/packages/tests/src/_jest/helpers/mocks.ts @@ -28,8 +28,6 @@ import type { Report, Compilation, OptionsDD, - OptionsWithTelemetry, - OutputOptions, TelemetryOptions, Module, } from '@dd/telemetry-plugin/types'; @@ -60,7 +58,11 @@ export const defaultPluginOptions: GetPluginsOptions = { export const mockLogFn = jest.fn((text: any, level: LogLevel) => {}); const logFn: Logger = { getLogger: jest.fn(), - time: jest.fn(), + time: () => ({ + end: jest.fn(), + resume: jest.fn(), + pause: jest.fn(), + }), error: (text: any) => { mockLogFn(text, 'error'); }, @@ -140,7 +142,7 @@ export const getContextMock = (overrides: Partial = {}): GlobalCo build: getMockBuildReport(), cwd: '/cwd/path', env: 'test', - getLogger: jest.fn(), + getLogger: jest.fn(() => mockLogger), asyncHook: jest.fn(), hook: jest.fn(), inject: jest.fn(), @@ -383,18 +385,12 @@ export const mockReport: Report = { }, }; -export const mockOutputOptions: OutputOptions = true; export const mockOptionsDD: OptionsDD = { tags: [], prefix: '', timestamp: 1, filters: [], }; -export const mockTelemetryOptions: TelemetryOptions = {}; -export const mockOptionsWithTelemetry: OptionsWithTelemetry = { - ...defaultPluginOptions, - telemetry: mockTelemetryOptions, -}; export const getTelemetryConfiguration = ( overrides: Partial = {}, diff --git a/packages/tools/src/commands/create-plugin/index.test.ts b/packages/tools/src/commands/create-plugin/index.test.ts index 28d95554a..06090a9e8 100644 --- a/packages/tools/src/commands/create-plugin/index.test.ts +++ b/packages/tools/src/commands/create-plugin/index.test.ts @@ -104,13 +104,8 @@ describe('Command create-plugin', () => { const fileRx = new RegExp( `packages\\/plugins\\/${slug}${codeowners.map((c) => `\\s+${c}`).join('')}`, ); - // Matches the tests lines in CODEOWNERS. - const testRx = new RegExp( - `packages\\/tests\\/src\\/plugins\\/${slug}${codeowners.map((c) => `\\s+${c}`).join('')}`, - ); expect(files['.github/CODEOWNERS']).toMatch(fileRx); - expect(files['.github/CODEOWNERS']).toMatch(testRx); }); }); }); diff --git a/packages/tools/src/commands/create-plugin/index.ts b/packages/tools/src/commands/create-plugin/index.ts index b8f26f711..293b74ae2 100644 --- a/packages/tools/src/commands/create-plugin/index.ts +++ b/packages/tools/src/commands/create-plugin/index.ts @@ -72,14 +72,11 @@ class CreatePlugin extends Command { const codeowners = fs.readFileSync(codeownersPath, 'utf-8'); const pluginPathToAdd = `packages/plugins/${context.plugin.slug}`; const paddingPlugin = ' '.repeat(70 - pluginPathToAdd.length); - const testPathToAdd = `packages/tests/src/plugins/${context.plugin.slug}`; - const paddingTest = ' '.repeat(70 - testPathToAdd.length); const newCodeowners = outdent` ${codeowners.trim()} # ${getTitle(context.plugin.slug)} ${pluginPathToAdd}${paddingPlugin}${context.codeowners} - ${testPathToAdd}${paddingTest}${context.codeowners} `; fs.writeFileSync(codeownersPath, newCodeowners); } diff --git a/packages/tools/src/commands/create-plugin/templates.ts b/packages/tools/src/commands/create-plugin/templates.ts index 30952e19c..4d3c3df7a 100644 --- a/packages/tools/src/commands/create-plugin/templates.ts +++ b/packages/tools/src/commands/create-plugin/templates.ts @@ -27,10 +27,10 @@ export const getFiles = (context: Context): File[] => { content: (ctx) => { const hooksContent = ctx.hooks.map((hook) => getHookTemplate(hook)).join('\n'); return outdent` - import type { GlobalContext, GetPlugins } from '@dd/core/types'; + import type { GlobalContext, GetPlugins, Options } from '@dd/core/types'; import { CONFIG_KEY, PLUGIN_NAME } from './constants'; - import type { OptionsWith${pascalCase}, ${pascalCase}Options, ${pascalCase}OptionsWithDefaults } from './types'; + import type { ${pascalCase}Options, ${pascalCase}OptionsWithDefaults } from './types'; export { CONFIG_KEY, PLUGIN_NAME }; @@ -41,26 +41,31 @@ export const getFiles = (context: Context): File[] => { export type types = { // Add the types you'd like to expose here. ${pascalCase}Options: ${pascalCase}Options; - OptionsWith${pascalCase}: OptionsWith${pascalCase}; }; // Deal with validation and defaults here. - export const validateOptions = (config: Partial): ${pascalCase}OptionsWithDefaults => { + export const validateOptions = (config: Options): ${pascalCase}OptionsWithDefaults => { const validatedOptions: ${pascalCase}OptionsWithDefaults = { - disabled: false, + disabled: !config[CONFIG_KEY], ...config[CONFIG_KEY] }; return validatedOptions; }; - export const getPlugins: GetPlugins = ( - opts: OptionsWith${pascalCase}, + export const getPlugins: GetPlugins = ( + opts: Options, context: GlobalContext, ) => { - const log = context.getLogger(PLUGIN_NAME); // Verify configuration. const options = validateOptions(opts); + // If the plugin is disabled, return an empty array. + if (options.disabled) { + return []; + } + + const log = context.getLogger(PLUGIN_NAME); + return [ { name: PLUGIN_NAME, @@ -75,19 +80,33 @@ export const getFiles = (context: Context): File[] => { name: `${plugin.location}/src/types.ts`, content: () => { return outdent` - import type { GetPluginsOptions } from '@dd/core/types'; - - import type { CONFIG_KEY } from './constants'; - export type ${pascalCase}Options = { disabled?: boolean; }; export type ${pascalCase}OptionsWithDefaults = Required<${pascalCase}Options>; - - export interface OptionsWith${pascalCase} extends GetPluginsOptions { - [CONFIG_KEY]: ${pascalCase}Options; - } + `; + }, + }, + { + name: `${plugin.location}/src/index.test.ts`, + content: () => { + return outdent` + import { getPlugins } from '@dd/${plugin.slug}-plugin'; + import { getContextMock } from '@dd/tests/_jest/helpers/mocks'; + + describe('${title} Plugin', () => { + describe('getPlugins', () => { + test('Should not initialize the plugin if disabled', async () => { + expect(getPlugins({ ${camelCase}: { disabled: true } }, getContextMock())).toHaveLength(0); + expect(getPlugins({}, getContextMock())).toHaveLength(0); + }); + + test('Should initialize the plugin if enabled', async () => { + expect(getPlugins({ ${camelCase}: { disabled: false } }, getContextMock()).length).toBeGreaterThan(0); + }); + }); + }); `; }, }, diff --git a/packages/tools/src/commands/integrity/files.ts b/packages/tools/src/commands/integrity/files.ts index 391f63477..85bf9b631 100644 --- a/packages/tools/src/commands/integrity/files.ts +++ b/packages/tools/src/commands/integrity/files.ts @@ -152,15 +152,10 @@ const updateFactory = async (plugins: Workspace[]) => { `; } else { importPluginsContent += outdent` - import type { OptionsWith${pascalCase} } from '${plugin.name}/types'; import * as ${camelCase} from '${plugin.name}'; `; typesExportContent += `export type { types as ${pascalCase}Types } from '${plugin.name}';`; - configContent += outdent` - if (options[${configKeyVar}] && options[${configKeyVar}].disabled !== true) { - context.plugins.push(...${camelCase}.getPlugins(options as OptionsWith${pascalCase}, context)); - } - `; + configContent += `${camelCase},`; // Only add helpers if they export them. if (pluginExports.helpers && Object.keys(pluginExports.helpers).length) { @@ -240,15 +235,8 @@ const verifyCodeowners = (plugins: Workspace[]) => { for (const plugin of plugins) { const title = green(plugin.slug); console.log(` Verifying ${title} is in ${green(codeownersPath)}.`); - const testsPath = `packages/tests/src/plugins/${plugin.slug}`; const pluginPath = `${plugin.location}`; - if (!codeowners.includes(testsPath)) { - errors.push( - `[${error}] Missing ${title}'s tests (${dim(testsPath)}) in ${green(codeownersPath)}.`, - ); - } - if (!codeowners.includes(pluginPath)) { errors.push( `[${error}] Missing ${title} (${dim(pluginPath)}) in ${green(codeownersPath)}.`, diff --git a/packages/tools/src/helpers.ts b/packages/tools/src/helpers.ts index 84bfce2dc..7cd2bfe8e 100644 --- a/packages/tools/src/helpers.ts +++ b/packages/tools/src/helpers.ts @@ -176,7 +176,7 @@ export const getWorkspaces = async ( }; // TODO: Update this, it's a bit hacky. -export const getSupportedBundlers = (getPlugins: GetPlugins) => { +export const getSupportedBundlers = (getPlugins: GetPlugins) => { const context = getContext({ // We don't care, this is a hack. options: {} as OptionsWithDefaults, From cab3bbc89233876ba750103e9e4ab037ed2a7ee4 Mon Sep 17 00:00:00 2001 From: Yoann Moinet Date: Thu, 27 Mar 2025 11:53:48 +0100 Subject: [PATCH 2/2] Remove unused types --- packages/plugins/error-tracking/src/types.ts | 8 -------- packages/plugins/telemetry/src/types.ts | 8 +------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/packages/plugins/error-tracking/src/types.ts b/packages/plugins/error-tracking/src/types.ts index 064e967d7..8d67b3bbd 100644 --- a/packages/plugins/error-tracking/src/types.ts +++ b/packages/plugins/error-tracking/src/types.ts @@ -2,10 +2,6 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { GetPluginsOptions } from '@dd/core/types'; - -import type { CONFIG_KEY } from './constants'; - export type MinifiedPathPrefix = `http://${string}` | `https://${string}` | `/${string}`; export type SourcemapsOptions = { @@ -36,10 +32,6 @@ export type ErrorTrackingOptionsWithSourcemaps = { sourcemaps: SourcemapsOptionsWithDefaults; }; -export interface OptionsWithErrorTracking extends GetPluginsOptions { - [CONFIG_KEY]: ErrorTrackingOptions; -} - export type Sourcemap = { minifiedFilePath: string; minifiedPathPrefix: MinifiedPathPrefix; diff --git a/packages/plugins/telemetry/src/types.ts b/packages/plugins/telemetry/src/types.ts index d9e4f8188..411cf8641 100644 --- a/packages/plugins/telemetry/src/types.ts +++ b/packages/plugins/telemetry/src/types.ts @@ -2,9 +2,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. -import type { Assign, GetPluginsOptions } from '@dd/core/types'; - -import type { CONFIG_KEY } from './constants'; +import type { Assign } from '@dd/core/types'; export interface MetricToSend { type: 'gauge'; @@ -57,10 +55,6 @@ export type TelemetryOptionsWithDefaults = Assign< } >; -export interface OptionsWithTelemetry extends GetPluginsOptions { - [CONFIG_KEY]: TelemetryOptions; -} - export interface TimingsReport { tapables?: TimingsMap; loaders?: TimingsMap;