Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
08ed6a3
Replace `ts-bridge` with `tsc` for building packages
Mrtenz Jul 16, 2026
7cd7c6c
Update package exports to ESM-only
Mrtenz Jul 16, 2026
8f050b1
Add `"type": "module"` to all packages
Mrtenz Jul 16, 2026
81b9439
Update yarn.lock
Mrtenz Aug 19, 2026
633a31c
Replace `__dirname` with `import.meta.dirname` in all packages
Mrtenz Jul 16, 2026
048cfac
Fix ts-bridge call in CI
Mrtenz Aug 20, 2026
1605b12
Fix remaining build errors
Mrtenz Aug 20, 2026
259a99f
Work around TypeScript ESM named-import issue in messenger-cli
Mrtenz Jul 16, 2026
5494786
Run Jest as CommonJS against the ESM sources
Mrtenz Aug 24, 2026
56b85b6
Move remaining CommonJS config files off the `.js` extension
Mrtenz Aug 24, 2026
85b4499
Run the `scripts` tests as ESM
Mrtenz Aug 24, 2026
8055bd7
Replace `lodash` with `lodash-es`
Mrtenz Aug 25, 2026
34360e9
Resolve `ethereumjs-wallet` through its CommonJS namespace
Mrtenz Aug 25, 2026
3bc6bfc
Remove the build info files in `build:only-clean`
Mrtenz Aug 25, 2026
de86923
Bump `@metamask/safe-event-emitter` to `^3.1.3`
Mrtenz Aug 26, 2026
a9db251
Replace `klona` with `lodash-es`'s `cloneDeep` in `smart-transactions…
Mrtenz Aug 27, 2026
4408bce
Add `build:clean` script to all packages
Mrtenz Aug 27, 2026
3a208b5
Add changelog entry
Mrtenz Sep 2, 2026
1b7d171
Add missing changelog entries
Mrtenz Sep 2, 2026
7aa17ea
Apply missing changes to package template
Mrtenz Sep 3, 2026
e583b9d
Remove unused `rimraf` dependency
Mrtenz Sep 3, 2026
309a1cc
Fix api-specs import
Mrtenz Sep 3, 2026
0d13c55
Add note to TS error
Mrtenz Sep 3, 2026
ab9e854
Fix one more import
Mrtenz Sep 9, 2026
4eda3c0
Fix eth-json-rpc-provider coverage
Mrtenz Sep 9, 2026
c1780db
Add some more ts-expect-errors
Mrtenz Sep 9, 2026
d0ebb9f
Fix one more instance of lodash to lodash-es
Mrtenz Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/lint-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ jobs:
echo "Building changed packages:"
jq -r '"- " + (.references[].path | ltrimstr("./") | rtrimstr("/tsconfig.build.json"))' "$TSCONFIG"
echo ""
yarn ts-bridge --project "$TSCONFIG" --verbose
yarn tsc --build --project "$TSCONFIG" --verbose
Comment thread
cursor[bot] marked this conversation as resolved.
else
echo "No packages to build."
fi
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ npmPreapprovedPackages:
- "@metamask/*"
- "@metamask-previews/*"
- "@lavamoat/*"
- "@ts-bridge/*"

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs
Expand Down
2 changes: 0 additions & 2 deletions docs/processes/building.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Building packages

