Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
bb41a72
Replace `ts-bridge` with `tsc` for building packages
Mrtenz Jul 16, 2026
8eee73b
Update package exports to ESM-only
Mrtenz Jul 16, 2026
f9e2997
Add `"type": "module"` to all packages
Mrtenz Jul 16, 2026
a841bc0
Add ESLint rules to enforce .js extensions in ESM imports
Mrtenz Jul 16, 2026
f40ea88
Replace `__dirname` with `import.meta.dirname` in all packages
Mrtenz Jul 16, 2026
775a62d
Convert Jest configuration to ESM
Mrtenz Jul 16, 2026
b80f805
Add `ts-jest` to root devDependencies
Mrtenz Jul 16, 2026
e8bad71
Work around TypeScript ESM named-import issue in messenger-cli
Mrtenz Jul 16, 2026
5e3bccb
Fix remaining `__dirname`
Mrtenz Jul 16, 2026
db128a5
Remove erroneous `uuid` entry from Jest `moduleNameMapper`
Mrtenz Jul 16, 2026
cf7ca0f
Fix ESLint errors for `build-utils`
Mrtenz Jul 16, 2026
4343a01
Fix ESLint errors for `controller-utils`
Mrtenz Jul 16, 2026
7a2f6ba
Fix ESLint errors for `messenger`
Mrtenz Jul 16, 2026
fe3f7b1
Fix ESLint errors for `base-controller`
Mrtenz Jul 16, 2026
2c84ab9
Fix ESLint errors for `json-rpc-engine`
Mrtenz Jul 16, 2026
0e95e7e
Fix ESLint errors for `storage-service`
Mrtenz Jul 16, 2026
fcbe888
Add `jest` global import to `build-utils` tests
Mrtenz Jul 16, 2026
3bdba17
Add `jest` global import to `controller-utils` tests
Mrtenz Jul 16, 2026
9e2a904
Add `jest` global import to `messenger` tests
Mrtenz Jul 16, 2026
a95af83
Add `jest` global import to `base-controller` tests
Mrtenz Jul 16, 2026
e36cc51
Add `jest` global import to `json-rpc-engine` tests
Mrtenz Jul 16, 2026
f29a716
Add `jest` global import to `storage-service` tests
Mrtenz Jul 16, 2026
8479da4
Add Jest custom resolver and fix ESM global import hoisting
Mrtenz Jul 16, 2026
e6ce384
Fix ESLint errors for `address-book-controller`
Mrtenz Jul 16, 2026
489cbb6
Add `jest` global import to `address-book-controller` tests
Mrtenz Jul 16, 2026
3d9fb9b
Fix ESLint errors for `ai-controllers`
Mrtenz Jul 16, 2026
41343a2
Fix ESLint errors for `analytics-controller`
Mrtenz Jul 16, 2026
03e54ea
Fix ESLint errors for `analytics-data-regulation-controller`
Mrtenz Jul 16, 2026
d68cc6c
Fix ESLint errors for `announcement-controller`
Mrtenz Jul 16, 2026
b4f46c7
Fix ESLint errors for `app-metadata-controller`
Mrtenz Jul 16, 2026
dbb7bde
Fix ESLint errors for `approval-controller`
Mrtenz Jul 16, 2026
2ef9fa6
Fix ESLint errors for `client-controller`
Mrtenz Jul 16, 2026
5459587
Fix ESLint errors for `compliance-controller`
Mrtenz Jul 16, 2026
6df564b
Fix ESLint errors for `connectivity-controller`
Mrtenz Jul 16, 2026
8ace21c
Fix ESLint errors for `geolocation-controller`
Mrtenz Jul 16, 2026
e4cccde
Add `jest` global import to `ai-controllers` tests
Mrtenz Jul 16, 2026
75a2c5d
Add `jest` global import to `analytics-controller` tests
Mrtenz Jul 16, 2026
6cde727
Add `jest` global import to `analytics-data-regulation-controller` tests
Mrtenz Jul 16, 2026
4ae40bd
Add `jest` global import to `approval-controller` tests
Mrtenz Jul 16, 2026
d71d8f2
Add `jest` global import to `compliance-controller` tests
Mrtenz Jul 16, 2026
693d412
Add `jest` global import to `connectivity-controller` tests
Mrtenz Jul 16, 2026
ec7583f
Add `jest` global import to `geolocation-controller` tests
Mrtenz Jul 16, 2026
4efa2db
Fix ESLint errors for `keyring-controller`
Mrtenz Jul 16, 2026
5edaca1
Fix ESLint errors for `logging-controller`
Mrtenz Jul 16, 2026
fa6a255
Fix ESLint errors for `message-manager`
Mrtenz Jul 16, 2026
fa3b360
Fix ESLint errors for `name-controller`
Mrtenz Jul 16, 2026
df90b8f
Fix ESLint errors for `passkey-controller`
Mrtenz Jul 16, 2026
be7623a
Fix ESLint errors for `preferences-controller`
Mrtenz Jul 16, 2026
eb5193d
Fix ESLint errors for `rate-limit-controller`
Mrtenz Jul 16, 2026
aa4da24
Fix ESLint errors for `remote-feature-flag-controller`
Mrtenz Jul 16, 2026
e6f0cef
Add `jest` global import to `keyring-controller` tests
Mrtenz Jul 16, 2026
0105398
Add `jest` global import to `logging-controller` tests
Mrtenz Jul 16, 2026
b09bb6c
Add `jest` global import to `message-manager` tests
Mrtenz Jul 16, 2026
faae17e
Add `jest` global import to `name-controller` tests
Mrtenz Jul 16, 2026
f6e99ce
Add `jest` global import to `passkey-controller` tests
Mrtenz Jul 16, 2026
bfc6ec5
Add `jest` global import to `rate-limit-controller` tests
Mrtenz Jul 16, 2026
e26e4a4
Add `jest` global import to `remote-feature-flag-controller` tests
Mrtenz Jul 16, 2026
80e97ae
Fix ESLint errors for `composable-controller`
Mrtenz Jul 16, 2026
85562f6
Fix ESLint errors for `eth-json-rpc-provider`
Mrtenz Jul 16, 2026
7194c68
Fix ESLint errors for `json-rpc-middleware-stream`
Mrtenz Jul 16, 2026
2eadbd9
Fix ESLint errors for `permission-log-controller`
Mrtenz Jul 16, 2026
55e9d7f
Fix ESLint errors for `base-data-service`
Mrtenz Jul 16, 2026
75847f8
Fix ESLint errors for `permission-controller`
Mrtenz Jul 16, 2026
19d7427
Add `jest` global import to batch 4 tests
Mrtenz Jul 16, 2026
cde2101
Add `jest` global import and fix import extensions in straggler files
Mrtenz Jul 16, 2026
c71bb38
ESLint fix and `jest` global import for eth-block-tracker
Mrtenz Jul 16, 2026
1d6d792
ESLint fix and `jest` global import for eip1193-permission-middleware
Mrtenz Jul 16, 2026
8a07be6
ESLint fix and `jest` global import for snap-account-service
Mrtenz Jul 16, 2026
709c259
ESLint fix and `jest` global import for chain-agnostic-permission
Mrtenz Jul 16, 2026
f9d1540
ESLint fix and `jest` global import for multichain-network-controller
Mrtenz Jul 16, 2026
0e7b579
ESLint fix and `jest` global import for network-controller
Mrtenz Jul 16, 2026
d519136
ESLint fix and `jest` global import for accounts-controller
Mrtenz Jul 16, 2026
f67e971
ESLint fix and `jest` global import for notification-services-controller
Mrtenz Jul 16, 2026
b029744
ESLint fix and `jest` global import for eip-5792-middleware
Mrtenz Jul 16, 2026
c121c89
ESLint fix and `jest` global import for shield-controller
Mrtenz Jul 16, 2026
4cc08de
ESLint fix and `jest` global import for smart-transactions-controller
Mrtenz Jul 16, 2026
ba8a94e
ESLint fix and `jest` global import for user-operation-controller
Mrtenz Jul 16, 2026
799f37b
ESLint fix and `jest` global import for transaction-controller
Mrtenz Jul 16, 2026
886d412
ESLint fix and `jest` global import for assets-controller
Mrtenz Jul 16, 2026
ca8d79c
ESLint fix and `jest` global import for assets-controllers
Mrtenz Jul 16, 2026
04d4c9f
ESLint fix and `jest` global import for bridge-controller
Mrtenz Jul 16, 2026
00c56c8
ESLint fix and `jest` global import for bridge-status-controller
Mrtenz Jul 16, 2026
205eb4a
ESLint fix and `jest` global import for signature-controller
Mrtenz Jul 16, 2026
32b18bc
ESLint fix and `jest` global import for transaction-pay-controller
Mrtenz Jul 16, 2026
5b30bb2
ESLint fix and `jest` global import for account-tree-controller
Mrtenz Jul 16, 2026
df9aec3
ESLint fix and `jest` global import for ens-controller
Mrtenz Jul 16, 2026
447119c
ESLint fix and `jest` global import for gas-fee-controller
Mrtenz Jul 16, 2026
9c340fb
ESLint fix and `jest` global import for polling-controller
Mrtenz Jul 16, 2026
1aa1f04
ESLint fix and `jest` global import for phishing-controller
Mrtenz Jul 16, 2026
ff4f243
ESLint fix and `jest` global import for selected-network-controller
Mrtenz Jul 16, 2026
99836a1
ESLint fix and `jest` global import for profile-sync-controller
Mrtenz Jul 16, 2026
368e3f3
ESLint fix and `jest` global import for multichain-transactions-contr…
Mrtenz Jul 16, 2026
058557c
ESLint fix and `jest` global import for multichain-account-service
Mrtenz Jul 16, 2026
4799bf3
ESLint fix and `jest` global import for authenticated-user-storage
Mrtenz Jul 16, 2026
7c2fb6f
ESLint fix and `jest` global import for chomp-api-service
Mrtenz Jul 16, 2026
6d300d5
ESLint fix and `jest` global import for claims-controller
Mrtenz Jul 16, 2026
0c4fc48
ESLint fix and `jest` global import for client-utils
Mrtenz Jul 16, 2026
d67c57c
ESLint fix and `jest` global import for delegation-controller
Mrtenz Jul 16, 2026
c38db11
ESLint fix and `jest` global import for earn-controller
Mrtenz Jul 16, 2026
4c04ef4
ESLint fix and `jest` global import for multichain-api-middleware
Mrtenz Jul 16, 2026
c37e2b0
ESLint fix and `jest` global import for eth-json-rpc-middleware
Mrtenz Jul 16, 2026
027dbfe
ESLint fix and `jest` global import for config-registry-controller
Mrtenz Jul 16, 2026
6d0a1cd
ESLint fix and `jest` global import for core-backend
Mrtenz Jul 16, 2026
7bfe880
ESLint fix and `jest` global import for gator-permissions-controller
Mrtenz Jul 16, 2026
0100581
ESLint fix and `jest` global import for network-connection-banner-con…
Mrtenz Jul 16, 2026
d81ae51
ESLint fix and `jest` global import for network-enablement-controller
Mrtenz Jul 16, 2026
cd3bf2a
ESLint fix and `jest` global import for perps-controller
Mrtenz Jul 16, 2026
e440eca
ESLint fix and `jest` global import for profile-metrics-controller
Mrtenz Jul 16, 2026
097a749
ESLint fix and `jest` global import for subscription-controller
Mrtenz Jul 16, 2026
ac52419
ESLint fix and `jest` global import for ramps-controller
Mrtenz Jul 16, 2026
0f23ead
ESLint fix and `jest` global import for sample-controllers
Mrtenz Jul 16, 2026
3a16f0b
ESLint fix and `jest` global import for seedless-onboarding-controller
Mrtenz Jul 16, 2026
6f00f88
ESLint fix and `jest` global import for social-controllers
Mrtenz Jul 16, 2026
a043a28
ESLint fix and `jest` global import for wallet
Mrtenz Jul 16, 2026
0d09c0a
ESLint fix and `jest` global import for money-account-controller
Mrtenz Jul 16, 2026
31bfd97
ESLint fix and `jest` global import for money-account-api-data-service
Mrtenz Jul 16, 2026
0d05ec1
ESLint fix and `jest` global import for money-account-balance-service
Mrtenz Jul 16, 2026
fca2931
ESLint fix and `jest` global import for money-account-upgrade-controller
Mrtenz Jul 16, 2026
8d147df
ESLint fix and `jest` global import for react-data-query
Mrtenz Jul 16, 2026
d1dee91
ESLint fix and `jest` global import for sentinel-api-service
Mrtenz Jul 16, 2026
ed0d6f1
ESLint fix and `jest` global import for eip-7702-internal-rpc-middleware
Mrtenz Jul 16, 2026
f80b3e9
ESLint fix and `jest` global import for local-node-utils
Mrtenz Jul 16, 2026
ac17817
ESLint fix and `jest` global import for messenger-cli
Mrtenz Jul 16, 2026
4ecef97
ESLint fix and `jest` global import for wallet-cli
Mrtenz Jul 16, 2026
e0f3e78
ESLint fix and `jest` global import for bitcoin-regtest-up
Mrtenz Jul 16, 2026
7f6ab79
ESLint fix and `jest` global import for foundryup
Mrtenz Jul 16, 2026
856c1ca
ESLint fix and `jest` global import for java-tron-up
Mrtenz Jul 16, 2026
1b5d227
ESLint fix and `jest` global import for platform-api-docs
Mrtenz Jul 16, 2026
f068c88
ESLint fix and `jest` global import for solana-test-validator-up
Mrtenz Jul 16, 2026
e1fd5b3
ESLint fix and `jest` global import for stellar-quickstart-up
Mrtenz Jul 16, 2026
468121f
ESLint fix and `jest` global import for create-package script
Mrtenz Jul 16, 2026
748e116
Fix .js import extensions and `isomorphic-fetch` hoisting in shared t…
Mrtenz Jul 16, 2026
d57ed28
Remove resolved suppressions from eslint-suppressions.json
Mrtenz Jul 16, 2026
3af1f68
ESM lint fixes: jest shadow, no-void, CJS unambiguous, JSON extensions
Mrtenz Jul 16, 2026
becbf55
Add `@jest/globals` to root devDependencies; prune resolved suppressions
Mrtenz Jul 16, 2026
bc7803a
patch: add `dist/esm/index.d.mts` to `@metamask/safe-event-emitter`
Mrtenz Jul 16, 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
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
diff --git a/dist/esm/index.d.mts b/dist/esm/index.d.mts
new file mode 100644
index 0000000000000000000000000000000000000000..d48ab7ade4e48f566f3ca48c60636368919b1044
--- /dev/null
+++ b/dist/esm/index.d.mts
@@ -0,0 +1,5 @@
+/// <reference types="node" />
+import { EventEmitter } from 'events';
+export default class SafeEventEmitter extends EventEmitter {
+ emit(type: string, ...args: any[]): boolean;
+}
diff --git a/package.json b/package.json
index 87ca2f6363c43d2f9d45be268e8ba03c1669c02c..72211f17fe3976ef8dac7d8512d60a6de1275fbd 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"exports": {
".": {
"import": {
- "types": "./dist/esm/index.d.ts",
+ "types": "./dist/esm/index.d.mts",
"default": "./dist/esm/index.mjs"
},
"require": {
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
40 changes: 1 addition & 39 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 7
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 1
},
"no-negated-condition": {
"count": 3
},
Expand Down Expand Up @@ -251,9 +248,6 @@
"packages/assets-controllers/src/DeFiPositionsController/DeFiPositionsController.ts": {
"@typescript-eslint/explicit-function-return-type": {
"count": 2
},
"@typescript-eslint/no-misused-promises": {
"count": 2
}
},
"packages/assets-controllers/src/DeFiPositionsController/group-defi-positions.ts": {
Expand Down Expand Up @@ -289,9 +283,6 @@
}
},
"packages/assets-controllers/src/MultichainBalancesController/MultichainBalancesController.ts": {
"@typescript-eslint/no-misused-promises": {
"count": 1
},
"no-restricted-syntax": {
"count": 2
}
Expand All @@ -311,12 +302,6 @@
"@typescript-eslint/naming-convention": {
"count": 5
},
"@typescript-eslint/no-misused-promises": {
"count": 2
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 6
},
"@typescript-eslint/prefer-optional-chain": {
"count": 1
},
Expand Down Expand Up @@ -475,9 +460,6 @@
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"@typescript-eslint/prefer-optional-chain": {
"count": 3
},
"id-length": {
"count": 1
},
Expand Down Expand Up @@ -601,9 +583,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 25
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 1
},
"no-negated-condition": {
"count": 1
}
Expand Down Expand Up @@ -1288,9 +1267,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 1
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 2
},
"id-denylist": {
"count": 1
}
Expand Down Expand Up @@ -1377,9 +1353,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 4
},
"@typescript-eslint/no-misused-promises": {
"count": 2
},
"no-restricted-syntax": {
"count": 1
}
Expand Down Expand Up @@ -1739,9 +1712,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 4
},
"@typescript-eslint/prefer-nullish-coalescing": {
"count": 4
},
"id-length": {
"count": 2
},
Expand Down Expand Up @@ -2105,9 +2075,6 @@
"@typescript-eslint/explicit-function-return-type": {
"count": 7
},
"@typescript-eslint/no-base-to-string": {
"count": 1
},
"@typescript-eslint/no-unused-vars": {
"count": 2
},
Expand All @@ -2131,7 +2098,7 @@
"count": 10
},
"@typescript-eslint/no-floating-promises": {
"count": 4
"count": 3
},
"no-restricted-syntax": {
"count": 4
Expand Down Expand Up @@ -2240,11 +2207,6 @@
"count": 2
}
},
"packages/transaction-pay-controller/src/strategy/bridge/bridge-submit.ts": {
"no-restricted-syntax": {
"count": 1
}
},
"packages/transaction-pay-controller/src/strategy/relay/hyperliquid-withdraw.ts": {
"no-restricted-syntax": {
"count": 1
Expand Down
50 changes: 49 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import base, { createConfig } from '@metamask/eslint-config';
import jest from '@metamask/eslint-config-jest';
import nodejs from '@metamask/eslint-config-nodejs';
import typescript from '@metamask/eslint-config-typescript';
import node from 'eslint-plugin-n';

const NODE_LTS_VERSION = 22;

Expand Down Expand Up @@ -94,6 +95,9 @@ const config = createConfig([
// Handled by Oxfmt.
'prettier/prettier': 'off',
'import-x/order': 'off',
// Allow `void somePromise()` to explicitly mark ignored promises
// (required by `no-floating-promises`).
'no-void': ['error', { allowAsStatement: true }],
},
},
{
Expand Down Expand Up @@ -125,7 +129,7 @@ const config = createConfig([
{
files: ['**/*.{js,cjs}'],
languageOptions: {
sourceType: 'script',
sourceType: 'module',
ecmaVersion: 2020,
},
},
Expand Down Expand Up @@ -179,6 +183,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 @@ -218,6 +226,19 @@ const config = createConfig([
'n/hashbang': 'off',
},
},
{
files: [
'**/*.cjs',
'**/.prettierrc.js',
'**/.eslintrc.js',
'**/jest.config*.js',
'**/jest.environment.js',
],
rules: {
// CJS config files have no import/export statements.
'import-x/unambiguous': 'off',
},
},
{
files: ['**/jest.environment.js'],
rules: {
Expand Down Expand Up @@ -373,6 +394,33 @@ const config = createConfig([
'n/no-process-env': 'off',
},
},

// ESM-specific configuration. We should port this to
// `@metamask/eslint-config` at some point.
{
plugins: { n: node },
rules: {
// `import-x/extensions` doesn't support using ".js" for TypeScript
// files(?), so we load the `n` plugin and use
// `n/file-extension-in-import` instead.
'n/file-extension-in-import': ['error', 'always'],
'import-x/extensions': [
'error',
{
js: 'ignorePackages',
ts: 'never',
tsx: 'never',
json: 'always',
},
],
'import-x/no-useless-path-segments': [
'error',
{
noUselessIndex: false,
},
],
},
},
]);

export default config;
36 changes: 22 additions & 14 deletions jest.config.packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@
* https://jestjs.io/docs/configuration
*/

module.exports = {
import { fileURLToPath } from 'node:url';
import { createDefaultEsmPreset } from 'ts-jest';

const presetConfig = createDefaultEsmPreset({
tsconfig: '<rootDir>/tsconfig.json',
});

const config = {
...presetConfig,

// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down Expand Up @@ -77,20 +86,17 @@ module.exports = {
// ],

// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// Here we ensure that Jest resolves `@metamask/*` imports to the uncompiled source code for packages that live in this repo.
// NOTE: This must be synchronized with the `paths` option in `tsconfig.base.json`.
// NOTE: Monorepo `@metamask/*` packages are resolved to TypeScript source by `jest.resolver.cjs`.
// External `@metamask/*` packages are resolved by Jest's default resolver, which honours `exports` fields.
// NOTE: The `'^(\\..+)\\.js$'` entry must be synchronized with the `paths` option in `tsconfig.base.json`.
moduleNameMapper: {
'^(\\..+)\\.js$': '$1',
'^@metamask/json-rpc-engine/v2$': [
'<rootDir>/../json-rpc-engine/src/v2/index.ts',
],
'^@metamask/utils/node$': require.resolve('@metamask/utils/node'),
'^@metamask/(.+)$': [
'<rootDir>/../$1/src',
// Some @metamask/* packages we are referencing aren't in this monorepo,
// so in that case use their published versions
'<rootDir>/../../node_modules/@metamask/$1',
],
'^uuid$': require.resolve('uuid'),
'^@metamask/utils/node$': fileURLToPath(
import.meta.resolve('@metamask/utils/node'),
),
},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
Expand All @@ -103,11 +109,11 @@ module.exports = {
// notifyMode: "failure-change",

// A preset that is used as a base for Jest's configuration
preset: 'ts-jest',
// preset: 'ts-jest',

// The path to the Prettier executable used to format snapshots
// Jest doesn't support Prettier 3 yet, so we use Prettier 2
prettierPath: require.resolve('prettier-2'),
prettierPath: fileURLToPath(import.meta.resolve('prettier-2')),

// Run tests from one or more projects
// projects: undefined
Expand All @@ -123,7 +129,7 @@ module.exports = {
// resetModules: false,

// A path to a custom resolver
// resolver: undefined,
resolver: '../../jest.resolver.cjs',

// "restoreMocks" restores all mocks created using jest.spyOn to their
// original implementations, between each test. It does not affect mocked
Expand Down Expand Up @@ -208,3 +214,5 @@ module.exports = {
// Whether to use watchman for file crawling
// watchman: true,
};

export default config;
43 changes: 43 additions & 0 deletions jest.resolver.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const { join, resolve } = require('path');
const { existsSync, statSync } = require('fs');

const REPO_ROOT = resolve(__dirname);
const PACKAGES_DIR = join(REPO_ROOT, 'packages');

/**
* Custom Jest resolver that redirects `@metamask/*` imports to monorepo source
* when the package exists locally, and falls back to default resolution (which
* honours the package `exports` field) for external packages.
*
* Without this, the `moduleNameMapper` fallback returns a directory path for
* external `@metamask/*` packages. Jest then uses `main` (CJS) rather than
* `exports.import` (ESM), causing class-inheritance failures at runtime.
*
* @param {string} moduleName - The module name to resolve.
* @param {object} options - Jest resolver options including `defaultResolver`.
* @returns {string} The resolved module path.
*/
module.exports = function resolver(moduleName, options) {
const { defaultResolver } = options;

const match = /^@metamask\/([^/]+)(\/.*)?$/u.exec(moduleName);
if (match) {
const [, pkgName, subPath = ''] = match;
const srcDir = join(PACKAGES_DIR, pkgName, 'src');
// eslint-disable-next-line n/no-sync
if (existsSync(srcDir)) {
let target = subPath ? join(srcDir, subPath) : join(srcDir, 'index.ts');
// If the resolved target is a directory, look for its index file.
// eslint-disable-next-line n/no-sync
if (existsSync(target) && statSync(target).isDirectory()) {
target = join(target, 'index.ts');
}
return defaultResolver(target, options);
}
}

// External package — use default resolver, which honours `exports` fields.
return defaultResolver(moduleName, options);
};
Loading
Loading