Skip to content

✨ Introduce @datadog/js-core, a runtime-agnostic core package with independent versioning#4727

Merged
thomas-lebeau merged 11 commits into
mainfrom
thomas.lebeau/add-js-core-package
Jun 5, 2026
Merged

✨ Introduce @datadog/js-core, a runtime-agnostic core package with independent versioning#4727
thomas-lebeau merged 11 commits into
mainfrom
thomas.lebeau/add-js-core-package

Conversation

@thomas-lebeau
Copy link
Copy Markdown
Collaborator

@thomas-lebeau thomas-lebeau commented Jun 4, 2026

Motivation

External packages such as electron-sdk and openfeature-js-client currently import APIs from @datadog/browser-core, which was never designed as a stable public surface — breaking changes can ship in patch releases, making downstream integrations brittle.

This PR introduces @datadog/js-core, a small, semver-stable, runtime-agnostic core package intended for cross-SDK and external usage, as proposed in the RFC. It is the MVP first step: create the package, move a first utility into it, and wire up the release process.

Changes

New package @datadog/js-core

  • Sub-path exports via both the exports field (modern resolvers, native Node ESM/CJS) and physical <name>/ directory fallbacks (legacy resolvers — webpack 4, old Node). The build emits esm/package.json with {"type":"module"} so Node correctly treats esm/*.js as ES modules.
  • No root entry point — always import from a sub-path (e.g. @datadog/js-core/time).
  • Versioned independently from @datadog/browser-* (starts at 0.0.1).
  • README.md + AGENTS.md documenting the no-breaking-changes, JSDoc, and sub-path rules.
  • Moves dateNow out of @datadog/browser-core into @datadog/js-core/time and updates all call sites in browser-core and browser-debugger to import directly from the new package.
  • Adds @datadog/js-core/time to the disallowSideEffects ESLint allowlist and a tsconfig path alias.
  • Adds --esm-type-module flag to the shared build-package.ts script, used by js-core to emit esm/package.json post-build.

Release process

  • @datadog/js-core is published in the same release pipeline as the browser packages, but keeps its own version.
  • prepare-release bumps independently-versioned packages with a patch increment (e.g. 0.0.10.0.2) instead of the synced release version, and updates dependents (browser-core, browser-debugger) to reference the new version.
  • check-release validates that dependents reference the independent package's actual version.

Test instructions

  • yarn build — js-core builds, integrates into the full build, and emits esm/package.json.
  • yarn typecheck, yarn lint — pass.
  • yarn test:script — 47 pass / 0 fail (validates the release/deploy scripts).
  • Release behavior was verified by simulating prepare-release + check-release against all package.json files: browser packages bump to the release version, js-core patches 0.0.10.0.2, and browser-core's @datadog/js-core dependency is updated and validated to match.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@cit-pr-commenter-54b7da
Copy link
Copy Markdown

cit-pr-commenter-54b7da Bot commented Jun 4, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 171.79 KiB 171.86 KiB +68 B +0.04%
Rum Profiler 7.88 KiB 7.88 KiB 0 B 0.00%
Rum Recorder 21.21 KiB 21.21 KiB 0 B 0.00%
Logs 54.31 KiB 54.31 KiB 0 B 0.00%
Rum Slim 129.70 KiB 129.69 KiB -6 B -0.00%
Worker 22.96 KiB 22.96 KiB 0 B 0.00%

@datadog-datadog-prod-us1
Copy link
Copy Markdown

datadog-datadog-prod-us1 Bot commented Jun 4, 2026

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 76.69% (-0.01%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: fec9f92 | Docs | Datadog PR Page | Give us feedback!

@thomas-lebeau thomas-lebeau force-pushed the thomas.lebeau/add-js-core-package branch from 56e08e9 to 817034d Compare June 4, 2026 13:28
@thomas-lebeau
Copy link
Copy Markdown
Collaborator Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 430e745be0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/js-core/package.json
Comment thread packages/browser-core/src/tools/utils/timeUtils.ts
@thomas-lebeau thomas-lebeau marked this pull request as ready for review June 5, 2026 05:23
@thomas-lebeau thomas-lebeau requested review from a team as code owners June 5, 2026 05:23
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eff36374e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/js-core/time/package.json
Comment on lines +33 to +39
### Runtime-agnostic exports only

Every export must work in both Node.js and browser environments. Do not add:

- DOM APIs (`document`, `window`, `navigator`, `performance.timing`, etc.)
- Node.js built-in modules (`fs`, `path`, `process`, etc.)
- Any API that is not available in both runtimes
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: we'll probably have some runtime-related code, like some kind of pageMayExitObservable versions for Browser and Nodejs. Or transport level things.

We'll need to figure whether we want a browser conditional export so we have isomorphic packages, or we export both variants and the consumer uses one or the other.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, we probably want to have some integration testing too. but I'd rather think about that in a separate PR.

Comment on lines +13 to +23
## API

The package uses sub-path exports. Import only what you need.

### `@datadog/js-core/time`

Time utilities that work in any JavaScript runtime.

| Export | Description |
| ----------- | --------------------------------------------------------------------------------------------------------------- |
| `dateNow()` | Returns the current Unix timestamp in milliseconds. Prefer over `Date.now()` to guard against broken polyfills. |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: for the future: we should have a API reference doc that is automatically generated. I don't want to maintain the README :D

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, for now I want to keep it simple. Claude can update the readme.

Comment thread scripts/lib/filesUtils.ts Outdated
Introduce @datadog/js-core, a stable, runtime-agnostic core package
intended for cross-SDK and external usage (electron-sdk,
openfeature-js-client). It exposes sub-path exports only (e.g.
@datadog/js-core/time) and is versioned independently from the
@datadog/browser-* packages.

As a first step, move dateNow from @datadog/browser-core into
@datadog/js-core/time and update all call sites in browser-core and
browser-debugger to import it from the new package.
@datadog/js-core ships in the same release process as the
@datadog/browser-* packages but keeps its own version.

- prepare-release bumps independently-versioned packages with a minor
  increment (e.g. 0.0.1 -> 0.1.0) instead of the synced release version,
  and updates dependents (browser-core, browser-debugger) to reference
  the new version.
- check-release validates that dependents reference the independent
  package's actual version rather than the synced release version.
The check-packages CI job requires every published package to include a
LICENSE file. Add the Apache-2.0 license, matching the other packages.
build:apps installs the SDK packages into each test app as packed .tgz
files via resolutions. Now that @datadog/browser-core depends on
@datadog/js-core (which is not published), each app that resolves
browser-core must also resolve js-core to its local package.tgz,
otherwise yarn tries the registry and fails with a 404.
Ship the `time` sub-path two ways so it resolves in both modern and
legacy tooling:
- the `exports` field for resolvers that support it (encapsulation +
  import/require/types conditions)
- a physical `time/package.json` (relative main/module/types) for
  resolvers that ignore `exports` (webpack 4, old Node, older Jest)

js-core is published transitively to all Browser SDK consumers, so the
fallback avoids breaking customers on older bundlers. `exports` takes
precedence wherever it is understood.
- Remove the `"exports"` field from `@datadog/js-core/package.json` — legacy
  resolvers (webpack 4, old Node, older Jest) that predate the `exports` spec
  would break, and getting native-Node ESM right requires extra packaging the
  build doesn't emit yet; defer to a future major release
- Add `jsCoreCompat.ts` to `@datadog/browser-core` with backward-compat
  re-exports for symbols that moved to `@datadog/js-core`, so existing consumers
  importing from `@datadog/browser-core` keep working until the next major
- Update `@datadog/js-core` AGENTS.md and README to document the physical
  sub-path strategy and the deliberate omission of `exports`
- Re-add exports field with ESM/CJS/types conditions for ./time entry point
- Add --esm-type-module flag to build-package script to write {"type":"module"} into esm/ dir for proper ESM resolution
…ategy

- AGENTS.md: document that sub-paths are now exposed via both the
  `exports` field (for modern resolvers) and physical `<name>/package.json`
  fallbacks (for legacy resolvers); update "adding a new sub-path" steps
- README.md: add a note about the dual resolution strategy and the
  TypeScript moduleResolution requirement for exports-aware sub-paths
Not used outside of filesUtils.ts, no need to export it.
@thomas-lebeau thomas-lebeau force-pushed the thomas.lebeau/add-js-core-package branch from 0b98ea7 to efa367f Compare June 5, 2026 10:02
Drop jsCoreCompat.ts and its re-export from browser-core/index.ts now
that consumers can import directly from @datadog/js-core.
js-core and similar packages now get a patch increment on each Browser
SDK release instead of a minor one, keeping their version progression
more conservative.
@thomas-lebeau thomas-lebeau merged commit c059e5f into main Jun 5, 2026
30 checks passed
@thomas-lebeau thomas-lebeau deleted the thomas.lebeau/add-js-core-package branch June 5, 2026 12:37
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants