Skip to content

[internal] Change how we initialise plugins #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export type CustomPluginOptions = Assign<
}
>;

export type GetPlugins<T> = (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';
Expand Down
23 changes: 0 additions & 23 deletions packages/factory/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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);
});
});
30 changes: 11 additions & 19 deletions packages/factory/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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));
Expand Down
18 changes: 17 additions & 1 deletion packages/plugins/error-tracking/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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,
Expand Down
20 changes: 9 additions & 11 deletions packages/plugins/error-tracking/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,32 @@
// 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';

export type types = {
// Add the types you'd like to expose here.
ErrorTrackingOptions: ErrorTrackingOptions;
OptionsWithErrorTracking: OptionsWithErrorTracking;
};

export const getPlugins: GetPlugins<OptionsWithErrorTracking> = (
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,
Expand Down
8 changes: 0 additions & 8 deletions packages/plugins/error-tracking/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -36,10 +32,6 @@ export type ErrorTrackingOptionsWithSourcemaps = {
sourcemaps: SourcemapsOptionsWithDefaults;
};

export interface OptionsWithErrorTracking extends GetPluginsOptions {
[CONFIG_KEY]: ErrorTrackingOptions;
}

export type Sourcemap = {
minifiedFilePath: string;
minifiedPathPrefix: MinifiedPathPrefix;
Expand Down
11 changes: 4 additions & 7 deletions packages/plugins/error-tracking/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<OptionsWithErrorTracking>,
log: Logger,
): ErrorTrackingOptionsWithDefaults => {
export const validateOptions = (config: Options, log: Logger): ErrorTrackingOptionsWithDefaults => {
const errors: string[] = [];

// Validate and add defaults sub-options.
Expand All @@ -34,6 +30,7 @@ export const validateOptions = (

// Build the final configuration.
const toReturn: ErrorTrackingOptionsWithDefaults = {
disabled: !config[CONFIG_KEY],
...config[CONFIG_KEY],
sourcemaps: undefined,
};
Expand Down Expand Up @@ -68,7 +65,7 @@ const validateMinifiedPathPrefix = (minifiedPathPrefix: string): boolean => {
};

export const validateSourcemapsOptions = (
config: Partial<OptionsWithErrorTracking>,
config: Options,
): ToReturn<SourcemapsOptionsWithDefaults> => {
const red = chalk.bold.red;
const validatedOptions: ErrorTrackingOptions = config[CONFIG_KEY] || {};
Expand Down
19 changes: 19 additions & 0 deletions packages/plugins/rum/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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".',
Expand Down
23 changes: 9 additions & 14 deletions packages/plugins/rum/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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<OptionsWithRum> = (
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) {
Expand Down
8 changes: 1 addition & 7 deletions packages/plugins/rum/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,7 +56,3 @@ export type RumOptionsWithDefaults = {
};

export type RumOptionsWithSdk = Assign<RumOptionsWithDefaults, { sdk: SDKOptionsWithDefaults }>;

export interface OptionsWithRum extends GetPluginsOptions {
[CONFIG_KEY]: RumOptions;
}
Loading