[`ts-bridge`](https://github.com/ts-bridge/ts-bridge) is used to build packages in both CommonJS- and ESM-compatible formats.

Built files show up in the `dist/` directory in each package. These are the files which will ultimately be published to NPM.

- Run `yarn build` to build all packages in the monorepo.
Expand Down
4 changes: 2 additions & 2 deletions docs/processes/package-migration-process-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ Find the release commit SHA with `git log --oneline merged-packages/<package-nam
### **[PR#8]** 3. Remove files and directories that will be replaced by files in the monorepo root directory

- **Remove**: `.github/`, `.git*`, `scripts/`, `knip.config.ts`, `.yarn/`, `.yarnrc.yml`, `yarn.lock`, `.editorconfig`, `.eslint*`, `.prettier*`, `.nvm*`.
- **Keep**: `src/`, `tests/`, `CHANGELOG.md`, `LICENSE`, `package.json`, `README.md`, `jest.config.js`, `tsconfig*.json`, `typedoc.json`
- **Keep**: `src/`, `tests/`, `CHANGELOG.md`, `LICENSE`, `package.json`, `README.md`, `jest.config.cjs`, `tsconfig*.json`, `typedoc.json`
- [Example PR](https://github.com/MetaMask/core/pull/1764)

### **[PR#9]** 4. Replace config files

- Update `tsconfig*.json`, `typedoc.json`, `jest.config.js` to extend from the corresponding files in the root directory by copying the contents of these files from other non-root packages.
- Update `tsconfig*.json`, `typedoc.json`, `jest.config.cjs` to extend from the corresponding files in the root directory by copying the contents of these files from other non-root packages.
- Preserve TypeScript compiler flags and its compilation target.
- Add tsconfig reference paths for non-root packages that are upstream dependencies of the migration target.
- Preserve Jest coverage threshold values.
Expand Down
2 changes: 1 addition & 1 deletion docs/processes/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Please follow the [MetaMask unit testing guidelines](https://github.com/MetaMask/contributor-docs/blob/main/docs/testing/unit-testing.md) when writing tests.

If you need to customize the behavior of Jest for a package, see `jest.config.js` within that package.
If you need to customize the behavior of Jest for a package, see `jest.config.cjs` within that package.

- Run `yarn workspace <workspaceName> run test` to run all tests for a package.
- Run `yarn workspace <workspaceName> run jest --no-coverage <file>` to run a test file within the context of a package.
Expand Down
7 changes: 2 additions & 5 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"count": 1
}
},
"packages/assets-controllers/jest.environment.js": {
"packages/assets-controllers/jest.environment.cjs": {
"n/prefer-global/text-decoder": {
"count": 1
},
Expand Down Expand Up @@ -500,7 +500,7 @@
"count": 25
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 1
"count": 2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

:( Oh well, not a big increase.

},
"no-negated-condition": {
"count": 1
Expand Down Expand Up @@ -1859,9 +1859,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 10
},
"@typescript-eslint/naming-convention": {
"count": 1
},
"@typescript-eslint/no-explicit-any": {
"count": 4
},
Expand Down
10 changes: 7 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const config = createConfig([
extends: [nodejs],
},
{
files: ['**/*.{js,cjs}'],
files: ['**/*.cjs'],
languageOptions: {
sourceType: 'script',
ecmaVersion: 2020,
Expand Down Expand Up @@ -152,6 +152,10 @@ const config = createConfig([
'jest/no-alias-methods': 'error',
'jest/no-commented-out-tests': 'error',
'jest/no-disabled-tests': 'error',

// `import { jest } from '@jest/globals'` is required in ESM test files
// and intentionally shadows the Jest-injected global.
'@typescript-eslint/no-shadow': ['error', { allow: ['jest'] }],
},
settings: {
node: {
Expand Down Expand Up @@ -192,14 +196,14 @@ const config = createConfig([
},
},
{
files: ['**/jest.environment.js'],
files: ['**/jest.environment.cjs'],
rules: {
// These files run under Node, and thus `require(...)` is expected.
'n/global-require': 'off',
},
},
{
files: ['**/*.mjs'],
files: ['**/*.js', '**/*.mjs'],
languageOptions: {
sourceType: 'module',
},
Expand Down
22 changes: 21 additions & 1 deletion jest.config.packages.js → jest.config.packages.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ module.exports = {
'<rootDir>/../../node_modules/@metamask/$1',
],
'^uuid$': require.resolve('uuid'),
// The sources import `lodash-es`, because `lodash` is CommonJS and its
Comment thread
Mrtenz marked this conversation as resolved.
// named exports cannot be imported from an ES module. The tests compile to
// CommonJS, where the reverse is true, so they are pointed back at
// `lodash`. The two have the same API.
'^lodash-es$': require.resolve('lodash'),
},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
Expand Down Expand Up @@ -190,7 +195,22 @@ module.exports = {
// testURL: "http://localhost",

// A map from regular expressions to paths to transformers
// transform: undefined,
// The packages are ESM, but Jest runs the tests as CommonJS: Jest only
// treats TypeScript as ESM when the extension is listed in
// `extensionsToTreatAsEsm`, so overriding the module settings here compiles
// the sources to CommonJS for tests without affecting the published build.
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: {
module: 'CommonJS',
moduleResolution: 'Node',
verbatimModuleSyntax: false,
},
},
],
},

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: undefined
Expand Down
9 changes: 9 additions & 0 deletions jest.config.scripts.js → jest.config.scripts.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ module.exports = {

preset: 'ts-jest',

// Unlike the packages, the scripts use `import.meta`, which has no CommonJS
Comment thread
mcmire marked this conversation as resolved.
// equivalent, so their tests run as ESM. Jest only treats TypeScript as ESM
// when the extension is listed here.
extensionsToTreatAsEsm: ['.ts', '.mts'],

transform: {
'^.+\\.m?tsx?$': ['ts-jest', { useESM: true }],
},

// "resetMocks" resets all mocks, including mocked modules, to jest.fn(),
// between each test case.
resetMocks: true,
Expand Down
12 changes: 6 additions & 6 deletions knip.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const config: KnipConfig = {
'scripts/**/*.{ts,js,sh}',
'tests/**/*.ts',
'*.config.{js,cjs,mjs,ts}',
'.prettierrc.js',
'.prettierrc.cjs',
],
project: ['scripts/**/*.ts', 'tests/**/*.ts', '*.{js,cjs,mjs,ts}'],
ignore: ['scripts/create-package/package-template/**'],
Expand Down Expand Up @@ -41,7 +41,7 @@ const config: KnipConfig = {
ignoreDependencies: [
'@metamask/controller-utils',
'@metamask/keyring-internal-api',
'lodash',
'lodash-es',
],
},
'packages/analytics-data-regulation-controller': {
Expand All @@ -66,7 +66,7 @@ const config: KnipConfig = {
ignoreDependencies: [
'@metamask/gas-fee-controller',
'@metamask/remote-feature-flag-controller',
'lodash',
'lodash-es',
'nock',
],
},
Expand Down Expand Up @@ -127,7 +127,7 @@ const config: KnipConfig = {
ignoreDependencies: [
'@metamask/base-controller',
'@metamask/superstruct',
'lodash',
'lodash-es',
],
},
'packages/multichain-network-controller': {
Expand Down Expand Up @@ -183,10 +183,10 @@ const config: KnipConfig = {
ignoreDependencies: ['cockatiel', 'nock'],
},
'packages/selected-network-controller': {
ignoreDependencies: ['immer', 'lodash', 'nock'],
ignoreDependencies: ['immer', 'lodash-es', 'nock'],
},
'packages/signature-controller': {
ignoreDependencies: ['lodash'],
ignoreDependencies: ['lodash-es'],
},
'packages/snap-account-service': {
ignoreDependencies: [
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
"packages/*"
],
"files": [],
"type": "module",
"scripts": {
"build": "yarn ts-bridge --project tsconfig.build.json --verbose",
"build": "yarn tsc --build tsconfig.build.json --verbose",
"build:clean": "yarn build:only-clean && yarn build",
"build:docs": "yarn workspaces foreach --all --no-private --parallel --interlaced --verbose run build:docs",
"build:only-clean": "rimraf -g 'packages/*/dist'",
"build:only-clean": "rimraf -g 'packages/*/dist' 'packages/*/tsconfig.build.tsbuildinfo'",
Comment thread
mcmire marked this conversation as resolved.
"build:types": "tsc --build tsconfig.build.json --verbose",
"changelog:merge": "tsx scripts/merge-changelog-conflicts.ts",
"changelog:update": "yarn workspaces foreach --all --no-private --parallel --interlaced --verbose run changelog:update",
Expand Down Expand Up @@ -54,14 +55,15 @@
"test": "yarn test:scripts --silent --collectCoverage=false --reporters=jest-silent-reporter && yarn test:scripts:shell && yarn test:packages",
"test:clean": "yarn workspaces foreach --all --parallel --verbose run test:clean && yarn test",
"test:packages": "yarn test:verbose --silent --collectCoverage=false --reporters=jest-silent-reporter",
"test:scripts": "NODE_OPTIONS=--experimental-vm-modules yarn jest --config ./jest.config.scripts.js --silent",
"test:scripts": "NODE_OPTIONS=--experimental-vm-modules yarn jest --config ./jest.config.scripts.cjs --silent",
"test:scripts:shell": "node_modules/bats/bin/bats scripts/*.bats",
"test:verbose": "yarn workspaces foreach --all --parallel --verbose run test:verbose",
"workspaces:list-versions": "./scripts/list-workspace-versions.sh"
},
"devDependencies": {
"@actions/core": "^3.0.1",
"@actions/github": "^9.1.1",
"@jest/globals": "^30.4.1",
"@lavamoat/allow-scripts": "^3.0.4",
"@lavamoat/preinstall-always-fail": "^2.1.0",
"@metamask/auto-changelog": "^6.1.0",
Expand All @@ -76,7 +78,6 @@
"@metamask/network-controller": "^36.0.0",
"@metamask/skills": "^0.1.0",
"@metamask/utils": "^11.12.0",
"@ts-bridge/cli": "^0.6.4",
"@types/jest": "^30.0.0",
"@types/lodash": "^4.14.191",
"@types/node": "^22.13.14",
Expand Down Expand Up @@ -111,6 +112,7 @@
"rimraf": "^5.0.5",
"semver": "^7.6.3",
"simple-git-hooks": "^2.8.0",
"ts-jest": "^29.4.11",
"tsx": "^4.20.5",
"typescript": "~5.3.3",
"typescript-eslint": "^8.48.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/account-tree-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **BREAKING:** Drop CommonJS support ([#9536](https://github.com/MetaMask/core/pull/9536))
- This package is now ESM-only, but can still be used in CommonJS projects via `require(esm)` in modern Node.js versions (22+), or dynamic imports in older Node.js versions.
- **BREAKING:** Bump minimum Node.js version to 22 ([#9976](https://github.com/MetaMask/core/pull/9976))

## [9.0.0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const merge = require('deepmerge');
const path = require('path');

const baseConfig = require('../../jest.config.packages');
const baseConfig = require('../../jest.config.packages.cjs');

const displayName = path.basename(__dirname);

Expand Down
23 changes: 9 additions & 14 deletions packages/account-tree-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,12 @@
"files": [
"dist/"
],
"type": "module",
"sideEffects": false,
"main": "./dist/index.cjs",
"types": "./dist/index.d.cts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
Comment on lines 24 to 27

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed import/require distinction to have Node.js resolve files regardless of whether it's running in ESM or CommonJS mode. This should work most of the time since require(esm) is possible now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we document this in the changelog as a breaking change?

"./package.json": "./package.json"
},
Expand All @@ -39,9 +32,11 @@
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
"build": "tsc --project tsconfig.build.json",
Comment thread
mcmire marked this conversation as resolved.
"build:all": "tsc --build tsconfig.build.json --verbose",
"build:clean": "yarn build:only-clean && yarn build",
"build:docs": "typedoc",
"build:only-clean": "rimraf './dist' './tsconfig.build.tsbuildinfo'",
"changelog:update": "../../scripts/update-changelog.sh @metamask/account-tree-controller",
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/account-tree-controller",
"lint:tsconfigs": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts",
Expand All @@ -68,17 +63,17 @@
"@metamask/superstruct": "^3.4.1",
"@metamask/utils": "^11.12.0",
"fast-deep-equal": "^3.1.3",
"lodash": "^4.17.21"
"lodash-es": "^4.17.21"
},
"devDependencies": {
"@metamask/account-api": "^2.0.0",
"@metamask/auto-changelog": "^6.1.0",
"@metamask/eth-hd-keyring": "^15.0.0",
"@metamask/providers": "^22.1.0",
"@ts-bridge/cli": "^0.6.4",
"@types/jest": "^30.0.0",
"deepmerge": "^4.2.2",
"jest": "^30.4.2",
"rimraf": "^5.0.5",
"ts-jest": "^29.4.11",
"tsx": "^4.20.5",
"typedoc": "^0.25.13",
Expand Down
2 changes: 2 additions & 0 deletions packages/accounts-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **BREAKING:** Drop CommonJS support ([#9536](https://github.com/MetaMask/core/pull/9536))
- This package is now ESM-only, but can still be used in CommonJS projects via `require(esm)` in modern Node.js versions (22+), or dynamic imports in older Node.js versions.
- **BREAKING:** Bump minimum Node.js version to 22 ([#9976](https://github.com/MetaMask/core/pull/9976))
- Bump `@metamask/utils` from `^11.11.0` to `^11.12.0` ([#10076](https://github.com/MetaMask/core/pull/10076))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const merge = require('deepmerge');
const path = require('path');

const baseConfig = require('../../jest.config.packages');
const baseConfig = require('../../jest.config.packages.cjs');

const displayName = path.basename(__dirname);

Expand Down
Loading
Loading