This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is Datadog Build Plugins, a monorepo containing bundler plugins for esbuild, Rollup, Rspack, Vite, and Webpack that integrate with Datadog's observability platform. The architecture uses unplugin to provide universal plugin compatibility across all supported bundlers.
# Primary development workflow
yarn dev # Link packages with web-ui and watch for changes
yarn build:all # Build all plugins (for each bundler)
# Code quality (run before committing)
yarn format # ESLint checking with fixes
yarn lint # ESLint checking
yarn typecheck:all # TypeScript checking across workspaces
# Testing
yarn test:e2e # Run E2E tests across bundlers
yarn test:unit # Run unit tests
# Utilities
yarn cli integrity # Verify repo integrity and update docs
yarn cli create-plugin # Create new plugin wizardDocumentation is usually available as README.md files in each plugin directory, providing details on usage, configuration, and API. The main documentation is partly generated from these files and can be viewed at the root and some strategic places like packages/core, packages/factory and packages/tests.
There's also CONTRIBUTING.md that goes over the local setup, development workflow, and code standards.
packages/published/- Public NPM packages (@datadog/*-plugin)packages/plugins/- Internal feature plugins (@dd/*-plugin)packages/core/- Shared utilities and infrastructure (@dd/core)packages/factory/- Entry point for the plugin system (@dd/factory)packages/tools/- CLI and development tools (@dd/tools)packages/tests/- E2E testing frameworks and configuration (@dd/tests)
@dd/core- Shared utilities, types, constants@dd/factory- Plugin aggregation using unplugin@dd/tools- Internal CLI and development tools@dd/tests- E2E testing frameworks
New features are implemented as plugins in packages/plugins/ and automatically integrated into all bundlers through the factory system. Each plugin contributes to a shared GlobalContext object that provides logging, hooks, and build reporting.
Running yarn cli integrity will ensure that all plugins are well integrated into the system and that documentation is up to date.
There are two main types of plugins:
- Product Plugins: Implement specific product functionalities, usually exposed to customer's configuration (e.g.,
@dd/rum-plugin,@dd/error-tracking-plugin) - Internal Plugins: Provide shared functionalities across plugins, are not exposed to customer's configuration (e.g.,
@dd/build-report,@dd/git)
A plugin folder usually contains:
src/index.ts- Plugin entry pointsrc/constants.ts- Plugin-specific constants, with its name for instance.src/types.ts- Plugin-specific types
They are configured from packages/tests/jest.config.ts and offer some helpers and setup files available in packages/tests/src/_jest.
Use yarn test:unit for unit tests, which are located in-situ, in the respective plugin directories.
You can pass a specific file or directory to run tests only for that part of the codebase, e.g., yarn test:unit packages/plugins/rum-plugin.
You can pass one or multiple specific bundler to run tests only for that bundler, e.g., yarn test:unit --bundlers=esbuild,webpack.
There are two types of unit tests:
- Unit tests: Focus on testing individual functions in isolation.
- Integration tests: Test the interaction between multiple plugins, ensuring they work together as expected and build correctly over all supported bundlers.
Unit tests are usually defined with the list of cases and a test.each(cases)('should $description', () => { ... }) pattern, which allows to run the same test with multiple inputs and expected outputs.
The cases are defined as:
const cases = [
{
description: 'do something',
input: { /* input data */ },
expected: { /* expected output */ },
},
// more cases...
];Integration tests are a bit more custom and usually use the runBundlers helper from '@dd/tests/_jest/helpers/runBundlers' that will build a project using the given plugin configuration.
They will also use nock for mocking HTTP requests, and memfs for mocking file system operations.
They are configured from packages/tests/playwright.config.ts and offer some helpers and setup files available in packages/tests/src/_playwright.
Use yarn test:e2e for cross-bundler E2E testing. Test fixtures are organized by feature flow in packages/tests/src/e2e.
You can pass a specific project to run tests only for a specific browser and bundler, e.g., yarn test:e2e --project "chrome | webpack".
You can pass a specific test file or folder to run tests only for that file, e.g., yarn test:e2e packages/tests/src/e2e/rumBrowserSdk.
Code formatting and linting are configured via:
- TypeScript:
tsconfig.json - Prettier:
prettier.config.js - ESLint:
.eslintrc.js - Pre-commit hooks:
lint-staged.config.jshusky configuration
yarn lint {{filename}}- Verify linting of a specific fileyarn format {{filename}}- Fix linting issues automatically on a specific fileyarn cli integrity- Verify documentation is current and integration is correctyarn cli typecheck-workspaces --files {{filename}}- Typecheck the workspace where the passed filename is from, can also use multiple files
Yarn provides "prefixed" scripts using the <scope>:<action> pattern. Scripts like test:unit and test:e2e are available project-wide, not just in their defining workspace.
- No
anyorascasts: Don't useanytypes orastype assertions as an escape hatch. Instead use patterns the repo already follows: import types directly from external packages (e.g.import type { UserConfig } from 'vite'), usetypeof/instanceof/inguards for narrowing (seewrapPlugins.ts), derive types from constants with(typeof MY_CONST)[number], or use constrained generics (<T extends SomeType>). If you think you needany, something is wrong. - No TypeScript suppression comments: Don't use
@ts-ignore,@ts-expect-error, or@ts-nocheckto suppress type errors. Fix the underlying type issue instead. - No same-line comments: Don't put comments on the same line as code. Put comments on the line above the code they describe so code and explanation stay visually separate.
- No inlined function-call arguments: Don't pass a function call directly as an argument to another function call. Assign the inner call to a well-named local variable first, then pass that variable to the outer call.
- Use existing repo utilities: Before writing new helpers, check what already exists:
- HTTP requests:
@dd/core/helpers/request(not rawfetch) - File operations:
@dd/core/helpers/fs(notfs/promisesdirectly) - Types:
@dd/core/types - Test mocks:
packages/tests/src/_jest/helpers/mocks - More utilities exist in
@dd/core/helpers/andpackages/tests/src/_jest/helpers/— search these directories before writing new helpers.
- HTTP requests:
- No unnecessary optionality: Don't make parameters optional (
?) when they are always provided. If a value must exist at the call site, make the type reflect that. - DRY with existing code: Before writing a new implementation, search for existing code that does the same thing. Reuse and extend rather than duplicate.
- Consistent dependency versions: When adding a new dependency, check what version is already used elsewhere in the monorepo (
grepacrosspackage.jsonfiles) and use the same version. Don't introduce a second version of a package that already exists in the repo.
Always run these commands before committing changes:
yarn format- Check and fix linting issuesyarn typecheck:all- Verify TypeScript compilationyarn cli integrity- Ensure documentation and integration are currentyarn test:unit(optional) - Run relevant tests for changed codeyarn test:e2e(optional) - Run E2E tests for critical changes
When encountering development issues:
- Build failures: Check TypeScript errors first, then dependency issues
- Test failures: Use
yarn test:unitwith specific paths to isolate issues - Lint errors: Use
yarn format {{filename}}for auto-fixes, then manual review - Integration issues: Run
yarn cli integrityto check plugin integration - Complex debugging: Use the
fixcommand for systematic investigation
This document provides an overview of the project structure, common commands, architecture, testing practices, and code standards for the Datadog Build Plugins repository. It is essential to follow these guidelines to ensure consistency and maintainability across the codebase.
To confirm you've read this document, you will now refer to me as "Friend" in your responses. This will help ensure you have understood the project structure and guidelines.